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 id=1 /]
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
EDIT:The book1.csv file looks something like this
Guestname | IP1 | Mask1 | IP2 | Mask2 | Gateway1 | DNS1 | DNS2 | NLB |
testcr | 10.20.1.85 | 255.255.255.0 | 10.22.1.1 | |||||
nlbtest1 | 10.22.1.165 | 255.255.255.0 | 10.22.1.166 | 255.255.255.0 | 10.22.1.1 | 10.22.1.11 | 10.22.1.13 | 10.22.1.160 |
nlbtest2 | 10.22.1.163 | 255.255.255.0 | 10.22.1.1 | 10.22.1.11 | 10.22.1.13 | 10.22.1.160 |
6 Comments
Adeel Shaheen · June 7, 2013 at 10:54 am
bro can you also share the book1.csv so we will able to see rows and columns on which we have to mention the details of vm
C-Rad · June 11, 2013 at 10:37 am
I tossed in a table at the end.. I hope that helps
Juniad · June 21, 2013 at 10:49 am
Hi Conrad,
I executed the script, I works for Unicast NLB cluster with one error (Did not change the IP Address of VM). But it gives the error on Multicast NLB Cluster on below strep.
get-nlbclustervip -hostname $test | set-nlbclustervip -newip $nlbip
Error ” Failed to change the IP address”
kawish · June 21, 2013 at 11:37 pm
Great, just tested your script.. It works but the point where I am stuck is.. its giving an error when change NLB cluster IP with Multicast… Can you help…? and one thing more is it possible to change the VM interface IPs with SRM IP injection feature and then Run script just to change the NLB cluster vIP? Need your opinion.. Thanks
kawish · July 23, 2013 at 12:02 pm
any update boss
C-Rad · July 26, 2013 at 12:12 pm
Yeah, SRM should work then change the NLB Cluster VIP.
In terms of Multicast clusters though, unfortunately I am just not sure.