DSCResources/DSC_iSCSIVirtualDisk/DSC_iSCSIVirtualDisk.psm1
$modulePath = Join-Path -Path (Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent) -ChildPath 'Modules' Import-Module -Name (Join-Path -Path $modulePath -ChildPath 'DscResource.Common') # Import Localization Strings $script:localizedData = Get-LocalizedData -DefaultUICulture 'en-US' <# .SYNOPSIS Returns the current state of the specified iSCSI Virtual Disk. .PARAMETER Path Specifies the path of the VHDX file that is associated with the iSCSI virtual disk. #> function Get-TargetResource { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $Path ) Write-Verbose -Message ( @( "$($MyInvocation.MyCommand): " $($script:localizedData.GettingiSCSIVirtualDiskMessage) ` -f $Path ) -join '' ) $virtualDisk = Get-VirtualDisk -Path $Path $returnValue = @{ Path = $Path } if ($virtualDisk) { Write-Verbose -Message ( @( "$($MyInvocation.MyCommand): " $($script:localizedData.iSCSIVirtualDiskExistsMessage) ` -f $Path ) -join '' ) $returnValue += @{ Ensure = 'Present' SizeBytes = $virtualDisk.Size DiskType = $virtualDisk.DiskType Description = $virtualDisk.Description ParentPath = $virtualDisk.ParentPath } } else { Write-Verbose -Message ( @( "$($MyInvocation.MyCommand): " $($script:localizedData.iSCSIVirtualDiskDoesNotExistMessage) ` -f $Path ) -join '' ) $returnValue += @{ Ensure = 'Absent' } } $returnValue } # Get-TargetResource <# .SYNOPSIS Creates, updates or removes an iSCSI Virtual Disk. .PARAMETER Ensure Ensures that Virtual Disk is either Absent or Present. .PARAMETER Path Specifies the path of the VHDX file that is associated with the iSCSI virtual disk. .PARAMETER SizeBytes Specifies the size, in bytes, of the iSCSI virtual disk. .PARAMETER BlockSizeBytes Specifies the block size, in bytes, for the VHDX. For fixed VHDX, if the value of the SizeBytes parameter is less than 32 MB, the default size is 2 MB. Otherwise, the default value is 32 MB. For dynamic VHDX, the default size is 2 MB. For differencing VHDX, the default size is the parent BlockSize. .PARAMETER DiskType Specifies the type of the VHDX. .PARAMETER LogicalSectorSizeBytes Specifies the logical sector size, in bytes, for the VHDX. .PARAMETER PhysicalSectorSizeBytes Specifies the physical sector size, in bytes, for the VHDX. .PARAMETER Description Specifies the description for the iSCSI virtual disk. .PARAMETER ParentPath Specifies the parent virtual disk path if the VHDX is a differencing disk. #> function Set-TargetResource { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $Path, [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present', [Parameter()] [ValidateSet('Dynamic', 'Fixed', 'Differencing')] [System.String] $DiskType = 'Dynamic', [Parameter()] [System.Uint64] $SizeBytes, [Parameter()] [System.Uint32] $BlockSizeBytes, [Parameter()] [ValidateSet(512, 4096)] [System.Uint32] $LogicalSectorSizeBytes, [Parameter()] [ValidateSet(512, 4096)] [System.UInt32] $PhysicalSectorSizeBytes, [Parameter()] [System.String] $Description, [Parameter()] [System.String] $ParentPath ) Write-Verbose -Message ( @( "$($MyInvocation.MyCommand): " $($script:localizedData.SettingiSCSIVirtualDiskMessage) ` -f $Path ) -join '' ) # Remove any parameters that can't be splatted. $null = $PSBoundParameters.Remove('Ensure') $null = $PSBoundParameters.Remove('DiskType') # Lookup the existing iSCSI Virtual Disk $virtualDisk = Get-VirtualDisk -Path $Path if ($Ensure -eq 'Present') { Write-Verbose -Message ( @( "$($MyInvocation.MyCommand): " $($script:localizedData.EnsureiSCSIVirtualDiskExistsMessage) ` -f $Path ) -join '' ) if ($virtualDisk) { # The iSCSI Virtual Disk exists $recreate = $false if (($DiskType) ` -and ($virtualDisk.DiskType -ne $DiskType)) { $recreate = $true } if (($SizeBytes) ` -and ($virtualDisk.Size -ne $SizeBytes)) { $recreate = $true } if (($ParentPath) ` -and ($virtualDisk.ParentPath -ne $ParentPath)) { $recreate = $true } <# If any parameters differ that require this Virtual Disk to be recreated then throw an error. Recreating the Virtual Disk is too dangerous as it may contain data. If the Virtual Disk *must* be recreated then the user will need to manually delete the Virtual Disk and the config will then create a new one. #> if ($recreate) { $errorId = 'iSCSIVirtualDiskRequiresRecreateError' $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidArgument $errorMessage = $($script:localizedData.iSCSIVirtualDiskRequiresRecreateError) -f $Path $exception = New-Object -TypeName System.InvalidOperationException ` -ArgumentList $errorMessage $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord ` -ArgumentList $exception, $errorId, $errorCategory, $null $PSCmdlet.ThrowTerminatingError($errorRecord) } Set-iSCSIVirtualDisk ` -ComputerName LOCALHOST ` -Path $Path ` -Description $Description ` -ErrorAction Stop Write-Verbose -Message ( @( "$($MyInvocation.MyCommand): " $($script:localizedData.iSCSIVirtualDiskUpdatedMessage) ` -f $Path ) -join '' ) } else { # Create the iSCSI Virtual Disk if ($DiskType -eq 'Fixed') { $null = $PSBoundParameters.Add('UseFixed', $True) } else { $null = $PSBoundParameters.Remove('LogicalSectorSizeBytes') } New-iSCSIVirtualDisk ` @PSBoundParameters ` -ComputerName LOCALHOST ` -ErrorAction Stop Write-Verbose -Message ( @( "$($MyInvocation.MyCommand): " $($script:localizedData.iSCSIVirtualDiskCreatedMessage) ` -f $Path ) -join '' ) } } else { Write-Verbose -Message ( @( "$($MyInvocation.MyCommand): " $($script:localizedData.EnsureiSCSIVirtualDiskDoesNotExistMessage) ` -f $Path ) -join '' ) if ($virtualDisk) { # The iSCSI Virtual Disk shouldn't exist - remove it Remove-iSCSIVirtualDisk ` -ComputerName LOCALHOST ` -Path $Path ` -ErrorAction Stop Write-Verbose -Message ( @( "$($MyInvocation.MyCommand): " $($script:localizedData.iSCSIVirtualDiskRemovedMessage) ` -f $Path ) -join '' ) } # if } # if } # Set-TargetResource <# .SYNOPSIS Tests if an iSCSI Virtual Disk needs to be created, updated or removed. .PARAMETER Ensure Ensures that Virtual Disk is either Absent or Present. .PARAMETER Path Specifies the path of the VHDX file that is associated with the iSCSI virtual disk. .PARAMETER SizeBytes Specifies the size, in bytes, of the iSCSI virtual disk. .PARAMETER BlockSizeBytes Specifies the block size, in bytes, for the VHDX. For fixed VHDX, if the value of the SizeBytes parameter is less than 32 MB, the default size is 2 MB. Otherwise, the default value is 32 MB. For dynamic VHDX, the default size is 2 MB. For differencing VHDX, the default size is the parent BlockSize. .PARAMETER DiskType Specifies the type of the VHDX. .PARAMETER LogicalSectorSizeBytes Specifies the logical sector size, in bytes, for the VHDX. .PARAMETER PhysicalSectorSizeBytes Specifies the physical sector size, in bytes, for the VHDX. .PARAMETER Description Specifies the description for the iSCSI virtual disk. .PARAMETER ParentPath Specifies the parent virtual disk path if the VHDX is a differencing disk. #> function Test-TargetResource { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $Path, [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present', [Parameter()] [ValidateSet('Dynamic', 'Fixed', 'Differencing')] [System.String] $DiskType = 'Dynamic', [Parameter()] [System.Uint64] $SizeBytes, [Parameter()] [System.Uint32] $BlockSizeBytes, [Parameter()] [ValidateSet(512, 4096)] [System.Uint32] $LogicalSectorSizeBytes, [Parameter()] [ValidateSet(512, 4096)] [System.UInt32] $PhysicalSectorSizeBytes, [Parameter()] [System.String] $Description, [Parameter()] [System.String] $ParentPath ) # Flag to signal whether settings are correct $desiredConfigurationMatch = $true Write-Verbose -Message ( @( "$($MyInvocation.MyCommand): " $($script:localizedData.TestingiSCSIVirtualDiskMessage) ` -f $Path ) -join '' ) # Lookup the existing iSCSI Virtual Disk $virtualDisk = Get-VirtualDisk -Path $Path if ($Ensure -eq 'Present') { # The iSCSI Virtual Disk should exist if ($virtualDisk) { # The iSCSI Virtual Disk exists already - check the parameters $recreate = $false if (($Description) ` -and ($virtualDisk.Description -ne $Description)) { Write-Verbose -Message ( @( "$($MyInvocation.MyCommand): " $($script:localizedData.iSCSIVirtualDiskParameterNeedsUpdateMessage) ` -f $Path, 'Description' ) -join '' ) $desiredConfigurationMatch = $false } if (($DiskType) ` -and ($virtualDisk.DiskType -ne $DiskType)) { Write-Verbose -Message ( @( "$($MyInvocation.MyCommand): " $($script:localizedData.iSCSIVirtualDiskParameterNeedsUpdateMessage) ` -f $Path, 'SizeBytes' ) -join '' ) $recreate = $true } if (($SizeBytes) ` -and ($virtualDisk.Size -ne $SizeBytes)) { Write-Verbose -Message ( @( "$($MyInvocation.MyCommand): " $($script:localizedData.iSCSIVirtualDiskParameterNeedsUpdateMessage) ` -f $Path, 'SizeBytes' ) -join '' ) $recreate = $true } if (($ParentPath) ` -and ($virtualDisk.ParentPath -ne $ParentPath)) { Write-Verbose -Message ( @( "$($MyInvocation.MyCommand): " $($script:localizedData.iSCSIVirtualDiskParameterNeedsUpdateMessage) ` -f $Path, 'ParentPath' ) -join '' ) $recreate = $true } <# If any parameters differ that require this Virtual Disk to be recreated then throw an error. Recreating the Virtual Disk is too dangerous as it may contain data. If the Virtual Disk *must* be recreated then the user will need to manually delete the Virtual Disk and the config will then create a new one. #> if ($recreate) { $errorId = 'iSCSIVirtualDiskRequiresRecreateError' $errorCategory = [System.Management.Automation.ErrorCategory]::InvalidArgument $errorMessage = $($script:localizedData.iSCSIVirtualDiskRequiresRecreateError) -f $Path $exception = New-Object -TypeName System.InvalidOperationException ` -ArgumentList $errorMessage $errorRecord = New-Object -TypeName System.Management.Automation.ErrorRecord ` -ArgumentList $exception, $errorId, $errorCategory, $null $PSCmdlet.ThrowTerminatingError($errorRecord) } } else { # Ths iSCSI Virtual Disk doesn't exist but should Write-Verbose -Message ( @( "$($MyInvocation.MyCommand): " $($script:localizedData.iSCSIVirtualDiskDoesNotExistButShouldMessage) ` -f $Path ) -join '' ) $desiredConfigurationMatch = $false } } else { # The iSCSI Virtual Disk should not exist if ($virtualDisk) { # The iSCSI Virtual Disk exists but should not Write-Verbose -Message ( @( "$($MyInvocation.MyCommand): " $($script:localizedData.iSCSIVirtualDiskExistsButShouldNotMessage) ` -f $Path ) -join '' ) $desiredConfigurationMatch = $false } else { # The iSCSI Virtual Disk does not exist and should not Write-Verbose -Message ( @( "$($MyInvocation.MyCommand): " $($script:localizedData.iSCSIVirtualDiskDoesNotExistAndShouldNotMessage) ` -f $Path ) -join '' ) } } # if return $desiredConfigurationMatch } # Test-TargetResource # Helper Functions <# .SYNOPSIS Looks up the specified iSCSI Virtual Disk. .PARAMETER Path Specifies the path of the VHDX file that is associated with the iSCSI virtual disk. #> function Get-VirtualDisk { param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.String] $Path ) try { <# Specify Localhost as computer because it speeds cmdlet up significantly. #> $virtualDisk = Get-iSCSIVirtualDisk ` -ComputerName LOCALHOST ` -Path $Path ` -ErrorAction Stop } catch [Microsoft.Iscsi.Target.Commands.IscsiCmdException] { $virtualDisk = $null } catch { throw $_ } return $virtualDisk } Export-ModuleMember -function *-TargetResource |