From 62f3ad854abf190acdd6ac57c099fffa5f3a8890 Mon Sep 17 00:00:00 2001 From: Ryan Hutchison Date: Fri, 19 Feb 2021 00:57:54 -0600 Subject: [PATCH 01/12] Fixed alais usage, added TODOs for modification. --- Storage-Spaces-Config.json | 0 new-storage-space.ps1 | 52 +++++++++++++++++++++++++++----------- remove-storage-space.ps1 | 2 ++ 3 files changed, 39 insertions(+), 15 deletions(-) create mode 100644 Storage-Spaces-Config.json diff --git a/Storage-Spaces-Config.json b/Storage-Spaces-Config.json new file mode 100644 index 0000000..e69de29 diff --git a/new-storage-space.ps1 b/new-storage-space.ps1 index 70e3ff7..ce46d95 100644 --- a/new-storage-space.ps1 +++ b/new-storage-space.ps1 @@ -1,15 +1,21 @@ # 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 + + #TODO: Allow a config file ingestion for varibles. Maybe use json? + + #TODO: Set default variables to null and make the global. + + #TODO: Write a pester test. +function defaults { #Pool that will suck in all drives $StoragePoolName = "My Storage Pool" -#Tiers in the storage pool -$SSDTierName = "SSDTier" -$HDDTierName = "HDDTier" + #Virtual Disk Name made up of disks in both tiers $TieredDiskName = "My Tiered VirtualDisk" + #TODO: Set selectable $DriveTierResiliency. #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" @@ -25,27 +31,43 @@ $TieredDriveLabel = "StorageDrive" $SSDTierSize = $null $HDDTierSize = $null #Drives cannot always be fully allocated - probably broken for drives < 10GB -$UsableSpace = 0.99 +$UsableSpace = 0.98 # I had an issue with 0.99, so I lowered it to 0.98. + #TODO: Write defauls to config file for injestion for script use. +} + #TODO: Add prompt to load global variable defaults. + #TODO: Make interactive prompt for global varibles set to $null. + +#Makes $PhysicalDisks an array for easier management. +$PhysicalDisks = @() + +#Tiers in the storage pool +$SSDTierName = "SSDTier" +$HDDTierName = "HDDTier" + +defaults + + #TODO: Covert $UseUnspecifiedDriveIsHDD to a default varible option. #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 = "Yes" #List all disks that can be pooled and output in table format (format-table) -Get-PhysicalDisk -CanPool $True | ft FriendlyName, OperationalStatus, Size, MediaType +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 ($UseUnspecifiedDriveIsHDD -ne $null){ - $DisksToChange = (Get-PhysicalDisk -CanPool $True | where MediaType -eq Unspecified) - Get-PhysicalDisk -CanPool $True | where MediaType -eq Unspecified | Set-PhysicalDisk -MediaType HDD + Get-PhysicalDisk -CanPool $True | Where-Object MediaType -eq Unspecified | Set-PhysicalDisk -MediaType HDD # show the type changed - Get-PhysicalDisk -CanPool $True | ft FriendlyName, OperationalStatus, Size, MediaType + Get-PhysicalDisk -CanPool $True | Format-Table FriendlyName, OperationalStatus, Size, MediaType } -$PhysicalDisks = (Get-PhysicalDisk -CanPool $True | Where MediaType -NE UnSpecified) -if ($PhysicalDisks -eq $null){ +$PhysicalDisks = (Get-PhysicalDisk -CanPool $True | Where-Object MediaType -NE UnSpecified) +if ($null -eq $PhysicalDisks){ throw "Abort! No physical Disks available" } @@ -53,7 +75,7 @@ if ($PhysicalDisks -eq $null){ $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 FriendlyName, MediaType +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 @@ -65,11 +87,11 @@ $HDDTier = New-StorageTier -StoragePoolFriendlyName $StoragePoolName -FriendlyNa #Calculate tier sizes within this storage pool #Can override by setting sizes at top -if ($SSDTierSize -eq $null){ +if ($null -eq $SSDTierSize){ $SSDTierSize = (Get-StorageTierSupportedSize -FriendlyName $SSDTierName -ResiliencySettingName $DriveTierResiliency).TierSizeMax $SSDTierSize = [int64]($SSDTierSize * $UsableSpace) } -if ($HDDTierSize -eq $null){ +if ($null -eq $HDDTierSize){ $HDDTierSize = (Get-StorageTierSupportedSize -FriendlyName $HDDTierName -ResiliencySettingName $DriveTierResiliency).TierSizeMax $HDDTierSize = [int64]($HDDTierSize * $UsableSpace) } @@ -79,7 +101,7 @@ Write-Output "TierSizes: ( $SSDTierSize , $HDDTierSize )" New-VirtualDisk -StoragePoolFriendlyName $StoragePoolName -FriendlyName $TieredDiskName -StorageTiers @($SSDTier, $HDDTier) -StorageTierSizes @($SSDTierSize, $HDDTierSize) -ResiliencySettingName $DriveTierResiliency -AutoWriteCacheSize -AutoNumberOfColumns # initialize the disk, format and mount as a single volume -Write-Output "preparing 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 -DriveLetter $TieredDriveLetter -UseMaximumSize diff --git a/remove-storage-space.ps1 b/remove-storage-space.ps1 index c7aa2f3..8c08351 100644 --- a/remove-storage-space.ps1 +++ b/remove-storage-space.ps1 @@ -4,6 +4,8 @@ $SSDTierName = "SSDTier" $HDDTierName = "HDDTier" $TieredDiskName = "My Tiered VirtualDisk" +#TODO: Config file ingestion. + # Make sure they really want to do this! $choices = '&Yes', '&No' $decision = $Host.UI.PromptForChoice('Remove Storage Space', 'Are you sure you wish to remove the storage space named "' + $TieredDiskName + '"?' + [Environment]::NewLine + 'ALL DATA WILL BE PERMANENTLY LOST', $choices, 1) From 462e6d5010ef70fdf656d0e91f8607e3eb8052c0 Mon Sep 17 00:00:00 2001 From: Ryan Hutchison Date: Fri, 19 Feb 2021 01:04:19 -0600 Subject: [PATCH 02/12] Script update and fixed README.md errors. --- .vscode/ltex.hiddenFalsePositives.en-US.txt | 4 ++++ README.md | 22 ++++++++++----------- remove-storage-space.ps1 | 14 ++++++------- 3 files changed, 22 insertions(+), 18 deletions(-) create mode 100644 .vscode/ltex.hiddenFalsePositives.en-US.txt diff --git a/.vscode/ltex.hiddenFalsePositives.en-US.txt b/.vscode/ltex.hiddenFalsePositives.en-US.txt new file mode 100644 index 0000000..ef1ca9a --- /dev/null +++ b/.vscode/ltex.hiddenFalsePositives.en-US.txt @@ -0,0 +1,4 @@ +{"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$"} diff --git a/README.md b/README.md index 332c74e..0e60c49 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ 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. ![Physical Disks](./images_folder/physical-disks.png) @@ -13,8 +13,8 @@ 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) ![Simple](./images_folder/simple.png) ![Mirrored](./images_folder/mirror-simple.png) ![Mirrored and Striped](./images_folder/mirror-stripe.png) @@ -22,19 +22,19 @@ This means Powershell must be used for all configuration. ## new-storage-space.ps1 Creates a tiered storage pool and allocates all the disk space to a single drive * 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 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. | ![Simple resiliency with striped drives](./images_folder/stripe-simple.png) @@ -45,10 +45,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 +67,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 +112,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 \ No newline at end of file +* See [Joe's blog](https://joe.blog.freemansoft.com) for any updates \ No newline at end of file diff --git a/remove-storage-space.ps1 b/remove-storage-space.ps1 index 8c08351..4337682 100644 --- a/remove-storage-space.ps1 +++ b/remove-storage-space.ps1 @@ -14,7 +14,7 @@ if ($decision -ne 0) { } # In reverse order of creation -if ((Get-VirtualDisk -FriendlyName $TieredDiskName) -ne $null){ +if ($null -ne (Get-VirtualDisk -FriendlyName $TieredDiskName)){ Write-Output "Removing drive: $TieredDiskName" Get-VirtualDisk -FriendlyName $TieredDiskName Remove-virtualdisk -friendlyName $TieredDiskName -Confirm:$false @@ -23,16 +23,16 @@ if ((Get-VirtualDisk -FriendlyName $TieredDiskName) -ne $null){ } # Remove Storage Tier -if ((Get-StorageTier -FriendlyName $HDDTierName) -ne $null){ +if ($null -ne (Get-StorageTier -FriendlyName $HDDTierName)){ Write-Output "Removing storage tiers: $HDDTierName" - Get-StorageTier -FriendlyName $HDDTierName | FT FriendlyName, MediaType, Size -AutoSize + Get-StorageTier -FriendlyName $HDDTierName | Format-Table FriendlyName, MediaType, Size -AutoSize Remove-StorageTier -FriendlyName $HDDTierName -Confirm:$false } else { Write-Output "Tier does not exist: $HDDTierName" } -if ((Get-StorageTier -FriendlyName $SSDTierName) -ne $null){ +if ($null -ne (Get-StorageTier -FriendlyName $SSDTierName)){ Write-Output "Removing storage tiers: $SSDTierName" - Get-StorageTier -FriendlyName $SSDTierName | FT FriendlyName, MediaType, Size -AutoSize + Get-StorageTier -FriendlyName $SSDTierName | Format-Table FriendlyName, MediaType, Size -AutoSize Remove-StorageTier -FriendlyName $SSDTierName -Confirm:$false } else { Write-Output "Tier does not exist: $SSDTierName" @@ -40,9 +40,9 @@ if ((Get-StorageTier -FriendlyName $SSDTierName) -ne $null){ Get-StorageTier # Remove the Storage Pool -if ((Get-StoragePool -FriendlyName $StoragePoolName) -ne $null){ +if ($null -ne (Get-StoragePool -FriendlyName $StoragePoolName)){ Write-Output "Removing storage pool: $StoragePoolName" - Get-StoragePool -FriendlyName $StoragePoolName | Get-PhysicalDisk | FT FriendlyName, MediaType + Get-StoragePool -FriendlyName $StoragePoolName | Get-PhysicalDisk | Format-Table FriendlyName, MediaType Remove-StoragePool -FriendlyName $StoragePoolName -Confirm:$false } else { Write-Output "Storage Pool does not exist: $StoragePoolName" From 26b5c54d8e1dce734c0874f3a927429f29a75912 Mon Sep 17 00:00:00 2001 From: Ryan Hutchison Date: Fri, 19 Feb 2021 01:06:11 -0600 Subject: [PATCH 03/12] Typo fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0e60c49..c4e2a60 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Creates a tiered storage pool and allocates all the disk space to a single drive * 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. -## remove-storage-space +## remove-storage-space.ps1 Removes the virtual drive, the storage tiers and then the storage pool. * All drives are returned the _Primordial_ pool. From 16e6c5a15eca652071427cf85a6545fc09527f54 Mon Sep 17 00:00:00 2001 From: Ryan Hutchison Date: Fri, 19 Feb 2021 10:25:43 -0600 Subject: [PATCH 04/12] Renamed scripts --- new-storage-space.ps1 => New-TiredStorageSpace.ps1 | 0 README.md | 6 +++--- remove-storage-space.ps1 => Remove-TiredStorageSpace.ps1 | 0 3 files changed, 3 insertions(+), 3 deletions(-) rename new-storage-space.ps1 => New-TiredStorageSpace.ps1 (100%) rename remove-storage-space.ps1 => Remove-TiredStorageSpace.ps1 (100%) diff --git a/new-storage-space.ps1 b/New-TiredStorageSpace.ps1 similarity index 100% rename from new-storage-space.ps1 rename to New-TiredStorageSpace.ps1 diff --git a/README.md b/README.md index c4e2a60..c9bd025 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Create Storage Spaces in Windows 10 +# 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. @@ -19,12 +19,12 @@ This means PowerShell must be used for all configuration. ![Simple](./images_folder/simple.png) ![Mirrored](./images_folder/mirror-simple.png) ![Mirrored and Striped](./images_folder/mirror-stripe.png) # Scripts -## new-storage-space.ps1 +## New-TiredStorageSpace.ps1 Creates a tiered storage pool and allocates all the disk space to a single drive * 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. -## remove-storage-space.ps1 +## Remove-TiredStorageSpace.ps1 Removes the virtual drive, the storage tiers and then the storage pool. * All drives are returned the _Primordial_ pool. diff --git a/remove-storage-space.ps1 b/Remove-TiredStorageSpace.ps1 similarity index 100% rename from remove-storage-space.ps1 rename to Remove-TiredStorageSpace.ps1 From 30785d353e52ae5db63cc8e505ceec94c83183d1 Mon Sep 17 00:00:00 2001 From: Ryan Hutchison Date: Fri, 19 Feb 2021 10:38:44 -0600 Subject: [PATCH 05/12] Added gitignore file --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1bb4614 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.code-workspace \ No newline at end of file From a9e147f23cffbc6986a286802af99fa6ecb988f1 Mon Sep 17 00:00:00 2001 From: Ryan Hutchison Date: Fri, 19 Feb 2021 11:38:17 -0600 Subject: [PATCH 06/12] Fixed file name typo and partially added defauls --- ...ageSpace.ps1 => New-TieredStorageSpace.ps1 | 83 +++++++++++++------ README.md | 4 +- ...Space.ps1 => Remove-TieredStorageSpace.ps1 | 0 Storage-Spaces-Config.json | 32 +++++++ 4 files changed, 91 insertions(+), 28 deletions(-) rename New-TiredStorageSpace.ps1 => New-TieredStorageSpace.ps1 (70%) rename Remove-TiredStorageSpace.ps1 => Remove-TieredStorageSpace.ps1 (100%) diff --git a/New-TiredStorageSpace.ps1 b/New-TieredStorageSpace.ps1 similarity index 70% rename from New-TiredStorageSpace.ps1 rename to New-TieredStorageSpace.ps1 index ce46d95..758e2f2 100644 --- a/New-TiredStorageSpace.ps1 +++ b/New-TieredStorageSpace.ps1 @@ -3,54 +3,85 @@ #Tested with one SSD and two HDD #Requires -RunAsAdministrator + + +[CmdletBinding()] +param ( + [Parameter()] + [string[]] + $ConfigFile +) + +$StorageSpacesParams = @() +#Makes $PhysicalDisks a hashtable for easier management. +$PhysicalDisks = @() + #TODO: Allow a config file ingestion for varibles. Maybe use json? #TODO: Set default variables to null and make the global. #TODO: Write a pester test. -function defaults { -#Pool that will suck in all drives -$StoragePoolName = "My Storage Pool" -#Virtual Disk Name made up of disks in both tiers -$TieredDiskName = "My Tiered VirtualDisk" + 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" ) { + + } + elseif ($DefaultPrompt.ToUpper() -eq "N") { + + } + else { + Write-Output "Invalid Selection." + DefaultPrompt + } + } + if ($null -ne $ConfigFile) { + + } + } + +DefaultPrompt +function defaults { + $StorageSpacesParams = @{ + #Pool that will suck in all drives + StoragePoolName = "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 + TieredDriveLetter = "Z" + TieredDriveLabel = "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. + } #TODO: Set selectable $DriveTierResiliency. -#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 -$TieredDriveLetter = "Z" -$TieredDriveLabel = "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. + #TODO: Write defauls to config file for injestion for script use. } #TODO: Add prompt to load global variable defaults. #TODO: Make interactive prompt for global varibles set to $null. -#Makes $PhysicalDisks an array for easier management. -$PhysicalDisks = @() + #Tiers in the storage pool $SSDTierName = "SSDTier" $HDDTierName = "HDDTier" -defaults - #TODO: Covert $UseUnspecifiedDriveIsHDD to a default varible option. #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 = "Yes" +$UseUnspecifiedDriveIsHDD = "$True" #List all disks that can be pooled and output in table format (format-table) Get-PhysicalDisk -CanPool $True | Format-Table FriendlyName, OperationalStatus, Size, MediaType diff --git a/README.md b/README.md index c9bd025..5d34645 100644 --- a/README.md +++ b/README.md @@ -19,12 +19,12 @@ This means PowerShell must be used for all configuration. ![Simple](./images_folder/simple.png) ![Mirrored](./images_folder/mirror-simple.png) ![Mirrored and Striped](./images_folder/mirror-stripe.png) # Scripts -## New-TiredStorageSpace.ps1 +## New-TieredStorageSpace.ps1 Creates a tiered storage pool and allocates all the disk space to a single drive * 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. -## Remove-TiredStorageSpace.ps1 +## Remove-TieredStorageSpace.ps1 Removes the virtual drive, the storage tiers and then the storage pool. * All drives are returned the _Primordial_ pool. diff --git a/Remove-TiredStorageSpace.ps1 b/Remove-TieredStorageSpace.ps1 similarity index 100% rename from Remove-TiredStorageSpace.ps1 rename to Remove-TieredStorageSpace.ps1 diff --git a/Storage-Spaces-Config.json b/Storage-Spaces-Config.json index e69de29..cc6e2cd 100644 --- a/Storage-Spaces-Config.json +++ b/Storage-Spaces-Config.json @@ -0,0 +1,32 @@ +{ + "StorageSpace":[ + { + "StoragePoolName" : "" + }, + { + "TieredDiskName": "" + }, + + { + "DriveTierResiliency": "" + }, + { + "TieredDriveLetter": "" + }, + { + "TieredDriveLabel": "" + }, + { + "SSDTierSize": "" + }, + { + "HDDTierSize": "" + }, + { + "UsableSpace": "" + }, + { + "UseUnspecifiedDriveIsHDD": "True" + } +] +} \ No newline at end of file From f90ca83dfa6f5382b655beb62ae0a2b1285edb32 Mon Sep 17 00:00:00 2001 From: Ryan Hutchison Date: Fri, 19 Feb 2021 12:12:20 -0600 Subject: [PATCH 07/12] Renamed Vars for splat, splatted and test files --- .vscode/ltex.hiddenFalsePositives.en-US.txt | 3 ++ New-TieredStorageSpace.Tests.ps1 | 0 New-TieredStorageSpace.ps1 | 46 ++++++++++++--------- Remove-TieredStorageSpace.Tests.ps1 | 0 Storage-Spaces-Config.json | 25 +++++++---- 5 files changed, 45 insertions(+), 29 deletions(-) create mode 100644 New-TieredStorageSpace.Tests.ps1 create mode 100644 Remove-TieredStorageSpace.Tests.ps1 diff --git a/.vscode/ltex.hiddenFalsePositives.en-US.txt b/.vscode/ltex.hiddenFalsePositives.en-US.txt index ef1ca9a..9569d9f 100644 --- a/.vscode/ltex.hiddenFalsePositives.en-US.txt +++ b/.vscode/ltex.hiddenFalsePositives.en-US.txt @@ -2,3 +2,6 @@ {"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$"} diff --git a/New-TieredStorageSpace.Tests.ps1 b/New-TieredStorageSpace.Tests.ps1 new file mode 100644 index 0000000..e69de29 diff --git a/New-TieredStorageSpace.ps1 b/New-TieredStorageSpace.ps1 index 758e2f2..5e67c8a 100644 --- a/New-TieredStorageSpace.ps1 +++ b/New-TieredStorageSpace.ps1 @@ -12,7 +12,7 @@ param ( $ConfigFile ) -$StorageSpacesParams = @() +$Global:StorageSpacesParams = @() #Makes $PhysicalDisks a hashtable for easier management. $PhysicalDisks = @() @@ -29,7 +29,7 @@ $PhysicalDisks = @() } elseif ($DefaultPrompt.ToUpper() -eq "N") { - + setDefaultValues } else { Write-Output "Invalid Selection." @@ -42,18 +42,18 @@ $PhysicalDisks = @() } DefaultPrompt -function defaults { +function setDefaultValues { $StorageSpacesParams = @{ #Pool that will suck in all drives - StoragePoolName = "My Storage Pool" + 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 - TieredDriveLetter = "Z" - TieredDriveLabel = "StorageDrive" + 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 @@ -62,23 +62,27 @@ function defaults { 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. + #Tiers in the storage pool + SSDTierName = "SSDTier" + HDDTierName = "HDDTier" + } +} + function loadValuesFromParamsToVaribles { + } + + #TODO: Set selectable $DriveTierResiliency. #TODO: Write defauls to config file for injestion for script use. -} + #TODO: Add prompt to load global variable defaults. #TODO: Make interactive prompt for global varibles set to $null. - - -#Tiers in the storage pool -$SSDTierName = "SSDTier" -$HDDTierName = "HDDTier" - #TODO: Covert $UseUnspecifiedDriveIsHDD to a default varible option. + #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" @@ -113,8 +117,8 @@ Get-StoragePool -FriendlyName $StoragePoolName | Get-PhysicalDisk | Select-Objec # 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 -StoragePoolFriendlyName $StoragePoolName -FriendlyName $SSDTierName -MediaType SSD -$HDDTier = New-StorageTier -StoragePoolFriendlyName $StoragePoolName -FriendlyName $HDDTierName -MediaType HDD +$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 @@ -129,14 +133,16 @@ if ($null -eq $HDDTierSize){ 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 -StoragePoolFriendlyName $StoragePoolName -FriendlyName $TieredDiskName -StorageTiers @($SSDTier, $HDDTier) -StorageTierSizes @($SSDTierSize, $HDDTierSize) -ResiliencySettingName $DriveTierResiliency -AutoWriteCacheSize -AutoNumberOfColumns +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 -DriveLetter $TieredDriveLetter -UseMaximumSize -Initialize-Volume -DriveLetter $TieredDriveLetter -FileSystem NTFS -Confirm:$false -NewFileSystemLabel $TieredDriveLabel -Get-Volume -DriveLetter $TieredDriveLetter +Get-VirtualDisk $TieredDiskName | Get-Disk | New-Partition @StorageSpacesParams -UseMaximumSize +Initialize-Volume -FileSystem NTFS -Confirm:$false @StorageSpacesParams +Get-Volume @StorageSpacesParams + +Write-Output "Operation complete" -Write-Output "Operation complete" \ No newline at end of file +Clear-Variable StorageSpacesParams -Scope Global \ No newline at end of file diff --git a/Remove-TieredStorageSpace.Tests.ps1 b/Remove-TieredStorageSpace.Tests.ps1 new file mode 100644 index 0000000..e69de29 diff --git a/Storage-Spaces-Config.json b/Storage-Spaces-Config.json index cc6e2cd..06b950b 100644 --- a/Storage-Spaces-Config.json +++ b/Storage-Spaces-Config.json @@ -1,32 +1,39 @@ { "StorageSpace":[ { - "StoragePoolName" : "" + "StoragePoolFriendlyName" : "" }, { "TieredDiskName": "" }, - { - "DriveTierResiliency": "" + "ResiliencySettingName": "" + }, + { + "DriveLetter": "" }, { - "TieredDriveLetter": "" + "NewFileSystemLabel": "" }, { - "TieredDriveLabel": "" + "SSDTierSize": "$null" }, { - "SSDTierSize": "" + "HDDTierSize": "$null" }, { - "HDDTierSize": "" + "UsableSpace": "0.98" }, { - "UsableSpace": "" + "UseUnspecifiedDriveIsHDD": "$True" }, { - "UseUnspecifiedDriveIsHDD": "True" + "SSDTierName": "SSDTier" + }, + { + "HDDTierName": "HDDTier" } + + ] } \ No newline at end of file From fc41b6a6d6d7d2cfc11dc81afcbf63deb6a4ff57 Mon Sep 17 00:00:00 2001 From: Ryan Hutchison Date: Fri, 19 Feb 2021 12:14:24 -0600 Subject: [PATCH 08/12] Renamed Config File --- Storage-Spaces-Config.json => TieredStorageSpace-Config.json | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Storage-Spaces-Config.json => TieredStorageSpace-Config.json (100%) diff --git a/Storage-Spaces-Config.json b/TieredStorageSpace-Config.json similarity index 100% rename from Storage-Spaces-Config.json rename to TieredStorageSpace-Config.json From 994b059f5c0e602a6306458e93646cb0a51a6634 Mon Sep 17 00:00:00 2001 From: Ryan Hutchison Date: Fri, 19 Feb 2021 12:54:51 -0600 Subject: [PATCH 09/12] Added defaults to config file + Begin, Proc, End --- New-TieredStorageSpace.ps1 | 205 +++++++++++++++++---------------- TieredStorageSpace-Config.json | 10 +- VM-Support/README.md | 2 +- 3 files changed, 114 insertions(+), 103 deletions(-) diff --git a/New-TieredStorageSpace.ps1 b/New-TieredStorageSpace.ps1 index 5e67c8a..1095a22 100644 --- a/New-TieredStorageSpace.ps1 +++ b/New-TieredStorageSpace.ps1 @@ -7,33 +7,30 @@ [CmdletBinding()] param ( - [Parameter()] + [Parameter(Mandatory = $False, ValueFromPipeline = $True)] [string[]] $ConfigFile ) -$Global:StorageSpacesParams = @() -#Makes $PhysicalDisks a hashtable for easier management. -$PhysicalDisks = @() +Begin{ - #TODO: Allow a config file ingestion for varibles. Maybe use json? + $Script:StorageSpacesParams = @() + #Makes $PhysicalDisks a hashtable for easier management. + $PhysicalDisks = @() - #TODO: Set default variables to null and make the global. - - #TODO: Write a pester test. - - function DefaultPrompt { + 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") { - setDefaultValues + } else { - Write-Output "Invalid Selection." - DefaultPrompt + Write-Output "Invalid Selection." + defaultPrompt } } if ($null -ne $ConfigFile) { @@ -41,35 +38,51 @@ $PhysicalDisks = @() } } -DefaultPrompt -function setDefaultValues { - $StorageSpacesParams = @{ - #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. - #Tiers in the storage pool - SSDTierName = "SSDTier" - HDDTierName = "HDDTier" + defaultPrompt + 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. + #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 loadValuesFromParamsToVaribles { + [CmdletBinding()] + param ( + [Parameter()] + $StorageSpacesParams + ) } +} + + #TODO: Allow a config file ingestion for varibles. + + + #TODO: Write a pester test. + + @@ -81,68 +94,66 @@ function setDefaultValues { #TODO: Make interactive prompt for global varibles set to $null. - #TODO: Covert $UseUnspecifiedDriveIsHDD to a default varible option. - -#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" - -#List all disks that can be pooled and output in table format (format-table) -Get-PhysicalDisk -CanPool $True | Format-Table FriendlyName, OperationalStatus, Size, MediaType +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 ($UseUnspecifiedDriveIsHDD -ne $null){ - 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) + #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 } -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 Global \ No newline at end of file +Clear-Variable StorageSpacesParams -Scope Global +} \ No newline at end of file diff --git a/TieredStorageSpace-Config.json b/TieredStorageSpace-Config.json index 06b950b..5895f5e 100644 --- a/TieredStorageSpace-Config.json +++ b/TieredStorageSpace-Config.json @@ -1,19 +1,19 @@ { "StorageSpace":[ { - "StoragePoolFriendlyName" : "" + "StoragePoolFriendlyName" : "My Storage Pool" }, { - "TieredDiskName": "" + "TieredDiskName": "My Tiered VirtualDisk" }, { - "ResiliencySettingName": "" + "ResiliencySettingName": "Simple" }, { - "DriveLetter": "" + "DriveLetter": "Z" }, { - "NewFileSystemLabel": "" + "NewFileSystemLabel": "StorageDrive" }, { "SSDTierSize": "$null" diff --git a/VM-Support/README.md b/VM-Support/README.md index 385ad19..5452a26 100644 --- a/VM-Support/README.md +++ b/VM-Support/README.md @@ -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 \ No newline at end of file +This directory was intended to support creating virtual drives that could be mounted into a VM and appear as if they were physical disks \ No newline at end of file From 9879fe8c89649a0af411bc9c86f1f6825f41dc5a Mon Sep 17 00:00:00 2001 From: Ryan Hutchison Date: Wed, 24 Feb 2021 19:41:46 -0600 Subject: [PATCH 10/12] Comments and Fromatting --- .gitignore | 3 +- New-TieredStorageSpace.ps1 | 54 +++++++++++++++++++++------------- Remove-TieredStorageSpace.ps1 | 3 ++ TieredStorageSpace-Config.json | 4 +-- 4 files changed, 40 insertions(+), 24 deletions(-) diff --git a/.gitignore b/.gitignore index 1bb4614..6fa6570 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -*.code-workspace \ No newline at end of file +*.code-workspace +.vscode \ No newline at end of file diff --git a/New-TieredStorageSpace.ps1 b/New-TieredStorageSpace.ps1 index 1095a22..bed8997 100644 --- a/New-TieredStorageSpace.ps1 +++ b/New-TieredStorageSpace.ps1 @@ -13,32 +13,50 @@ param ( ) Begin{ - + #Initilize 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..." + Exit } else { - Write-Output "Invalid Selection." + 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 + } } } - - defaultPrompt function setDefaultValues { @{ #Pool that will suck in all drives @@ -67,32 +85,27 @@ Begin{ UseUnspecifiedDriveIsHDD = "$True" } } - function loadValuesFromParamsToVaribles { + function loadValuesFromParamsToVariables { [CmdletBinding()] param ( [Parameter()] - $StorageSpacesParams + [TypeName] + $ParameterName ) + $Script:StorageSpacesParams + } + + defaultPrompt + loadValuesFromParamsToVariables } #TODO: Allow a config file ingestion for varibles. + #TODO: Write a pester test. - #TODO: Write a pester test. - - - - - - #TODO: Set selectable $DriveTierResiliency. - - #TODO: Write defauls to config file for injestion for script use. - - #TODO: Add prompt to load global variable defaults. - - #TODO: Make interactive prompt for global varibles set to $null. + #TODO: Write defaults to config file for ingestion for script use. Process { #List all disks that can be pooled and output in table format (format-table) @@ -100,6 +113,7 @@ Process { #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 diff --git a/Remove-TieredStorageSpace.ps1 b/Remove-TieredStorageSpace.ps1 index 4337682..cbc231f 100644 --- a/Remove-TieredStorageSpace.ps1 +++ b/Remove-TieredStorageSpace.ps1 @@ -1,3 +1,6 @@ +#TODO: Adapt to new format. + +#Requires -RunAsAdministrator #Variables names here MUST MATCH create-storage-space.ps1 $StoragePoolName = "My Storage Pool" $SSDTierName = "SSDTier" diff --git a/TieredStorageSpace-Config.json b/TieredStorageSpace-Config.json index 5895f5e..46392be 100644 --- a/TieredStorageSpace-Config.json +++ b/TieredStorageSpace-Config.json @@ -33,7 +33,5 @@ { "HDDTierName": "HDDTier" } - - -] + ] } \ No newline at end of file From ad61357276c237b82c9601995d76f2e251216125 Mon Sep 17 00:00:00 2001 From: Ryan Hutchison Date: Wed, 24 Feb 2021 20:13:15 -0600 Subject: [PATCH 11/12] Managing TODOs --- New-TieredStorageSpace.ps1 | 10 ++-------- README.md | 3 +++ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/New-TieredStorageSpace.ps1 b/New-TieredStorageSpace.ps1 index bed8997..2f8a11d 100644 --- a/New-TieredStorageSpace.ps1 +++ b/New-TieredStorageSpace.ps1 @@ -3,8 +3,6 @@ #Tested with one SSD and two HDD #Requires -RunAsAdministrator - - [CmdletBinding()] param ( [Parameter(Mandatory = $False, ValueFromPipeline = $True)] @@ -101,12 +99,8 @@ Begin{ loadValuesFromParamsToVariables } - #TODO: Allow a config file ingestion for varibles. - #TODO: Write a pester test. - #TODO: Write defaults to config file for ingestion for script use. - 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 @@ -167,7 +161,7 @@ Process { } End{ -Write-Output "Operation complete" +Write-Output "Operation complete." -Clear-Variable StorageSpacesParams -Scope Global +Clear-Variable StorageSpacesParams -Scope Script } \ No newline at end of file diff --git a/README.md b/README.md index 5d34645..4a7996d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ + + + # 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. From 571cba6d9c296d2bb5de803271e0fa74c497c2e3 Mon Sep 17 00:00:00 2001 From: Ryan Hutchison Date: Wed, 16 Mar 2022 18:36:07 -0500 Subject: [PATCH 12/12] Removed Test Scripts and fixed typo --- New-TieredStorageSpace.Tests.ps1 | 0 New-TieredStorageSpace.ps1 | 2 +- Remove-TieredStorageSpace.Tests.ps1 | 0 3 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 New-TieredStorageSpace.Tests.ps1 delete mode 100644 Remove-TieredStorageSpace.Tests.ps1 diff --git a/New-TieredStorageSpace.Tests.ps1 b/New-TieredStorageSpace.Tests.ps1 deleted file mode 100644 index e69de29..0000000 diff --git a/New-TieredStorageSpace.ps1 b/New-TieredStorageSpace.ps1 index 2f8a11d..05e1c52 100644 --- a/New-TieredStorageSpace.ps1 +++ b/New-TieredStorageSpace.ps1 @@ -11,7 +11,7 @@ param ( ) Begin{ - #Initilize Variables + #Initialize Variables $Script:StorageSpacesParams = @() #Makes $PhysicalDisks a hashtable for easier management. $PhysicalDisks = @() diff --git a/Remove-TieredStorageSpace.Tests.ps1 b/Remove-TieredStorageSpace.Tests.ps1 deleted file mode 100644 index e69de29..0000000