-
-
Save FlorianHeigl/3b229ffe5d7aa9df44b614c4c034f5cd to your computer and use it in GitHub Desktop.
This file contains 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" | |
$hyperVHost = "hyper-v-host.domain.tld" | |
# 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 = 3 | |
$NetboxServerRoleID = 25 | |
# 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." | |
$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..." | |
$clusterName = (Get-Cluster -Domain $($env:USERDNSDOMAIN) | Get-ClusterNode | where-object {$_.Name -eq $hyperVHost}).Cluster.name | |
if($null -eq $clusterName) { | |
Write-Host -foregroundcolor cyan "[$hyperVHost] Host is standalone" | |
$clusterName = "Standalone-$hyperVHost" | |
} | |
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) | |
#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) | |
} | |
######################################### | |
# 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
backup