Skip to content

Instantly share code, notes, and snippets.

@FlorianHeigl
Forked from InputObject2/Import-NetboxVM.ps1
Created February 20, 2022 16:16
Show Gist options
  • Save FlorianHeigl/3b229ffe5d7aa9df44b614c4c034f5cd to your computer and use it in GitHub Desktop.
Save FlorianHeigl/3b229ffe5d7aa9df44b614c4c034f5cd to your computer and use it in GitHub Desktop.
# 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]
}
}
@FlorianHeigl
Copy link
Author

backup

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment