Here it is, my little project I have been working on for the last few weeks. Yes, I know,  a few weeks is quite a long time for a script. This however is my first time writing a powershell script, so there have a been a few road bumps and blocks a long the way.

My goal for the script is such being able to re-ip a VM and an NLB cluster. I also wanted to do this to a VM that doesn’t have a current network connection. The thought being that after an srm failover the VM would not have a network connection since it would be on a different subnet and all that goodness.

My thoughts were to pull the info I wanted from a nice and simple excel spreadsheet that I would keep up to date, being that the IPs wouldn’t change that often I figured that wouldn’t be that hard. My spreadsheet looks like this.

[table "1" not found /]

I think the titles there are pretty descriptive as to contents of the cells and columns.

There were also a few things I wanted to stay away from

  • netsh- I didn’t want to have to script or plan for the the interface name, also I wasn’t sure how well netsh would handle re-ip with multiple IPs to a single interface
  • Set-VMGuestNetworkInterface–The guests would primarily be Server 2008, which means this cmdlet just doesn’t work

That leaves me with pretty much this line

(Get-WMIObject Win32_NetworkAdapterConfiguration | where {$_.ipenabled -eq $true}).EnableStatic($ip,$mask)

Which is great but how do I use it with a VM that currently doesn’t have network access. The answer is the Invoke-VMScript cmdlet. This answer is both great and awful.

I could not and have not been able to get my re-ip line to work inside of the Invoke-VMScript cmdlet, no matter how I tried to feed to the Invoke-VMScript, it wouldn’t work. I could get it to return the interface by leaving off the .EnableStatic($ip,$mask), however once I put the EnableStatic on there it continuously had problems.

Taking it from there I decided to put the script and spreadsheet local on the target computer and run it using the Invoke-VMScript. This obviously isn’t the most ideal solution, but it’s what I got! I wrote a quick script to copy my ip script and the to those target computers.

$data=import-csv book1.csv

Foreach ($line in $data){
$match = $line.guestname
$match
IF(
(test-path \$matchc$power -pathtype container) -ne $true){
new-item \$matchc$power -type directory}

copy ./works2.ps1 \$matchc$power -confirm
copy ./book1.csv \$matchc$power -confirm
}

As you can see it just simply copies those to files to each of the guests named in the spreadsheet. This allows me to keep a central or master copy of both the script and the spreadsheet and send them out whenever there are updates.

Now my for invoke-vmscript. This one tests the guest names listed in the spreadsheet for VMs listed in a folder, if there is a match then it will run the ip changing script(works2.ps1 in my case) on the target machine. Oh, and I also threw in a ton of comments in case they are helpful….

# The $test variable can be pretty much whatever you want it to be, or with a little adjustment it isn't even necessary.
# I just wanted to set it up like this for the $match variable later on
$test=(get-folder testing|get-vm)

#$data and the csv is where all the information lies that this script/s pulls
$data=import-csv book1.csv

$hostcredential=Get-Credential "Host Credentials"
$guestcredential=Get-Credential "Guest Credentials"

#Line row, row line, same thing in a spreadsheet. I just wish I knew more of those basic understood variables such as $line.
# If anyone knows a good listing please let me know
foreach ($line in $data)
{
#For each of the VMs in $test it checks to see if there is a listing for that vm name in the excel spreadsheet.
$match=$test|?{$line.guestname -eq $_.name}

	IF($match)
	{
	#Oh invoke-vmscript how I both love and hate you. This calls for the execution of the script works2.ps1 script locally on the target computer
	invoke-vmscript -vm $match.name -scripttext '&"C:WindowsSystem32WindowsPowerShellv1.0powershell.exe" "C:Powerworks2.ps1"' -scripttype "powershell" -hostcredential $hostcredential -guestcredential $guestcredential -confirm
	}

}

And last but certainly not least, my script to re-ip a VM. Not going to lie, being my first real script I am pretty proud of it.


#Different than my script to run Invoke-Vmscript, here $test is the hostname of the vm, because I am only going to be running this script against the computer it resides

$test=hostname

$data=import-csv "c:powerbook1.csv"

foreach ($line in $data){

$match=$test|?{$line.guestname -eq $_}

	IF($match)
	{
	#Pulling the information for the vm. Basically as long
	#as the naming convention I set is correct in the spreadsheet
	#and the cell isn't blank, it will pull all the info it needs

	$ips=1..50|%{IF ($line."ip$_"  -gt ""){$line."ip$_"}}
	$masks=1..50|%{IF ($line."mask$_"  -gt ""){$line."mask$_"} }
	$gateway=1..50|%{IF ($line."gateway$_"  -gt ""){$line."gateway$_"} }
	$dns=1..50|%{IF ($line."dns$_"  -gt ""){$line."dns$_"} }

	#I only want the network interface that is enabled. If you have more than one interface, you will need to make adjustments

	$NICs =Get-WMIObject Win32_NetworkAdapterConfiguration | where {$_.ipenabled -eq $true}

	#I like this nice group variable because it allows me to see what is being put into the actionable commands
	#It makes it easier to troubleshoot if there are problems.

	$ips
	$masks
	$nice
	$gateway
	$nics

	#Setting the static IPs, Gateways, and DNS entries on the VM

	$nics.EnableStatic($ips,$masks)
	$nics.setgateways($gateway)
	$nics.SetDNSServerSearchOrder($dns)

	#This last part I threw in to change the NLB virtual IP for an NLB cluster
	IF ($line.nlb -gt "")
	{
	#In this instance the full path of the module isn't necessary
	import-module "C:WindowsSystem32WindowsPowerShellv1.0ModulesNetworkLoadBalancingClusters"
	#I did a sleep to have the script pause after changing the IPs of the nics.
	#I don't believe it is necessary, but changing the nlb virtual IP has been very finicky for me personally and this seems to work for me
	start-sleep -s 15
	#The IP of the NLB Cluster
	$nlbip=$line.nlb

	#I should note sometimes this does give an error about the cmdlet when in fact it does succeed in the change
	#Just FYI
	get-nlbclustervip -hostname $test | set-nlbclustervip -newip $nlbip
	}
	}

}

There are some things this script specifically was not designed to do

  • Change IP on multiple interfaces for a single VM, although a few changes and it would be able to do it.
  • Copy the script and excel spreadsheets out to the target VMs  After a failover has occurred.  A network connection is needed for that so make sure you have everything up to date.

I understand as a whole this is all kind of messy and not as clean as most people would want it. If anyone has any suggestions on how I could clean it up let me know. Please please Let me know!! :)

One more thing, I just recently learned powershell, and I am definitely still learning. I just wanted to say though that Hal’s Book has been immensely helpful in both teaching me powershell/powercli and as an all-around great reference guide