-
Notifications
You must be signed in to change notification settings - Fork 43
Added fixes and tweaks #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
62f3ad8
462e6d5
26b5c54
16e6c5a
30785d3
a9e147f
f90ca83
fc41b6a
994b059
9879fe8
ad61357
571cba6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| *.code-workspace | ||
| .vscode |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| {"rule":"MORFOLOGIK_RULE_EN_US","sentence":"^\\QThe script can coerce them to be MediaType:HDD\nThe entire virtual drive is added to the system as a single large volume\nYou need at least\n1 SSD and 1 HDD to run cached storage / Simple resiliency\n2 SSD and 2 HDDs to run cached storage / Mirror resiliency /\n1 SSD and 2 HDDs to run cached storage / Simple resiliency / striped storage (sum of HDD space)\\E$"} | ||
| {"rule":"ENGLISH_WORD_REPEAT_RULE","sentence":"^\\QSimple Mirrored Mirrored and Striped\\E$"} | ||
| {"rule":"MASS_AGREEMENT","sentence":"^\\QThe HDD drive media types are not recognized.\\E$"} | ||
| {"rule":"MORFOLOGIK_RULE_EN_US","sentence":"^\\QCredits\nMost of the script came from this great blog article by Nils Schimmelmann\nSee Joe's blog for any updates\\E$"} | ||
| {"rule":"MORFOLOGIK_RULE_EN_US","sentence":"^\\QResiliancyName: Simple vs Mirror\nThe “Mirror” resiliency level attempts to mirror both SSD and HDD tiers, so you would need 4 drives run mirror, to mirror both tiers\\E$"} | ||
| {"rule":"MORFOLOGIK_RULE_EN_US","sentence":"^\\QRemove-TieredStorageSpace.ps1\nRemoves the virtual drive, the storage tiers and then the storage pool.\\E$"} | ||
| {"rule":"MORFOLOGIK_RULE_EN_US","sentence":"^\\QScripts\nNew-TieredStorageSpace.ps1\nCreates a tiered storage pool and allocates all the disk space to a single drive\nYou can change the drive letter and label by editing the variables at the top.\\E$"} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,167 @@ | ||
| # RUN AS ADMINISTRATOR | ||
| # https://nils.schimmelmann.us/post/153541254987/intel-smart-response-technology-vs-windows-10 | ||
| #Tested with one SSD and two HDD | ||
| #Requires -RunAsAdministrator | ||
|
|
||
| [CmdletBinding()] | ||
| param ( | ||
| [Parameter(Mandatory = $False, ValueFromPipeline = $True)] | ||
| [string[]] | ||
| $ConfigFile | ||
| ) | ||
|
|
||
| Begin{ | ||
| #Initialize Variables | ||
| $Script:StorageSpacesParams = @() | ||
| #Makes $PhysicalDisks a hashtable for easier management. | ||
| $PhysicalDisks = @() | ||
| $Script:TieredDiskName | ||
|
|
||
|
|
||
| function defaultPrompt { | ||
| if ($null -eq $ConfigFile) { | ||
| $DefaultPrompt = Read-Host = "Would you like to load the default values to the config file? (Y/N)" | ||
|
|
||
| if ($DefaultPrompt.ToUpper() -eq "Y" ) { | ||
| $Script:StorageSpacesParams = setDefaultValues | ||
| $Script:StorageSpacesParams | ConvertTo-Json | Out-File $PSScriptRoot + "\TieredStorageSpace-Config.json" | ||
| } | ||
| elseif ($DefaultPrompt.ToUpper() -eq "N") { | ||
| Read-Host "Ether pass the config file to the script or use default values. Exiting..." | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "Ether" should be "Either" |
||
| Exit | ||
| } | ||
| else { | ||
| Write-Output "Invalid Selection. Try Again." | ||
| defaultPrompt | ||
| } | ||
| } | ||
| if ($null -ne $ConfigFile) { | ||
| #This will load all values from the $ConfigFile var to $Script:StorageSpacesParams. | ||
| $PSversion = $PSVersionTable.PSVersion.Major | ||
| if ($PSversion -le "5") { | ||
| $ConfigObj = $ConfigFile | ConvertFrom-Json | ||
| foreach ($obj in ($ConfigObj.StorageSpace | Get-Member * -MemberType NoteProperty).Name) { | ||
| $Script:StorageSpacesParams =+ $($ConfigObj.StorageSpace.$obj) | ||
| } | ||
|
|
||
| } | ||
| elseif ($PSversion -ge "6") { | ||
| $Script:StorageSpacesParams = $ConfigFile | ConvertFrom-Json -AsHashtable | ||
| } | ||
| else { | ||
| Read-Host "Invalid PS Version. Exiting..." | ||
| Exit | ||
| } | ||
|
|
||
| } | ||
| } | ||
| function setDefaultValues { | ||
| @{ | ||
| #Pool that will suck in all drives | ||
| StoragePoolFriendlyName = "My Storage Pool" | ||
| #Virtual Disk Name made up of disks in both tiers | ||
| TieredDiskName = "My Tiered VirtualDisk" | ||
| #Simple = striped. Mirror only works if both can mirror AFIK | ||
| #https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/dn387076(v=ws.11) | ||
| DriveTierResiliency = "Simple" | ||
| #Change to suit - drive later and the label name | ||
| DriveLetter = "Z" | ||
| NewFileSystemLabel = "StorageDrive" | ||
| #Override the default sizing here - useful if have two different size SSDs or HDDs - set to smallest of pair | ||
| #These must be Equal or smaller than the disk size available in that tier SSD and HDD | ||
| #SSD:cache - HDD:data | ||
| #set to null so copy/paste to command prompt doesn't have previous run values | ||
| SSDTierSize = $null | ||
| HDDTierSize = $null | ||
| #Drives cannot always be fully allocated - probably broken for drives < 10GB | ||
| UsableSpace = 0.98 # I had an issue with 0.99, so I lowered it to 0.98. | ||
freemansoft marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| #Tiers in the storage pool | ||
| SSDTierName = "SSDTier" | ||
| HDDTierName = "HDDTier" | ||
| #Uncomment and put your HDD type here if it shows up as unspecified with "Get-PhysicalDisk -CanPool $True | ||
| # If your HDDs show up as Unspecified instead of HDD | ||
| UseUnspecifiedDriveIsHDD = "$True" | ||
| } | ||
| } | ||
| function loadValuesFromParamsToVariables { | ||
| [CmdletBinding()] | ||
| param ( | ||
| [Parameter()] | ||
| [TypeName] | ||
| $ParameterName | ||
| ) | ||
|
|
||
| $Script:StorageSpacesParams | ||
|
|
||
| } | ||
|
|
||
| defaultPrompt | ||
| loadValuesFromParamsToVariables | ||
| } | ||
|
|
||
| #TODO: Write a pester test. | ||
|
|
||
| Process { | ||
| #List all disks that can be pooled and output in table format (format-table) | ||
| Get-PhysicalDisk -CanPool $True | Format-Table FriendlyName, OperationalStatus, Size, MediaType | ||
|
|
||
|
|
||
| #TODO: Create selectable options to fine tune what disks are selected. | ||
|
|
||
| #Store all physical disks that can be pooled into a variable, $PhysicalDisks | ||
| # This assumes you want all raw / unpartitioned disks to end up in your pool - | ||
| # Add a clause like the example with your drive name to stop that drive from being included | ||
| # Example " | Where FriendlyName -NE "ATA LITEONIT LCS-256" | ||
| if ($null -ne $UseUnspecifiedDriveIsHDD) { | ||
| Get-PhysicalDisk -CanPool $True | Where-Object MediaType -eq Unspecified | Set-PhysicalDisk -MediaType HDD | ||
| # show the type changed | ||
| Get-PhysicalDisk -CanPool $True | Format-Table FriendlyName, OperationalStatus, Size, MediaType | ||
| } | ||
| $PhysicalDisks = (Get-PhysicalDisk -CanPool $True | Where-Object MediaType -NE UnSpecified) | ||
| if ($null -eq $PhysicalDisks) { | ||
| throw "Abort! No physical Disks available" | ||
| } | ||
|
|
||
| #Create a new Storage Pool using the disks in variable $PhysicalDisks with a name of My Storage Pool | ||
| $SubSysName = (Get-StorageSubSystem).FriendlyName | ||
| New-StoragePool -PhysicalDisks $PhysicalDisks -StorageSubSystemFriendlyName $SubSysName -FriendlyName $StoragePoolName | ||
| #View the disks in the Storage Pool just created | ||
| Get-StoragePool -FriendlyName $StoragePoolName | Get-PhysicalDisk | Select-Object FriendlyName, MediaType | ||
|
|
||
| #Set the number of columns used for each resiliency - This setting assumes you have at least 2-SSD and 2-HDD | ||
| # Get-StoragePool $StoragePoolName | Set-ResiliencySetting -Name Simple -NumberOfColumnsDefault 2 | ||
| # Get-StoragePool $StoragePoolName | Set-ResiliencySetting -Name Mirror -NumberOfColumnsDefault 1 | ||
|
|
||
| #Create two tiers in the Storage Pool created. One for SSD disks and one for HDD disks | ||
| $SSDTier = New-StorageTier @StorageSpacesParams -FriendlyName $SSDTierName -MediaType SSD | ||
| $HDDTier = New-StorageTier @StorageSpacesParams -FriendlyName $HDDTierName -MediaType HDD | ||
|
|
||
| #Calculate tier sizes within this storage pool | ||
| #Can override by setting sizes at top | ||
| if ($null -eq $SSDTierSize) { | ||
| $SSDTierSize = (Get-StorageTierSupportedSize -FriendlyName $SSDTierName -ResiliencySettingName $DriveTierResiliency).TierSizeMax | ||
| $SSDTierSize = [int64]($SSDTierSize * $UsableSpace) | ||
| } | ||
| if ($null -eq $HDDTierSize) { | ||
| $HDDTierSize = (Get-StorageTierSupportedSize -FriendlyName $HDDTierName -ResiliencySettingName $DriveTierResiliency).TierSizeMax | ||
| $HDDTierSize = [int64]($HDDTierSize * $UsableSpace) | ||
| } | ||
| Write-Output "TierSizes: ( $SSDTierSize , $HDDTierSize )" | ||
|
|
||
| # you can end up with different number of columns in SSD - Ex: With Simple 1SSD and 2HDD could end up with SSD-1Col, HDD-2Col | ||
| New-VirtualDisk @StorageSpacesParams -FriendlyName $TieredDiskName -StorageTiers @($SSDTier, $HDDTier) -StorageTierSizes @($SSDTierSize, $HDDTierSize) @StorageSpacesParams -AutoWriteCacheSize -AutoNumberOfColumns | ||
|
|
||
| # initialize the disk, format and mount as a single volume | ||
| Write-Output "Preparing volume..." | ||
| Get-VirtualDisk $TieredDiskName | Get-Disk | Initialize-Disk -PartitionStyle GPT | ||
| # This will be Partition 2. Storage pool metadata is in Partition 1 | ||
| Get-VirtualDisk $TieredDiskName | Get-Disk | New-Partition @StorageSpacesParams -UseMaximumSize | ||
| Initialize-Volume -FileSystem NTFS -Confirm:$false @StorageSpacesParams | ||
| Get-Volume @StorageSpacesParams | ||
| } | ||
|
|
||
| End{ | ||
| Write-Output "Operation complete." | ||
|
|
||
| Clear-Variable StorageSpacesParams -Scope Script | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,11 @@ | ||
| # Create Storage Spaces in Windows 10 | ||
|
|
||
| <!--TODO: Update README documrntaion to match new scripts usage. /---> | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. documrntation should be "documentation". |
||
|
|
||
| # Create Tiered Storage Spaces in Windows 10 | ||
| Windows Server O/S contains Storage Spaces support for Server Spaces tiered storage. | ||
| You can front slower spinning disks with smaller faster SSDs. | ||
| Windows 10 has a Storage Spaces GUI Control Panel that does not include the tiered storage GUI. | ||
| This means Powershell must be used for all configuration. | ||
| This means PowerShell must be used for all configuration. | ||
|
|
||
|  | ||
|
|
||
|
|
@@ -13,28 +16,28 @@ This means Powershell must be used for all configuration. | |
| * The entire virtual drive is added to the system as a single large volume | ||
| * You need at least | ||
| * 1 SSD and 1 HDD to run cached storage / Simple resiliency | ||
| * 2 SSD and 2 HDD to run cached storage / Mirror resiliency / | ||
| * 1 SSD and 2 HDD to run cached storage / Simple resiliency / striped storage (sum of HDD space) | ||
| * 2 SSD and 2 HDDs to run cached storage / Mirror resiliency / | ||
| * 1 SSD and 2 HDDs to run cached storage / Simple resiliency / striped storage (sum of HDD space) | ||
|
|
||
|    | ||
|
|
||
| # Scripts | ||
| ## new-storage-space.ps1 | ||
| ## New-TieredStorageSpace.ps1 | ||
| Creates a tiered storage pool and allocates all the disk space to a single drive | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add a line here or at the top that tells us how to run the script with the external configuration file? |
||
| * You can change the drive letter and label by editing the variables at the top. | ||
| * the script can auto size the drive and cache. That didn't work for me so the script supports manual sizing. | ||
| * The script can auto size the drive and cache. That didn't work for me, so the script supports manual sizing. | ||
|
|
||
| ## remove-storage-space | ||
| ## Remove-TieredStorageSpace.ps1 | ||
| Removes the virtual drive, the storage tiers and then the storage pool. | ||
| * All drives are returned the _Primordial_ pool | ||
| * All drives are returned the _Primordial_ pool. | ||
|
|
||
| # Sample configuration | ||
| *new-storage-space.ps* created a Virtual drive from 3 physical drives | ||
|
|
||
| | Physical Drives | Storage Space Virtual Drive| | ||
| |-----------------|-----------------------------| | ||
| | two 2TB HDD | single 3.6TB data volume _striped_ across my two HDD | | ||
| | one 200GB SSD. | with a 200GB read/write cache | | ||
| | Two 2 TB HDD | Single 3.6 TB data volume _striped_ across my two HDD | | ||
| | One 200 GB SSD. | With a 200 GB read/write cache. | | ||
|
|
||
|  | ||
|
|
||
|
|
@@ -45,10 +48,10 @@ The control panel does not display or manipulate tiers | |
|
|
||
|
|
||
| ## ResiliancyName: Simple vs Mirror | ||
| The "Mirror" resiliency level attempts to mirror both SSD and HDD tiers so you would need 4 drives run mirror, to mirror both tiers | ||
| The “Mirror” resiliency level attempts to mirror both SSD and HDD tiers, so you would need 4 drives run mirror, to mirror both tiers | ||
|
|
||
| ## Caching Impact Benchmark | ||
| All Storage Pool drives connected to 3Gb/s SATA. The write-back cache is not used with sequential writes over 256KB | ||
| All Storage Pool drives connected to 3Gb/s SATA. The write-back cache is not used with sequential writes over 256 KB. | ||
|
|
||
| ``` | ||
| [Read] *Single 2TB no cache* *Two 2TB mirrored with 200GB cache* | ||
|
|
@@ -67,7 +70,7 @@ Sequential 1MiB (Q= 1, T= 1): 154.147 MB/s [ 147.0 IOPS] 230.149 MB/s [ | |
|
|
||
| ## Example state | ||
| ### Before script | ||
| Three drives can pool. The HDD drive media types are not recognized | ||
| Three drives can pool. The HDD drive media types are not recognized. | ||
| ``` | ||
| PS C:\WINDOWS\system32> Get-PhysicalDisk | ||
| Number FriendlyName SerialNumber MediaType CanPool OperationalStatus HealthStatus Usage Size | ||
|
|
@@ -112,4 +115,4 @@ My Tiered VirtualDisk OK | |
|
|
||
| # Credits | ||
| * Most of the script came from this great [blog article by Nils Schimmelmann](https://nils.schimmelmann.us/post/153541254987/intel-smart-response-technology-vs-windows-10) | ||
| * See [joe's blog](https://joe.blog.freemansoft.com) for any updates | ||
| * See [Joe's blog](https://joe.blog.freemansoft.com) for any updates | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| { | ||
| "StorageSpace":[ | ||
| { | ||
| "StoragePoolFriendlyName" : "My Storage Pool" | ||
| }, | ||
| { | ||
| "TieredDiskName": "My Tiered VirtualDisk" | ||
| }, | ||
| { | ||
| "ResiliencySettingName": "Simple" | ||
| }, | ||
| { | ||
| "DriveLetter": "Z" | ||
| }, | ||
| { | ||
| "NewFileSystemLabel": "StorageDrive" | ||
| }, | ||
| { | ||
| "SSDTierSize": "$null" | ||
| }, | ||
| { | ||
| "HDDTierSize": "$null" | ||
| }, | ||
| { | ||
| "UsableSpace": "0.98" | ||
| }, | ||
| { | ||
| "UseUnspecifiedDriveIsHDD": "$True" | ||
| }, | ||
| { | ||
| "SSDTierName": "SSDTier" | ||
| }, | ||
| { | ||
| "HDDTierName": "HDDTier" | ||
| } | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| This directory was intended to support creating virtual drives that could be mounted into a VM and appear as if they were phsical disks | ||
| This directory was intended to support creating virtual drives that could be mounted into a VM and appear as if they were physical disks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this going to save defaults to a config file or load them from a config file. I'm not sure from the prompt.