Step-by-Step for Mirrored Storage Spaces Resiliency using PowerShell

 
0 - Overview

 

This blog post is a walkthrough of the resiliency offered by Storage Spaces when using mirrored spaces.
For this exercise we have a single virtual machine with multiple data disks used to create the spaces.
The idea is to simulate a number of different failure and recovery scenarios, reviewing the behavior.
It includes the procedure to replace a disk and repair a degraded Space.

Notes and disclaimers:

  • Obviously, putting all virtual disks on a single physical disk won't provide real resiliency.
  • The specific Storage Spaces configuration shown in this blog post is not supported. Microsoft Support will only answer questions and assist in troubleshooting configurations where Storage Spaces uses a physical machine (not a VM) and uses one of the certified JBOD hardware solutions (see https://www.windowsservercatalog.com/results.aspx?bCatID=1573&cpID=0&avc=10&OR=1)
  • Because of the two items above, the configuration described here should only be used for demos, testing or learning environments.

 

1 - Two-way mirror with 3 disks

 

Part 1 of this post focuses on testing the resiliency of a two-way mirrored virtual disk (storage space) on a storage pool with 3 physical disks.
For each section you have the steps to perform (useful if you want to cut/paste), the actual output of the cmdlets on my test system and finally some notes explaining what happened.

 

1.1 - Attach 3 disks to a VM

 

Steps to perform on the host:

 

1..3 | % { New-VHD –Path D:demodisk$_.VHDX –Dynamic –SizeBytes 20GB } | Out-Null

1..3 | % { Add-VMHardDiskDrive –VMName VM2 –Path D:demodisk$_.VHDX -ControllerType SCSI}

Get-VMHardDiskDrive -VMName VM2

 

Output:

 

PS C:> 1..3 | % { New-VHD –Path D:demodisk$_.VHDX –Dynamic –SizeBytes 20GB } | Out-Null

PS C:> 1..3 | % { Add-VMHardDiskDrive –VMName VM2 –Path D:demodisk$_.VHDX -ControllerType SCSI}

PS C:> Get-VMHardDiskDrive -VMName VM2

 

VMName ControllerType ControllerNumber ControllerLocation DiskNumber Path

------ -------------- ---------------- ------------------ ---------- ----

VM2 IDE 0 0 c:demov2.vhdx

VM2 SCSI 0 0 D:demodisk1.VHDX

VM2 SCSI 0 1 D:demodisk2.VHDX

VM2 SCSI 0 2 D:demodisk3.VHDX

 

Notes:

 

Nothing much. Just your regular VM with 1 IDE boot disk and 3 SCSI data disks.

 

1.2 - Create pool and mirrored space

 

Steps to perform on the guest:

 

$s = Get-StorageSubSystem -FriendlyName *Spaces*

$d = Get-PhysicalDisk -CanPool $true
New-StoragePool -FriendlyName Pool1 -StorageSubSystemFriendlyName $s.FriendlyName -PhysicalDisks $d
$p = Get-StoragePool Pool1
Set-ResiliencySetting -StoragePool $p -Name Mirror -NumberofColumnsDefault 1 -NumberOfDataCopiesDefault 2
$p | New-VirtualDisk -FriendlyName Space1 -ResiliencySettingName Mirror –UseMaximumSize

 

$L ="X”
$N = (Get-VirtualDisk -FriendlyName Space1 | Get-Disk).Number
Set-Disk -Number $N -IsReadOnly 0
Set-Disk -Number $N -IsOffline 0
Initialize-Disk -Number $N -PartitionStyle MBR
New-Partition -DiskNumber $N -DriveLetter $L -UseMaximumSize 
Start-Sleep –Seconds 10
Initialize-Volume -DriveLetter $L -FileSystem NTFS -Confirm:$false

 

Output:

 

PS C:> $s = Get-StorageSubSystem -FriendlyName *Spaces*

PS C:> $d = Get-PhysicalDisk -CanPool $true

PS C:> New-StoragePool -FriendlyName Pool1 -StorageSubSystemFriendlyName $s.FriendlyName -PhysicalDisks $d

 

FriendlyName OperationalStatus HealthStatus IsPrimordial IsReadOnly

------------ ----------------- ------------ ------------ ----------

Pool1 OK Healthy False False

 

PS C:> $p = Get-StoragePool Pool1

PS C:> Set-ResiliencySetting -StoragePool $p -Name Mirror -NumberofColumnsDefault 1 -NumberOfDataCopiesDefault 2

PS C:> $p | New-VirtualDisk -FriendlyName Space1 -ResiliencySettingName Mirror –UseMaximumSize

 

FriendlyName ResiliencySettingNa OperationalStatus HealthStatus IsManualAttach Size

                    me

------------ ------------------- ----------------- ------------ -------------- ----

Space1 Mirror OK Healthy False 27 GB

 

PS C:> $L ="X”

PS C:> $N = (Get-VirtualDisk -FriendlyName Space1 | Get-Disk).Number

PS C:> Set-Disk -Number $N -IsReadOnly 0

PS C:> Set-Disk -Number $N -IsOffline 0

PS C:> Initialize-Disk -Number $N -PartitionStyle MBR

PS C:> New-Partition -DiskNumber $N -DriveLetter $L -UseMaximumSize

 

   Disk Number: 4

 

PartitionNumber DriveLetter Offset Size Type

--------------- ----------- ------ ---- ----

1 X 1048576 27 GB Logical

 

PS C:> Start-Sleep –Seconds 10

PS C:> Initialize-Volume -DriveLetter $L -FileSystem NTFS -Confirm:$false

 

DriveLetter FileSystemLabel FileSystem DriveType HealthStatus SizeRemaining Size

----------- --------------- ---------- --------- ------------ ------------- ----

X NTFS Fixed Healthy 26.9 GB 27 GB

 

Notes:

 

Created a Pool and Space. Resulting disk is initialized and mounted as volume X:.

 

1.3 - Verify health of the pool and space

 

Steps to perform on the guest:

 

Get-Volume X | FT -AutoSize

Get-Volume X | Get-Partition | FT -AutoSize

Get-Volume X | Get-Partition | Get-Disk | FT -AutoSize

Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize

Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize

Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT -AutoSize

 

Output:

 

PS C:> Get-Volume X | FT -AutoSize

 

DriveLetter FileSystemLabel FileSystem DriveType HealthStatus SizeRemaining Size

----------- --------------- ---------- --------- ------------ ------------- ----

X NTFS Fixed Healthy 26.9 GB 27 GB

 

PS C:> Get-Volume X | Get-Partition | FT -AutoSize

 

   Disk Number: 4

 

PartitionNumber DriveLetter Offset Size Type

--------------- ----------- ------ ---- ----

1 X 1048576 27 GB IFS

 

PS C:> Get-Volume X | Get-Partition | Get-Disk | FT -AutoSize

 

Number Friendly Name OperationalStatus Total Size Partition Style

------ ------------- ----------------- ---------- ---------------

4 Microsoft Storage Space Device Online 27 GB MBR

 

PS C:> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize

 

FriendlyName ResiliencySettingName OperationalStatus HealthStatus IsManualAttach Size

------------ --------------------- ----------------- ------------ -------------- ----

Space1 Mirror OK Healthy False 27 GB

 

PS C:> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize

 

FriendlyName OperationalStatus HealthStatus IsPrimordial IsReadOnly

------------ ----------------- ------------ ------------ ----------

Pool1 OK Healthy False False

 

PS C:> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT -AutoSize

 

FriendlyName CanPool OperationalStatus HealthStatus Usage Size

------------ ------- ----------------- ------------ ----- ----

PhysicalDisk2 False OK Healthy Auto-Select 19.25 GB

PhysicalDisk1 False OK Healthy Auto-Select 19.25 GB

PhysicalDisk3 False OK Healthy Auto-Select 19.25 GB

 

Notes:

 

All is healthy: Volume, Space (Virtual Disk), Pool and Physical Disks.

 

1.4 - Remove 1 disk

 

Steps to perform on the host:

 

Remove-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 0

Get-VMHardDiskDrive -VMName VM2

 

Output:

 

PS C:> Remove-VMHardDiskDrive -VMName VM2 -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 0

PS C:> Get-VMHardDiskDrive -VMName VM2

 

VMName ControllerType ControllerNumber ControllerLocation DiskNumber Path

------ -------------- ---------------- ------------------ ---------- ----

VM2 IDE 0 0 c:demov2.vhdx

VM2 SCSI 0 1 D:demodisk2.VHDX

VM2 SCSI 0 2 D:demodisk3.VHDX

 

Notes:

 

Removed one of the 3 SCSI disks for the VM.

That is the equivalent, in a physical machine, to pulling a drive out while the system is running (assuming you have a drive that supports hot removal).

 

1.5 - Verify effect on the pool and space

 

Steps to perform on the guest:

 

Get-Volume X | FT -AutoSize

Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize

Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize

Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT -AutoSize

Get-EventLog -LogName System -Source Disk | ? EntryType -ne "Information" | FL

Get-WinEvent -LogName Microsoft-Windows-Stor* | ? Level -lt 4 | FL

 

Output:

 

PS C:> Get-Volume X | FT -AutoSize

 

DriveLetter FileSystemLabel FileSystem DriveType HealthStatus SizeRemaining Size

----------- --------------- ---------- --------- ------------ ------------- ----

X NTFS Fixed Healthy 26.9 GB 27 GB

 

PS C:> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | FT -AutoSize

 

FriendlyName ResiliencySettingName OperationalStatus HealthStatus IsManualAttach Size

------------ --------------------- ----------------- ------------ -------------- ----

Space1 Mirror Incomplete Warning False 27 GB

 

PS C:> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-StoragePool | FT -AutoSize

 

FriendlyName OperationalStatus HealthStatus IsPrimordial IsReadOnly

------------ ----------------- ------------ ------------ ----------

Pool1 Degraded Warning False False

 

PS C:> Get-Volume X | Get-Partition | Get-Disk | Get-VirtualDisk | Get-PhysicalDisk | FT -AutoSize

 

FriendlyName CanPool OperationalStatus HealthStatus Usage Size

------------ ------- ----------------- ------------ ----- ----

PhysicalDisk