ConvertDhcpLeaseToReservation.ps1
<#PSScriptInfo .VERSION 2.4.0 .GUID 8bcade2e-0988-40d3-aa37-071a2f8b4c79 .AUTHOR Pavel_Kandratsyeu@outlook.com .COMPANYNAME .COPYRIGHT .TAGS .LICENSEURI .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES DhcpServer, ThreadJob .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES #> <# .SYNOPSIS Convert IpV4 lease to dhcp reservation. .DESCRIPTION The script searches a dhcp lease by IP or MAC address on all dhcp servers in Active Directory using ThreadJob and converts it to reservation. If dhcp server has a failover partner, the script notifies partner server too. The script requires DHCP admin credentials to work. #> #requires -Version 3.0 -Modules DhcpServer, ThreadJob [CmdletBinding( SupportsShouldProcess = $true, ConfirmImpact = 'High', DefaultParametersetName = 'ByIPAddress' )] param( [Parameter ( Position = 0, Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'ByIPAddress' )] [Alias('IP')] [ValidateNotNullOrEmpty()] [string] $IpAddress, [Parameter ( Position = 0, Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'ByMACAddress' )] [Alias('MAC')] [ValidateNotNullOrEmpty()] [string] $ClientId, [Parameter ( Mandatory = $false )] [Alias('Server')] [ValidateNotNullOrEmpty()] [string[]] $ComputerName, [Parameter ( Mandatory = $false )] [Alias('Notes')] [ValidateNotNullOrEmpty()] [string] $Description ) begin { $DhcpServers = Get-DhcpServerInDC } process { switch ($PsCmdlet.ParameterSetName) { 'ByIPAddress' { Write-Verbose -Message 'Parameter set ByIPAddress has been chosen.' $ScripBlock = { $VerbosePreference = $Using:VerbosePreference try { Get-DhcpServerv4Lease -IPAddress $Using:IpAddress -ComputerName $Using:Server -ErrorAction Stop | Add-Member -NotePropertyName PSComputerName -NotePropertyValue $Using:Server -Force -PassThru } catch { Write-Verbose -Message "Get-DhcpServerv4Lease Failed: IPAddress = $Using:IpAddress; Server = $Using:Server; Exception = $($_.Exception.Message)" } } } 'ByMACAddress' { Write-Verbose -Message 'Parameter set By has been chosen.' $ScripBlock = { Import-Module -Name DhcpServer $VerbosePreference = $Using:VerbosePreference Get-DhcpServerv4Scope -ComputerName $Using:Server | ForEach-Object -Process { try { $ScopeId = $_.ScopeId $_ | Get-DhcpServerv4Lease -ClientId ($Using:ClientId).Trim().Replace(':', '-') -ComputerName $Using:Server -ErrorAction Stop | Add-Member -NotePropertyName PSComputerName -NotePropertyValue $Using:Server -Force -PassThru } catch { Write-Verbose -Message "Get-DhcpServerv4Lease Failed: ClientId = $Using:ClientId; Sope = $ScopeId; Server = $Using:Server; Exception = $($_.Exception.Message)" } } } } } Write-Verbose -Message 'Searching dhcp lease...' foreach ($server in $(if ($ComputerName) { $ComputerName } else { $DhcpServers.DNSname })) { $null = Start-ThreadJob -ScriptBlock $ScripBlock -ThrottleLimit 32 } Write-Verbose 'Waiting jobs to complete...' $DhcpV4Lease = Get-Job | Receive-Job -Wait -AutoRemoveJob | Group-Object -Property IPAddress | ForEach-Object -Process { $_.Group | Select-Object -First 1 } if (-not $DhcpV4Lease) { Write-Warning -Message "Lease with Id '$(if($IpAddress){$IpAddress}else{$ClientId})' was not found. Try later." exit 0 } $DhcpV4Lease | ForEach-Object -Process { Write-Verbose -Message "Lease has been found on server $($_.PSComputerName):" Write-Verbose -Message "IpAddress: $($_.IpAddress)" Write-Verbose -Message "ClientId: $($_.ClientId)" Write-Verbose -Message "ScopeId: $($_.ScopeId)" Write-Verbose -Message "HostName: $($_.HostName)" Write-Verbose -Message "AddressState: $($_.AddressState)" } $DhcpV4Lease | Where-Object -Property AddressState -Like -Value '*Reservation' | ForEach-Object -Process { "Lease IpAddress $($_.IpAddress) already reserved on server $($_.PSComputerName):", "ClientId: $($_.ClientId)", "ScopeId: $($_.ScopeId)" , "HostName: $($_.HostName)", "AddressState: $($_.AddressState)", "Description: $($_.Description)" | Write-Warning } try { $AddDhcpReservationParams = @{Type = 'Dhcp' } if ($Description) { $AddDhcpReservationParams.Add('Description', $Description) } $DhcpV4Lease | Where-Object -Property AddressState -NotLike -Value '*Reservation' | ForEach-Object -Process { $Computer = $_.PSComputerName if ($PsCmdlet.ShouldProcess($_.IPAddress, "Convert lease to reservation: [ScopeId: $($_.ScopeId); Server: $Computer]")) { $_ | Add-DhcpServerv4Reservation @AddDhcpReservationParams -ComputerName $Computer -PassThru -ErrorAction Stop | ForEach-Object { if (Get-DhcpServerv4Failover -ComputerName $Computer -ScopeId $_.ScopeId -ErrorAction Ignore) { $null = Invoke-DhcpServerv4FailoverReplication -ComputerName $Computer -ScopeId $_.ScopeId -Force } Write-Host "[IpAddress: $($_.IpAddress); ClientId: $($_.ClientId); ScopeId: $($_.ScopeId); Server: $Computer] has been added to reservation." -ForegroundColor Green } } } } catch { Write-Host -Object "Failed to add address '$(if($IpAddress){$IpAddress}else{$ClientId})' to reservation on server '$($DhcpV4Lease.PSComputerName)': $($_.Exception.Message)" -ForegroundColor Red exit 1 } } |