DSCResources/POSHOrigin_vSphere_VM/Helpers/_TestGuestDisks.ps1

function _TestGuestDisks {
    [cmdletbinding()]
    param(
        [Parameter(Mandatory)]
        [ValidateNotNull()]
        $vm,

        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$DiskSpec,

        [Parameter(Mandatory)]
        [Microsoft.Management.Infrastructure.CimSession]$CimSession,

        [Parameter(Mandatory)]
        [System.Management.Automation.Runspaces.PSSession]$PSSession
    )

    begin {
        Write-Debug -Message '_TestGuestDisks() starting'
    }

    process {

        $pass = $true

        try {           
            $desiredDiskConfigMapping = _GeConfigDiskToVMDiskMapping -vm $vm -DiskSpec $DiskSpec        
            $os = _GetGuestOS -CimSession $CimSession

            # Get mapped disks between the guest and VMware
            $guestDiskMapping = _GetGuestDiskToVMDiskMapping -VM $vm -CimSession $CimSession
            
            if ($os -ge 62) {
                # Test Server 2012 or higher #
                Write-Debug -Message 'Running 2012 disk tests'
            
                $disks = Invoke-Command -Session $PSSession -ScriptBlock { Get-Disk }

                # Compare the mapping to what is configured
                foreach($config in $desiredDiskConfigMapping) {

                    # Do we have a matching guest disk
                        $guestDisk = $guestDiskMapping |
                            Where-Object {(($_.HasSN) -and ($_.SerialNumber -eq $config.SerialNumber)) -or ((!$_.HasSN) -and ($_.SCSIBus -eq $config.SCSIController -and $_.SCSIUnit -eq $config.SCSITarget))} |
                            Select-Object -First 1

                    if ($guestDisk) {

                        $disk = $disks | Where-Object {$_.Number -eq $guestDisk.WindowsDisk} | Select-Object -First 1
                        if ($disk) {

                            Write-Debug -Message "Testing guest disk configuration [$($config.DiskName)]"

                            $diskSize = $disk.Size / 1GB
                            $partition = Invoke-Command -Session $PSSession -ScriptBlock { 
                                $args[0] | Get-Partition -Verbose:$false |
                                    Where-Object {$_.Type -ne 'Reserved' -and $_.Type -ne 'Unknown' -and $_.IsSystem -eq $false} |
                                    Select-Object -Last 1
                            } -ArgumentList $disk

                            if ($partition) {

                                $sizes = Invoke-Command -Session $PSSession -ScriptBlock {
                                    $args[0] | Get-PartitionSupportedSize
                                } -ArgumentList $partition

                                # The max partition size is greater than the current partition size
                                if ( [math]::round($partition.Size / 1GB) -lt [math]::round($sizes.SizeMax / 1GB)) {
                                    $partSize = [Math]::Round($partition.Size / 1GB)
                                    Write-Verbose -Message "Disk [$($disk.Number)] does not match configuration [$partSize GB <> $($config.DiskSizeGB) GB]"
                                    $pass = $false
                                }

                                $volume = Invoke-Command -Session $PSSession -ScriptBlock { 
                                    $args[0] | Get-Volume -Verbose:$false | Select-Object -last 1
                                } -ArgumentList $partition

                                # Drive letter
                                if ($volume.DriveLetter -ne $config.VolumeName) {
                                    Write-Verbose -Message "Volume [$($volume.DriveLetter)] does not match configuration [$($config.VolumeName)]"
                                    $pass = $false
                                }

                                # Volume label
                                if (($volume.FileSystemLabel -ne $config.VolumeLabel) -and ($config.VolumeLabel -ne $null)) {
                                    Write-Verbose -Message "Volume label [$($Volume.FileSystemLabel)] does not match configuration [$($config.VolumeLabel)]"
                                    $pass = $false
                                }
                            } else {
                                Write-Verbose -Message "Could not find partition for disk with SN [$($config.SerialNumber)]"
                                $pass = $false
                            }
                        } else {
                            Write-Verbose -Message "Could not find matching formated disk with SN [$($guestDisk.SerialNumber)]"
                            $pass = $false
                        }
                    } else {
                        Write-Verbose -Message "Could not find disk with SN [$($config.SerialNumber)]"
                        $pass = $false
                    }
                }
            } else {
                Write-Debug -Message 'Running 2008r2 disk tests'
                # Test Server 2008R2 or lower #

                $disks = Get-CimInstance -ClassName CIM_DiskDrive -CimSession $CimSession -verbose:$false | Select -Property *

                # Compare the mapping to what is configured
                foreach($config in $desiredDiskConfigMapping) {

                    # Do we have a matching guest disk
                    $guestDisk = $guestDiskMapping |
                        Where-Object {(($_.HasSN) -and ($_.SerialNumber -eq $config.SerialNumber)) -or ((!$_.HasSN) -and ($_.SCSIBus -eq $config.SCSIController -and $_.SCSIUnit -eq $config.SCSITarget))} |
                        Select-Object -First 1 

                    if ($guestDisk) {

                        $disk = $disks | Where-Object {$_.Index -eq $guestDisk.WindowsDisk} | Select-Object -First 1
                        if ($disk) {

                            Write-Debug -Message "Testing guest disk configuration [$($config.DiskName)]"                         
                            $diskInfo = $null
                            $gs = @{
                                Session = $PSSession
                                ArgumentList = $guestdisk.WindowsDisk
                                ScriptBlock = {
                                    $diskSize = New-Object psobject
                                    $windowsDisk = [int]$($args[0])
                                    $primaryPart = Get-WMIObject win32_diskpartition | where {($_.DiskIndex -eq $windowsDisk) -and ($_.PrimaryPartition -eq $true)}
                                    if ($primaryPart.count -gt 1) {
                                                $pass = $false
                                                $diskError = "Not able to configure $windowsDisk because it has more than 1 primary partition"
                                                Write-Error $diskError
                                                throw                                       
                                    }
                                    $tempString = ' Disk ' + $windowsDisk.ToString()
                                    $results = "list disk" | diskpart | ? {$_.startswith($tempString)}
                                    $results |% { 
                                        if ($_ -match 'Disk\s+(\d+)\s+\w+\s+(\d+)\s+\w+\s+(\d+)\s+(\w+)') {
                                            Add-Member -InputObject $diskSize -MemberType Noteproperty -Name ExtraSpace -Value $($matches[3])
                                            Add-Member -InputObject $diskSize -MemberType NoteProperty -Name DiskSize -Value $($matches[2])
                                            $command = "select disk $($matches[1])`r`nlist part"
                                            $x = $command |diskpart | where {($_ -notlike '*Reserved*') -and ($_ -notlike '*Unknown*') -and ($_ -match 'Partition\s\d')}
                                            if ($x.count -gt 1) {
                                                $pass = $false
                                                $diskError = "Not able to configure $windowsDisk because it has more than 1 primary partition"
                                                Write-Error $diskError
                                                throw
                                            }
                                            $results2 = $x | where {$_ -match 'Partition\s+(\d+).*\s+(\d+\s+\w+)\s+(.*)'}
                                            Add-Member -InputObject $diskSize -Membertype Noteproperty -Name PartNum -Value ([convert]::ToInt32($matches[1], 10))
                                            #$tempSize = $matches[2].replace(' ', '')
                                            #$diskInBytes = [scriptblock]::Create($tempSize).Invoke()
                                            #$diskInGB = ([convert]::ToInt64($diskInBytes, 10) / 1GB)
                                            $diskInGB = ($primaryPart.size / 1GB)
                                            Add-Member -InputObject $diskSize -Membertype Noteproperty -Name PartSize -Value $diskInGB
                                            #Lots of type casting magic to get the correct offset size in GB based on given type(KB, MB, or GB)
                                            #$offSet = $matches[3].replace(' ', '')
                                            #$sizeInBytes = [scriptblock]::Create($offSet).Invoke()
                                            #$sizeInGB = ([convert]::ToInt32($sizeInBytes, 10) / 1GB)
                                            $sizeInGB = ($primaryPart.StartingOffset / 1GB) 
                                            Add-Member -InputObject $diskSize -Membertype NoteProperty -Name Offset -Value ([convert]::ToDecimal($sizeInGB))
                                        }
                                    }
                                    $diskSize
                                }
                            }
                            $diskInfo = Invoke-Command @gs
                            Write-Debug $diskInfo
                            $actualSize = [math]::round($diskInfo.PartSize + $diskInfo.Offset)
                            if ($actualSize -ne $config.DiskSizeGB) {
                                Write-Verbose -Message "Disk [$($guestdisk.WindowsDisk)] does not match configuration [$($actualSize) GB <> $($config.DiskSizeGB) GB]"
                                $pass = $false
                            }

                            # Drive letter
                            if ($guestdisk.VolumeName -ne $config.VolumeName) {
                                Write-Verbose -Message "Volume [$($guestDisk.VolumeName)] does not match configuration [$($config.VolumeName)]"
                                $pass = $false
                            }

                            # Volume label
                            if (($guestdisk.VolumeLabel -ne $config.VolumeLabel) -and ($config.VolumeLabel -ne $null)) {
                                Write-Verbose -Message "Volume label [$($guestdisk.VolumeLabel)] does not match configuration [$($config.VolumeLabel)]"
                                $pass = $false
                            }                               
                        } else {
                            Write-Verbose -Message "Could not find matching formated disk with SN [$($guestDisk.SerialNumber)]"
                            $pass = $false
                        }
                    } else {
                        Write-Verbose -Message "Could not find disk [$($config.SerialNumber)]"
                        $pass = $false
                    }
                }                
            }
            return $pass
        } catch {
            Write-Error -Message 'There was a problem testing the guest disks'
            Write-Error -Message "$($_.InvocationInfo.ScriptName)($($_.InvocationInfo.ScriptLineNumber)): $($_.InvocationInfo.Line)"
            write-Error -ErrorRecord $_
        }
        return $pass
    }

    end {
        Write-Debug -Message '_TestGuestDisks() ending'
    }
}