DSCResources/MSFT_xDhcpServerScope/MSFT_xDhcpServerScope.psm1
$script:resourceHelperModulePath = Join-Path -Path $PSScriptRoot -ChildPath '../../Modules/DscResource.Common' $script:moduleHelperPath = Join-Path -Path $PSScriptRoot -ChildPath '../../Modules/DhcpServerDsc.Common' Import-Module -Name $script:resourceHelperModulePath Import-Module -Name $script:moduleHelperPath $script:localizedData = Get-LocalizedData -DefaultUICulture 'en-US' <# .SYNOPSIS Gets current status of the scope with specified ScopeId. .DESCRIPTION Used by DSC Resource to perform Get method. For existing scopes retrieves all information that might be defined in the resource. Fore missing scopes returns only ScopeId, AddressFamily and the fact that it is absent. .EXAMPLE Get-TargetResource -ScopeId 192.168.1.0 -Name MyScope -IPStartRange 192.168.1.1 -IPEndRange 192.168.1.250 -SubnetMask 255.255.255.0 Gets information about scope 192.168.1.0 (if exists) or retunrs information about missing scope. .PARAMETER ScopeId ScopeId of the DHCP scope .PARAMETER Name Name of the DHCP scope .PARAMETER IPStartRange StartRange of the DHCP scope .PARAMETER IPEndRange EndRange of the DHCP scope .PARAMETER SubnetMask SubnetMask of the DHCP scope .PARAMETER AddressFamily AddressFamily of the DHCP scope #> function Get-TargetResource { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [Parameter(Mandatory = $true)] [System.String] $ScopeId, [Parameter(Mandatory = $true)] [System.String] $Name, [Parameter(Mandatory = $true)] [System.String] $IPStartRange, [Parameter(Mandatory = $true)] [System.String] $IPEndRange, [Parameter(Mandatory = $true)] [System.String] $SubnetMask, [Parameter()] [ValidateSet('IPv4')] [System.String] $AddressFamily = 'IPv4' ) Write-Verbose -Message ( $script:localizedData.GetServerScopeMessage -f $ScopeId ) #region Input Validation # Check for DhcpServer module/role Assert-Module -ModuleName 'DHCPServer' # Check values of IP Addresses used to define the scope $ipAddressesAssertionParameters = @{ ScopeId = $ScopeId IPStartRange = $IPStartRange IPEndRange = $IPEndRange SubnetMask = $SubnetMask AddressFamily = $AddressFamily } Assert-ScopeParameter @ipAddressesAssertionParameters #endregion Input Validation $dhcpScope = Get-DhcpServerv4Scope -ScopeId $ScopeId -ErrorAction 'SilentlyContinue' if ($dhcpScope) { $ensure = 'Present' $leaseDuration = $dhcpScope.LeaseDuration.ToString() } else { $ensure = 'Absent' $leaseDuration = '' } return @{ ScopeID = $ScopeId Name = $dhcpScope.Name IPStartRange = $dhcpScope.StartRange IPEndRange = $dhcpScope.EndRange SubnetMask = $dhcpScope.SubnetMask Description = $dhcpScope.Description LeaseDuration = $leaseDuration State = $dhcpScope.State AddressFamily = $AddressFamily Ensure = $ensure } } <# .SYNOPSIS Sets the scope with specified ScopeId. .DESCRIPTION Used by DSC Resource to perform Set method. It will add/remove/modify Scope based on input parameters .EXAMPLE Set-TargetResource -ScopeId 192.168.1.0 -Name MyScope -IPStartRange 192.168.1.1 -IPEndRange 192.168.1.250 -SubnetMask 255.255.255.0 Sets or creates scope with ScopeId 192.168.1.0 with parameters specified. .PARAMETER ScopeId ScopeId of the DHCP scope .PARAMETER Name Expected name of the DHCP scope .PARAMETER IPStartRange Expected startRange of the DHCP scope .PARAMETER IPEndRange Expected endRange of the DHCP scope .PARAMETER SubnetMask Expected subnetMask of the DHCP scope .PARAMETER Description Expected description of the DHCP scope .PARAMETER LeaseDuration Expected duration of the lease of the DHCP scope .PARAMETER AddressFamily Expected address family of the DHCP scope .PARAMETER State Expected state of the DHCP scope .PARAMETER Ensure Expected presence of the DHCP scope #> function Set-TargetResource { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.String] $ScopeId, [Parameter(Mandatory = $true)] [System.String] $Name, [Parameter(Mandatory = $true)] [System.String] $IPStartRange, [Parameter(Mandatory = $true)] [System.String] $IPEndRange, [Parameter(Mandatory = $true)] [System.String] $SubnetMask, [Parameter()] [System.String] $Description, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $LeaseDuration, [Parameter()] [ValidateSet('IPv4')] [System.String] $AddressFamily = 'IPv4', [Parameter()] [ValidateSet('Active', 'Inactive')] [System.String] $State = 'Active', [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present' ) Write-Verbose -Message ( $script:localizedData.SetServerScopeMessage -f $ScopeId ) #region Input Validation # Check for DhcpServer module/role Assert-Module -ModuleName DHCPServer # Check values of IP Addresses used to define the scope $ipAddressesAssertionParameters = @{ ScopeId = $ScopeId IPStartRange = $IPStartRange IPEndRange = $IPEndRange SubnetMask = $SubnetMask AddressFamily = $AddressFamily } Assert-ScopeParameter @ipAddressesAssertionParameters #endregion Input Validation if ($PSBoundParameters.ContainsKey('Debug')) { $null = $PSBoundParameters.Remove('Debug') } if ($PSBoundParameters.ContainsKey('AddressFamily')) { $null = $PSBoundParameters.Remove('AddressFamily') } Update-ResourceProperties @PSBoundParameters -Apply } <# .SYNOPSIS Tests the scope with specified ScopeId. .DESCRIPTION Used by DSC Resource to perform Test method. It will verify that Scope is configured as described in the parameters. .EXAMPLE Test-TargetResource -ScopeId 192.168.1.0 -Name MyScope -IPStartRange 192.168.1.1 -IPEndRange 192.168.1.250 -SubnetMask 255.255.255.0 Returns $true if scope is configured as described and $false if it's not .PARAMETER ScopeId ScopeId of the DHCP scope .PARAMETER Name Expected name of the DHCP scope .PARAMETER IPStartRange Expected startRange of the DHCP scope .PARAMETER IPEndRange Expected endRange of the DHCP scope .PARAMETER SubnetMask Expected subnetMask of the DHCP scope .PARAMETER Description Expected description of the DHCP scope .PARAMETER LeaseDuration Expected duration of the lease of the DHCP scope .PARAMETER AddressFamily Expected address family of the DHCP scope .PARAMETER State Expected state of the DHCP scope .PARAMETER Ensure Expected presence of the DHCP scope #> function Test-TargetResource { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [System.String] $ScopeId, [Parameter(Mandatory = $true)] [System.String] $Name, [Parameter(Mandatory = $true)] [System.String] $IPStartRange, [Parameter(Mandatory = $true)] [System.String] $IPEndRange, [Parameter(Mandatory = $true)] [System.String] $SubnetMask, [Parameter()] [System.String] $Description, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $LeaseDuration, [Parameter()] [ValidateSet('IPv4')] [System.String] $AddressFamily = 'IPv4', [Parameter()] [ValidateSet('Active', 'Inactive')] [System.String] $State = 'Active', [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present' ) Write-Verbose -Message ( $script:localizedData.TestServerScopeMessage -f $ScopeId ) #region Input Validation # Check for DhcpServer module/role Assert-Module -ModuleName DHCPServer # Check values of IP Addresses used to define the scope $ipAddressesAssertionParameters = @{ ScopeId = $ScopeId IPStartRange = $IPStartRange IPEndRange = $IPEndRange SubnetMask = $SubnetMask AddressFamily = $AddressFamily } Assert-ScopeParameter @ipAddressesAssertionParameters #endregion Input Validation if ($PSBoundParameters.ContainsKey('Debug')) { $null = $PSBoundParameters.Remove('Debug') } if ($PSBoundParameters.ContainsKey('AddressFamily')) { $null = $PSBoundParameters.Remove('AddressFamily') } Update-ResourceProperties @PSBoundParameters -Apply:$false } function Update-ResourceProperties { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [System.String] $ScopeId, [Parameter(Mandatory = $true)] [System.String] $Name, [Parameter(Mandatory = $true)] [System.String] $IPStartRange, [Parameter(Mandatory = $true)] [System.String] $IPEndRange, [Parameter(Mandatory = $true)] [System.String] $SubnetMask, [Parameter()] [System.String] $Description, [Parameter()] [ValidateNotNullOrEmpty()] [System.String] $LeaseDuration, [Parameter()] [ValidateSet('Active', 'Inactive')] [System.String] $State = 'Active', [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present', [Parameter()] [System.Management.Automation.SwitchParameter] $Apply ) # Convert the Lease duration to be a valid timespan if ($LeaseDuration) { $LeaseDuration = (Get-ValidTimeSpan -tsString $LeaseDuration -parameterName 'Leaseduration').ToString() } $checkScopeMessage = $script:localizedData.CheckScopeMessage -f $ScopeId Write-Verbose -Message $checkScopeMessage $dhcpScope = Get-DhcpServerv4Scope -ScopeId $ScopeId -ErrorAction 'SilentlyContinue' # Initialize the parameter collection if ($Apply) { $parameters = @{} } # dhcpScope is set if ($dhcpScope) { $TestScopeMessage = $($script:localizedData.TestScopeMessage) -f $ScopeId, 'present', $Ensure Write-Verbose -Message $TestScopeMessage # if it should be present, test individual properties to match parameter values if ($Ensure -eq 'Present') { #region Test the Scope Name $checkPropertyMsg = $($script:localizedData.CheckPropertyMessage) -f 'name' Write-Verbose -Message $checkPropertyMsg if ($dhcpScope.Name -ne $Name) { $notDesiredPropertyMsg = $($script:localizedData.NotDesiredPropertyMessage) -f 'name', $Name, $($dhcpScope.Name) Write-Verbose -Message $notDesiredPropertyMsg if ($Apply) { $parameters['Name'] = $Name } else { return $false } } else { $desiredPropertyMsg = $($script:localizedData.DesiredPropertyMessage) -f 'name' Write-Verbose -Message $desiredPropertyMsg } #endregion scope name #region Test the IPStartRange and IPEndRange if ($dhcpScope.StartRange -ne $IPStartRange -or $dhcpScope.EndRange -ne $IPEndRange) { $notDesiredPropertyMsg = $($script:localizedData.NotDesiredPropertyMessage) -f 'Start/EndRange', "$IPStartRange/$IPEndRange", "$($dhcpScope.StartRange)/$($dhcpScope.EndRange)" Write-Verbose -Message $notDesiredPropertyMsg if ($Apply) { $parameters['StartRange'] = $IPStartRange $parameters['EndRange'] = $IPEndRange } else { return $false } } #endregion IPStartRange and IPEndRange #region Test the Scope Description if ($PSBoundParameters.ContainsKey('Description')) { $checkPropertyMsg = $($script:localizedData.CheckPropertyMessage) -f 'description' Write-Verbose -Message $checkPropertyMsg if ($dhcpScope.Description -ne $Description) { $notDesiredPropertyMsg = $($script:localizedData.NotDesiredPropertyMessage) -f 'description', $Description, $($dhcpScope.Description) Write-Verbose -Message $notDesiredPropertyMsg if ($Apply) { $parameters['Description'] = $Description } else { return $false } } else { $desiredPropertyMsg = $($script:localizedData.DesiredPropertyMessage) -f 'description' Write-Verbose -Message $desiredPropertyMsg } } #endregion scope description #region Test the Lease duration if ($PSBoundParameters.ContainsKey('LeaseDuration')) { $checkPropertyMsg = $($script:localizedData.CheckPropertyMessage) -f 'lease duration' Write-Verbose -Message $checkPropertyMsg if ($dhcpScope.LeaseDuration -ne $LeaseDuration) { $notDesiredPropertyMsg = $($script:localizedData.NotDesiredPropertyMessage) -f 'lease duration', $LeaseDuration, $($dhcpScope.LeaseDuration) Write-Verbose -Message $notDesiredPropertyMsg if ($Apply) { $parameters['LeaseDuration'] = $LeaseDuration } else { return $false } } else { $desiredPropertyMsg = $($script:localizedData.DesiredPropertyMessage) -f 'lease duration' Write-Verbose -Message $desiredPropertyMsg } } #endregion lease duration #region Test the Scope State if ($PSBoundParameters.ContainsKey('State')) { $checkPropertyMsg = $($script:localizedData.CheckPropertyMessage) -f 'state' Write-Verbose -Message $checkPropertyMsg if ($dhcpScope.State -ne $State) { $notDesiredPropertyMsg = $($script:localizedData.NotDesiredPropertyMessage) -f 'state', $State, $($dhcpScope.State) Write-Verbose -Message $notDesiredPropertyMsg if ($Apply) { $parameters['State'] = $State } else { return $false } } else { $desiredPropertyMsg = $($script:localizedData.DesiredPropertyMessage) -f 'state' Write-Verbose -Message $desiredPropertyMsg } } #endregion scope state #region Test the Subnet Mask $checkPropertyMsg = $($script:localizedData.CheckPropertyMessage) -f 'subnet mask' Write-Verbose -Message $checkPropertyMsg if ($dhcpScope.SubnetMask -ne $SubnetMask) { $notDesiredPropertyMsg = $($script:localizedData.NotDesiredPropertyMessage) -f 'subnet mask', $SubnetMask, $($dhcpScope.SubnetMask) Write-Verbose -Message $notDesiredPropertyMsg if ($Apply) { try { # To set the subnet mask scope, the only ways is to remove the old scope and add a new scope Remove-DhcpServerv4Scope -ScopeId $ScopeId ## We can't splat two hashtables and $parameters may be empty, so just clone the existing one $addDhcpServerv4ScopeParams = $parameters.Clone() $addDhcpServerv4ScopeParams['Type'] = 'Dhcp' $addDhcpServerv4ScopeParams['StartRange'] = $IPStartRange $addDhcpServerv4ScopeParams['EndRange'] = $IPEndRange $addDhcpServerv4ScopeParams['Name'] = $Name $addDhcpServerv4ScopeParams['SubnetMask'] = $SubnetMask Add-DhcpServerv4Scope @addDhcpServerv4ScopeParams } catch { New-TerminatingError -errorId DhcpServerScopeFailure -errorMessage $_.Exception.Message -errorCategory InvalidOperation } $setPropertyMsg = $($script:localizedData.SetPropertyMessage) -f 'subnet mask', $SubnetMask Write-Verbose -Message $setPropertyMsg } else { return $false } } else { $desiredPropertyMsg = $($script:localizedData.DesiredPropertyMessage) -f 'subnet mask' Write-Verbose -Message $desiredPropertyMsg } #endregion subnet mask if ($Apply) { # If parameters contains more than 0 key, set the DhcpServer scope if ($parameters.Count -gt 0) { Set-DhcpServerv4Scope @parameters -ScopeId $dhcpScope.ScopeId Write-PropertyMessage -Parameters $parameters -keysToSkip ScopeId ` -Message $($script:localizedData.SetPropertyMessage) -Verbose } } # end Apply else { return $true } } # end ensure eq present # If dhcpscope should be absent else { if ($Apply) { $removingScopeMsg = $script:localizedData.RemovingScopeMessage -f $ScopeId Write-Verbose -Message $removingScopeMsg # Remove the scope Remove-DhcpServerv4Scope -ScopeId $ScopeId $deleteScopeMsg = $script:localizedData.deleteScopeMessage -f $ScopeId Write-Verbose -Message $deleteScopeMsg } else { return $false } }# end ensure -eq 'Absent' } # if $dhcpScope #If dhcpScope is not set, create it if needed else { $TestScopeMessage = $($script:localizedData.TestScopeMessage) -f $ScopeId, 'absent', $Ensure Write-Verbose -Message $TestScopeMessage if ($Ensure -eq 'Present') { if ($Apply) { # Add mandatory parameters $parameters['Name'] = $Name $parameters['StartRange'] = $IPStartRange $parameters['EndRange'] = $IPEndRange $parameters['SubnetMask'] = $SubnetMask # Check if Lease duration is specified, add to parameter collection if ($PSBoundParameters.ContainsKey('LeaseDuration')) { $parameters['LeaseDuration'] = $LeaseDuration } # Check if State is specified, add to parameter collection if ($PSBoundParameters.ContainsKey('State')) { $parameters['State'] = $State } $addingScopeMessage = $script:localizedData.AddingScopeMessage -f $ScopeId Write-Verbose -Message $addingScopeMessage try { # Create a new scope with specified properties Add-DhcpServerv4Scope @parameters -Type dhcp $setScopeMessage = $($script:localizedData.SetScopeMessage) -f $Name Write-Verbose -Message $setScopeMessage } catch { New-TerminatingError -errorId DhcpServerScopeFailure -errorMessage $_.Exception.Message -errorCategory InvalidOperation } }# end Apply else { return $false } } # end Ensure -eq Present else { return $true } } # else !dhcpscope } Export-ModuleMember -Function *-TargetResource |