-
-
Save cpi-bcso/53480313149a15b4e35c5645a38f48d3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Powershell refuses to connect to the Netbox API on our setup without this. | |
add-type @" | |
using System.Net; | |
using System.Security.Cryptography.X509Certificates; | |
public class TrustAllCertsPolicy : ICertificatePolicy { | |
public bool CheckValidationResult( | |
ServicePoint srvPoint, X509Certificate certificate, | |
WebRequest request, int certificateProblem) { | |
return true; | |
} | |
} | |
"@ | |
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy | |
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 | |
########################## | |
# Fill out these settings | |
########################## | |
# Some useful settings. | |
$token = "<netbox token>" | |
$uri = "http://netbox.domain.tld/api" | |
# set cluster and host the same name to get all vms on cluster, | |
# or set hyperVHost to hostname only, to just migrate the machines | |
# from one host of the cluster. Keep in mind, that all names are | |
# UPPERCASE when reading from AD | |
# -> Keep existing Clusternames in Netbox in Sync (uppercase) to | |
# not recreate them | |
$hyperVHost = "hyper-v-host" | |
$hyperVCluster = "hyper-v-cluster" | |
$hyperVDomain = "domain.tld" # without leading dot | |
# These are some ID's in Netbox | |
# We added a "Hyper-V" (id 3) cluster type. This needs to match yours! | |
# id 25 for us corresponds to the role "Server". | |
$NetboxHyperVClusterType = 1 | |
$NetboxServerRoleID = 7 | |
# Source: https://www.reddit.com/r/PowerShell/comments/8u14wl/check_a_list_of_ips_against_a_list_of_subnets/e1brhe3/ | |
function Test-IPInSubnet { | |
[CmdletBinding()] | |
param( | |
[Parameter( | |
Position = 0, | |
Mandatory, | |
ValueFromPipelineByPropertyName | |
)][ValidateNotNull()][System.Net.IPAddress]$Subnet, | |
[Parameter( | |
Position = 1, | |
Mandatory, | |
ValueFromPipelineByPropertyName | |
)][Alias('Mask')][ValidateNotNull()][System.Net.IPAddress]$SubnetMask, | |
[Parameter( | |
Position = 0, | |
Mandatory, | |
ValueFromPipeline, | |
ValueFromPipelineByPropertyName | |
)][Alias('Address')][ValidateNotNull()][System.Net.IPAddress]$IPAddress | |
) | |
process { | |
$Subnet.Address -eq ($IPAddress.Address -band $SubnetMask.Address) | |
} | |
} | |
function Add-NetboxIP { | |
[CmdletBinding()] | |
param ( | |
[Parameter()][System.Net.IPAddress]$ip, | |
[Parameter()][String]$mask | |
) | |
$id = Get-NetboxIP -ip $ip -mask $mask | |
if(-not $id) { | |
# Add the IP and return the resulting Id | |
Write-host "[$($vm.name)] Adding new ip address object for $ip/$mask" | |
$ipconcat="$ip" + "/" + "$mask" | |
$id = ((Invoke-WebRequest -Uri "$uri/ipam/ip-addresses/" -Method POST -Headers $headers -Body $(@{address=$ipconcat} | Convertto-json)).content | convertfrom-json).id | |
} | |
return $id | |
} | |
function Add-NetboxVM { | |
[CmdletBinding()] | |
param ( | |
[Parameter()][Microsoft.HyperV.PowerShell.VirtualMachine]$vm, | |
[Parameter()][String]$roleId, | |
[Parameter()][String]$clusterId | |
) | |
# Get or add the VM to Netbox | |
$id = Get-NetboxVM -name $vm.name | |
$virtualMachineBody = $(@{ | |
name=$($vm.VMName) | |
cluster=$clusterId | |
status=$(if($vm.state -eq "Running") {"active"} else {"offline"}) | |
role=$roleId | |
vcpus=$($vm.ProcessorCount) | |
memory=$(if($vm.DynamicMemoryEnabled){$vm.MemoryMaximum/1MB}else{$vm.MemoryStartup/1MB}) | |
disk=$(((($vm.HardDrives | Get-VHD -computername $hyperVHost).Size) | Measure-Object -Sum).Sum/1GB) | |
} | ConvertTo-Json) | |
if (-not $id) { | |
# Create | |
Write-host "[$($vm.name)] Creating new VM." | |
$id = ((Invoke-WebRequest -uri "$uri/virtualization/virtual-machines/" -Method POST -Body $virtualMachineBody -Headers $headers).content | convertfrom-json).id | |
} else { | |
# Update | |
Write-host "[$($vm.name)] Updating existing VM with id $id." | |
$id = ((Invoke-WebRequest -uri "$uri/virtualization/virtual-machines/$id/" -Method PATCH -Body $virtualMachineBody -Headers $headers).content | convertfrom-json).id | |
} | |
return $id | |
} | |
function Add-NetboxNetworkInterface { | |
[CmdletBinding()] | |
param ( | |
[Parameter()][Microsoft.HyperV.PowerShell.VMNetworkAdapter]$networkAdapter, | |
[Parameter()][String]$virtualMachineId | |
) | |
$id = Get-NetboxNetworkInterface -networkAdapter $networkAdapter -virtualMachineId $virtualMachineId | |
if(-not $id) { | |
$id = ((Invoke-WebRequest -Uri "$uri/virtualization/interfaces/" -method Post -Headers $headers -body $(@{name=$networkAdapter.name;virtual_machine=$virtualMachineId;mac_address=$networkAdapter.macaddress} | Convertto-json)).content | convertfrom-json).id | |
} | |
return $id | |
} | |
function Add-NetboxIPNetworkInterfaceAssociation { | |
[CmdletBinding()] | |
param ( | |
[Parameter()][String]$networkInterfaceId, | |
[Parameter()][String[]]$ipList | |
) | |
foreach($ipId in ($ipList | Where-Object {($null -ne $_) -and ($_ -notlike "fe80*")})) { | |
Write-host "[$($vm.name)] Creating interface $networkInterfaceId association with ip $ipId." | |
$result = Invoke-WebRequest -Uri "$uri/ipam/ip-addresses/$ipId/" -Method Patch -Headers $headers -Body $(@{assigned_object_type="virtualization.vminterface";assigned_object_id=$networkInterfaceId}| ConvertTo-Json) | |
} | |
} | |
function Add-NetboxCluster { | |
[CmdletBinding()] | |
param ( | |
[Parameter()][String]$name | |
) | |
Write-Host -foregroundcolor yellow "[$name] The cluster doesn't exist. Let's add it !" | |
return ((Invoke-WebRequest -Uri "$uri/virtualization/clusters/" -Method Post -Body $(@{name=$name;type=$NetboxHyperVClusterType}| Convertto-json) -Headers $headers).content | convertfrom-json).id | |
} | |
function Get-NetboxCluster { | |
[CmdletBinding()] | |
param ( | |
[Parameter()][String]$name | |
) | |
Write-host "[$name] Looking for a matching cluster." | |
try { return ((Invoke-WebRequest -Uri "$uri/virtualization/clusters/?name=$name" -Method Get -Headers $headers).content | convertfrom-json).results[0].id } | |
catch { | |
Write-host "[$name] No match found." | |
return $null | |
} | |
} | |
function Get-NetboxVM{ | |
[CmdletBinding()] | |
param ( | |
[Parameter()][String]$name | |
) | |
Write-host "[$($vm.name)] Looking for a matching VM." | |
try { return ((Invoke-WebRequest -uri "$uri/virtualization/virtual-machines/?q=$name" -Method Get -Headers $headers).content | convertfrom-json).results[0].id } | |
catch { | |
Write-host "[$($vm.name)] No match found" | |
return $null | |
} | |
} | |
function Get-NetboxIP { | |
[CmdletBinding()] | |
param ( | |
[Parameter()][System.Net.IPAddress]$ip, | |
[Parameter()][String]$mask | |
) | |
$ipconcat="$ip" + "/" + "$mask" | |
Write-host "[$($vm.name)] Looking for a ip matching $ipconcat." | |
try { return ((Invoke-WebRequest -Uri "$uri/ipam/ip-addresses/?q=$ipconcat" -Headers $headers -Method Get).content | convertfrom-json).results[0].id } | |
catch { | |
Write-host "[$($vm.name)] $ipconcat : no match found." | |
return $null | |
} | |
} | |
function Get-NetboxIPAMPrefixes { | |
Write-host -ForegroundColor Cyan "Getting Netbox IP prefixes" | |
return ((Invoke-WebRequest -Uri "$uri/ipam/prefixes/" -Method Get -Headers $headers).content | convertfrom-json).results | |
} | |
function Get-NetboxNetworkInterface { | |
[CmdletBinding()] | |
param ( | |
[Parameter()][Microsoft.HyperV.PowerShell.VMNetworkAdapter]$networkAdapter, | |
[Parameter()][String]$virtualMachineId | |
) | |
Write-host "[$($vm.name)] Looking for a network interface matching VM with id $virtualMachineId." | |
try { return (((Invoke-WebRequest -uri "$uri/virtualization/interfaces/?virtual_machine_id=${virtualMachineID}" -Method Get -Headers $headers).content | convertfrom-json).results | Where-Object {$_.name -eq $networkAdapter.name}).id } | |
catch { | |
Write-host "[$($vm.name)] No existing interfaces found that match." | |
return $null | |
} | |
} | |
function Get-HyperVClusterName { | |
# If we're not in a cluster, we use "Standalone - $Hostname" as a cluster name instead. | |
# We try to see if the cluster exists, if it does, we take it's ID for later. If not, we create it. | |
Write-host -foregroundcolor cyan "[$hyperVHost] Trying to determine if server is part of a cluster..." | |
if ( $hyperVCluster = $hyperVHost ) | |
{ | |
$clusterName = (Get-Cluster -Domain $($env:USERDNSDOMAIN) -Name $hyperVCluster | where-object {$_.Name -eq $hyperVHost}).name + "." + "$hyperVDomain" | |
} | |
else { | |
$clusterName = (Get-Cluster -Domain $($env:USERDNSDOMAIN) -Name $hyperVCluster | Get-ClusterNode | where-object {$_.Name -eq $hyperVHost}).Cluster.name + "." + "$hyperVDomain" | |
} | |
if($null -eq $clusterName) { | |
Write-Host -foregroundcolor cyan "[$hyperVHost.$hyperVDomain] Host is standalone" | |
$clusterName = "Standalone-$hyperVHost.$hyperVDomain" | |
} | |
return $clusterName | |
} | |
function Get-MaskFromPrefix { | |
[CmdletBinding()] | |
param ( | |
[Parameter()][String]$prefix | |
) | |
$MaskLength = $prefix.split('/')[1] | |
#[System.Net.IPAddress] $mask = 0 | |
# $mask.Address = ([UInt32]::MaxValue) -shl (32 - $MaskLength) -shr (32 - $MaskLength) | |
$maskresult = Convert-Subnetmask -CIDR $MaskLength | |
$mask = $maskresult.{Mask} | |
Write-host "[$($vm.name)] Mask for network prefix $($prefix.split('/')[1]) is $mask" | |
return $mask | |
} | |
function Get-NetboxPrefixFromIP { | |
[CmdletBinding()] | |
param ( | |
[Parameter()][System.Net.IPAddress]$ip | |
) | |
Write-host "[$($vm.name)] Looking for a subnet matching ip $ip." | |
foreach($prefix in $prefixes) { | |
$mask = Get-MaskFromPrefix -prefix $prefix.prefix | |
Write-host "$($prefix.prefix) has $mask" | |
if(Test-IPInSubnet -IPAddress $ip -Subnet $prefix.prefix.split('/')[0] -SubnetMask $mask) { | |
write-host -ForegroundColor Green "[$($vm.name)] Match found : $ip matches subnet $($prefix.prefix.split('/')[0])" | |
return $prefix.prefix.split('/')[1] | |
} | |
} | |
return $null | |
} | |
function Get-HyperVVMNics { | |
[CmdletBinding()] | |
param ( | |
[Parameter()][String]$vmname | |
) | |
Write-host "[$($vm.name)] Getting network interface list." | |
return Get-VMNetworkAdapter -VMName $vm.Name -computername $hyperVHost | |
} | |
function Set-NetboxCluster { | |
[CmdletBinding()] | |
param ( | |
[Parameter()][String]$name | |
) | |
Write-host "[$name] Setting cluster variable." | |
$id = Get-NetboxCluster($name) | |
if($null -eq $id) { | |
Write-host "[$name] Cluster does not exists - adding." | |
$id = Add-NetboxCluster($name) | |
} | |
return $id | |
} | |
function Set-NetboxVMPrimaryIP { | |
[CmdletBinding()] | |
param ( | |
[Parameter()][String]$virtualMachineId, | |
[Parameter()][String]$ipId | |
) | |
Write-host "[$($vm.name)] Setting primary IP to id $ipId for VM $virtualMachineId" | |
$result = Invoke-WebRequest -uri "$uri/virtualization/virtual-machines/$virtualMachineId/" -Method Patch -Headers $headers -Body $(@{primary_ip4=$ipId} | ConvertTo-Json) | |
} | |
# added new subnetconversion | |
# Language : PowerShell 4.0 | |
# Filename : Convert-Subnetmask.ps1 | |
# Autor : BornToBeRoot (https://github.com/BornToBeRoot) | |
# Description : Convert a subnetmask to CIDR and vise versa | |
# Repository : https://github.com/BornToBeRoot/PowerShell | |
# .SYNOPSIS | |
# Convert a subnetmask to CIDR and vise versa | |
# .LINK | |
# https://github.com/BornToBeRoot/PowerShell/blob/master/Documentation/Function/Convert-Subnetmask.README.md | |
function Convert-Subnetmask | |
{ | |
[CmdLetBinding(DefaultParameterSetName='CIDR')] | |
param( | |
[Parameter( | |
ParameterSetName='CIDR', | |
Position=0, | |
Mandatory=$true, | |
HelpMessage='CIDR like /24 without "/"')] | |
[ValidateRange(0,32)] | |
[Int32]$CIDR, | |
[Parameter( | |
ParameterSetName='Mask', | |
Position=0, | |
Mandatory=$true, | |
HelpMessage='Subnetmask like 255.255.255.0')] | |
[ValidateScript({ | |
if($_ -match "^(254|252|248|240|224|192|128).0.0.0$|^255.(254|252|248|240|224|192|128|0).0.0$|^255.255.(254|252|248|240|224|192|128|0).0$|^255.255.255.(255|254|252|248|240|224|192|128|0)$") | |
{ | |
return $true | |
} | |
else | |
{ | |
throw "Enter a valid subnetmask (like 255.255.255.0)!" | |
} | |
})] | |
[String]$Mask | |
) | |
Begin { | |
} | |
Process { | |
switch($PSCmdlet.ParameterSetName) | |
{ | |
"CIDR" { | |
# Make a string of bits (24 to 11111111111111111111111100000000) | |
$CIDR_Bits = ('1' * $CIDR).PadRight(32, "0") | |
# Split into groups of 8 bits, convert to Ints, join up into a string | |
$Octets = $CIDR_Bits -split '(.{8})' -ne '' | |
$Mask = ($Octets | ForEach-Object -Process {[Convert]::ToInt32($_, 2) }) -join '.' | |
} | |
"Mask" { | |
# Convert the numbers into 8 bit blocks, join them all together, count the 1 | |
$Octets = $Mask.ToString().Split(".") | ForEach-Object -Process {[Convert]::ToString($_, 2)} | |
$CIDR_Bits = ($Octets -join "").TrimEnd("0") | |
# Count the "1" (111111111111111111111111 --> /24) | |
$CIDR = $CIDR_Bits.Length | |
} | |
} | |
[pscustomobject] @{ | |
Mask = $Mask | |
CIDR = $CIDR | |
} | |
} | |
End { | |
} | |
} | |
######################################### | |
# Script starts here | |
######################################### | |
# Set API Headers | |
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" | |
$headers.Add("Authorization", "Token $token") | |
$headers.Add("Content-Type", 'application/json') | |
$headers.Add("Accept", 'application/json') | |
# Prepare the common variables | |
$clusterName = Get-HyperVClusterName | |
$clusterId = Set-NetboxCluster($clustername) | |
$prefixes = Get-NetboxIPAMPrefixes | |
$vms = Get-VM -computername $hyperVHost | |
foreach($vm in $vms) { | |
$virtualMachineId = Add-NetboxVM -vm $vm -clusterId $clusterId -roleId $NetboxServerRoleID | |
$virtualMachineIPList = @() | |
# Foreach interface, create the IP, create the nic and create the association | |
foreach($nic in (Get-HyperVVMNics -vmname $vm.name)) { | |
$ipList = @() | |
foreach ($ip in $nic.IPAddresses | Where-Object {($null -ne $_) -and ($_ -notlike "fe80*")}) { | |
$ipList += Add-NetboxIP -ip $ip -mask (Get-NetboxPrefixFromIP -ip $ip) | |
} | |
$nicId = Add-NetboxNetworkInterface -networkAdapter $nic -virtualMachineId $virtualMachineId | |
Add-NetboxIPNetworkInterfaceAssociation -networkInterfaceId $nicId -ipList $ipList | |
$virtualMachineIPList += $ipList | |
} | |
# Set the ip from the first interface as being the primary ipv4 | |
if($virtualMachineIPList -ne @()) { | |
Set-NetboxVMPrimaryIP -virtualMachineId $virtualMachineId -ipId ($virtualMachineIPList | Where-Object {$null -ne $_})[0] | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment