JetStream Software Portal

change_drva_addr_new.ps1

#!/usr/bin/pwsh

#
#(c) 2023 JetStream Software, Inc < legal @jetstreamsoft.com >
    #
# This software is provided under the terms of the
# JetStream Software Inc.Software Tools License Agreement(STLA).
# Use of this software constitutes agreement to the terms of the STLA.
#

# force stop on error
$ErrorActionPreference = "Stop"

# vCenter parameters - fill with caution!
    $login = "[email protected]"
$passwd = ""
$srvaddr = "10.40.4.101"
# vCenter FQDN

$drva_prefix = "jss-"

# Expect 4.2 / 4.1 .18 compatible extra routing by
default.

class netConfig {
    [string] $netName
        [string] $routes[string] $gw[string] $setup[string] $dns
}

# rules to fill the configuration:
    # - only one interface is
default (others are non -
    default)
# - All interfaces must exist on the appliance
$fullConfig = @(
    #[netConfig] @ {
        netName = "VM Network";
        gw = "*";
        setup = "";
        routes = "10.8.0.0/24 via 10.50.0.11";
        dns = "8.8.8.8, 1.1.1.1"
    },
    #[netConfig] @ {
        netName = "VM Network 2";
        gw = "";
        setup = "";
        routes = "10.20.0.0/24 via 192.168.100.2";
        dns = ""
    },
    #[netConfig] @ {
        netName = "VM Network 3";
        gw = "";
        setup = "";
        routes = "10.12.0.0/24 via 10.5.5.2 metric 500,10.10.0.0/24 via 10.5.5.2";
        dns = ""
    }
    [netConfig] @ {
        netName = "VM Network";
        gw = "10.40.0.1";
        setup = "10.40.2.25#255.255.248.0";
        routes = "";
        dns = "10.40.0.9"
    }
    #[netConfig] @ {
        netName = "VM Network";
        gw = "";
        setup = "";
        routes = "";
        dns = ""
    },
    #[netConfig] @ {
        netName = "VM Network 2";
        gw = "192.168.100.1";
        setup = "192.168.100.99#255.255.255.0";
        routes = "";
        dns = ""
    },
    #[netConfig] @ {
        netName = "VM Network 3";
        gw = "";
        setup = "";
        routes = "10.10.0.0/24 via 10.5.5.2 metric 666";
        dns = ""
    }
)

function check_ip {
    param(
        [string] $ipv4_str
    )
    $parts = $ipv4_str.Split('.')
    if ($parts.Length - ne 4) {
        "Wrong number of octets in {0}" - f $ipv4_str | Write - Host
        return $False
    }
    foreach($octet in $parts) {
        Try {
            $oval = [int]::Parse($octet)
            if ($oval - le 0 - or $oval - ge 256) {
                "Bad octet {0} in IP address {1}" - f $octet, $ipv4_str | Write - Host
                return $False
            }
        } catch {
            "Bad octet {0} in IP address {1}" - f $octet, $ipv4_str | Write - Host
            return $False
        }
    }
    return $True
}

# sanity check configuration
# - exactly one def route NIC expected
$numDflt = 0
foreach($cfg in $fullConfig) {
        if ([String]::IsNullOrEmpty($cfg.netName)) {
            Write - Host "Network name is not provided in one of the config entries"
            exit
        }
        if (![String]::IsNullOrEmpty($cfg.gw)) {
            $numDflt += 1
            if ($cfg.gw - eq "*") {
                # DHCP + def GW
                if ($cfg.setup - ne "") {
                    "Network {0}, default non-DHCP interface must provide specific default GW"
                    `
                    -f $cfg.NetName  | Write-Host
                exit
            }
        } else { # IP address in GW
            if ($cfg.setup -eq "") {
                "Network {0}, default DHCP interface must pick gw from DHCP options" ` -
                    f $cfg.NetName | Write - Host
                    exit
                }
            }
        }
        if (![String]::IsNullOrEmpty($cfg.dns)) {
            [Char[]] $sep = @(' ', ',')
            $servers = $cfg.dns.Split($sep, [System.StringSplitOptions]::RemoveEmptyEntries)
            foreach($server in $servers) {
                if (!(check_ip($server))) {
                    "Network {0}, invalid DNS server specified {1}"
                    `
                     -f $cfg.NetName, $server | Write-Host
                exit
            }
        }
    }
}
if ($numDflt -ne 1) {
    "Wrong number of default adapters - {0}, expected 1" -f $numDflt | Write-Host
    exit
}

# check vCenter server access credentials
if ([String]::IsNullOrEmpty($srvaddr)) {
    $srvaddr = Read-Host -Prompt "Enter vCenter IP or FQDN"
} else {
    "Connecting to host {0}" -f $srvaddr | Write-Host
}

if ([String]::IsNullOrEmpty($login)) {
    $login = Read-Host -Prompt "Enter vCenter user name"
} else {
    "Username {0}" -f $login | Write-Host
}

if ([String]::IsNullOrEmpty($passwd)) {
    $passwd = Read-Host -Prompt "Enter password" -AsSecureString
    $passwd = $passwd | ConvertFrom-SecureString -AsPlainText
}


$visrv = Connect-VIServer -Server $srvaddr -User $login -Password $passwd

:extloop while ($True) {
    # choose VM to edit
    do {
        $vmlist=Get-VM -Server $visrv | where {$_.Name.StartsWith($drva_prefix)}
        Write-Host "Choose VM to reconfigure:"
        $idx=0
        foreach ($jsvm in $vmlist) {
            $idx += 1
            "`
                    t {
                        0
                    }: {
                        1
                    }
                    " -f $idx, $jsvm.Name | Write-Host
                }
                $reply = Read - Host "index, newline to re-read, Q/q to exit "
                if ([Char]::ToUpper($reply[0]) - eq 'Q') {
                    break extloop
                }
                $reply = $reply - as[int]
            }
            while ($null - eq $reply - or $reply - le 0 - or $reply - gt $vmlist.Length)

                $vm = $vmlist[$reply - 1]

            # validate options: all VM networks must be found in config
            $nic_list = $vm | Get - NetworkAdapter
            foreach($nic in $nic_list) {
                $cfg = $fullConfig | Where - Object {
                    $_.netName - eq $nic.NetworkName
                }
                if (!$cfg) {
                    "Network {0} of VM {1} not found in config"
                    `
                -f $nic.NetworkName, $vm.Name | Write-Host
            break extloop
        }
    }

    while($True)
    {
        # validate options: all config networks muts be configured with VM
        # print config changes
        foreach ($cfg in $fullConfig)
        {
            $nic = $nic_list | Where-Object { $_.NetworkName -eq $cfg.netName }
            if (!$nic)
            {
                "Network {0} not found on VM {1}" -f $cfg.netName, $vm.Name | Write-Host
                break extloop
            }

            $ip_setup_param = [String]::Format("guestinfo.net.{0}", $nic.MacAddress)
            $route_setup_param = [String]::Format("guestinfo.net.routes.{0}", $nic.MacAddress)
            $gway_setup_param = [String]::Format("guestinfo.net.gw.{0}", $nic.MacAddress)
            $dns_setup_param = [String]::Format("guestinfo.net.dns.{0}", $nic.MacAddress)

            $ip_setup = $vm | Get-AdvancedSetting -Name $ip_setup_param
            $route_setup = $vm | Get-AdvancedSetting -Name $route_setup_param
            $gway_setup = $vm | Get-AdvancedSetting -Name $gway_setup_param
            $dns_setup = $vm | Get-AdvancedSetting -Name $dns_setup_param

            $msg = ""
            if ($ip_setup.Value -ne $cfg.setup)
            {
                $msg += " config to '{0}';" -f $cfg.setup
            }
            if ($route_setup.Value -ne $cfg.routes)
            {
                $msg += " routes to '{0}';" -f $cfg.routes
            }
            if ($gway_setup.Value -ne $cfg.gw)
            {
                $msg += " gateway to '{0}';" -f $cfg.gw
            }
            if ($dns_setup.Value -ne $cfg.dns)
            {
                $msg += " DNS settings to '{0}';" -f $cfg.dns
            }
            if (! [String]::IsNullOrEmpty($msg)) {
                "`
                    tChanging {
                        0
                    }
                    on network {
                        1
                    }
                    " -f $msg, $cfg.netName | Write-Host
                }
            }

            $reply = Read - Host "Press enter to continue, Q/q to exit, N/n to choose next VM,"
            `
            + " E/e to change IP address"
        if ([Char]::ToUpper($reply[0]) -eq 'N')
        {
            continue extloop
        }
        if ([Char]::ToUpper($reply[0]) -eq 'Q')
        {
            break extloop
        }
        if ([Char]::ToUpper($reply[0]) -eq 'E')
        {
            foreach ($cfg in $fullConfig)
            {
                if ([String]::IsNullOrEmpty($cfg.setup)) {
                    "Interface {0} configured for DHCP" -f $cfg.netName | Write-Host
                } else {
                    do {
                        $new_ip = Read-Host ("IP for interface {0}" -f $cfg.netName)
                    } while (! $new_ip -or !(check_ip($new_ip)))
                    $parts = $cfg.setup.Split('#')
                    $cfg.setup = "{0}#{1}" -f $new_ip, $parts[1]
                }
            }
            continue
        }
        break
    }

    # perform GW config changes
    if ($vm.PowerState -ne [VMware.VimAutomation.ViCore.Types.V1.Inventory.PowerState]::PoweredOff) {
        Stop-VM -VM $vm -Confirm:$False
    }

    foreach ($nic in $nic_list) {
        $cfg = $fullConfig | Where-Object {$_.netName -eq $nic.NetworkName}

        $ip_setup_param = [String]::Format("guestinfo.net.{0}", $nic.MacAddress)
        $route_setup_param = [String]::Format("guestinfo.net.routes.{0}", $nic.MacAddress)
        $gway_setup_param = [String]::Format("guestinfo.net.gw.{0}", $nic.MacAddress)
        $dns_setup_param = [String]::Format("guestinfo.net.dns.{0}", $nic.MacAddress)

        $ip_setup = $vm | Get-AdvancedSetting -Name $ip_setup_param
        $route_setup = $vm | Get-AdvancedSetting -Name $route_setup_param
        $gway_setup = $vm | Get-AdvancedSetting -Name $gway_setup_param
        $dns_setup = $vm | Get-AdvancedSetting -Name $dns_setup_param

        if ($ip_setup.Value -ne $cfg.setup) {
            $ip_setup | Remove-AdvancedSetting -Confirm:$False
            if (! [String]::IsNullOrEmpty($cfg.setup)) {
                $vm | New-AdvancedSetting -Name $ip_setup_param -Value $cfg.setup -Confirm:$False
            }
        }
        if ($route_setup.Value -ne $cfg.routes) {
            $route_setup | Remove-AdvancedSetting -Confirm:$False
            if (! [String]::IsNullOrEmpty($cfg.routes)) {
                $vm | New-AdvancedSetting -Name $route_setup_param -Value $cfg.routes -Confirm:$False
            }
        }
        if ($gway_setup.Value -ne $cfg.gw) {
            $gway_setup | Remove-AdvancedSetting -Confirm:$False
            if (! [String]::IsNullOrEmpty($cfg.gw)) {
                $vm | New-AdvancedSetting -Name $gway_setup_param -Value $cfg.gw -Confirm:$False
            }
        }
        if ($dns_setup.Value -ne $cfg.dns) {
            $dns_setup | Remove-AdvancedSetting -Confirm:$False
            if (! [String]::IsNullOrEmpty($cfg.dns)) {
                $vm | New-AdvancedSetting -Name $dns_setup_param -Value $cfg.dns -Confirm:$False
            }
        }
    }

    Start-VM -VM $vm -Confirm:$False
}

Disconnect-VIServer -Server $global:DefaultVIServers -Confirm:$False
Was this article helpful?

Can We Help You?

Can't find what you're looking for?
Contact JetStream