VMware Cloud Community
imompero
Enthusiast
Enthusiast
Jump to solution

Using Powercli I having trouble modifying vm hardware and nic portgroup when deploying from template

Hello,

wondering if anyone can help out, i am trying to deploy 1 or more vm from multiple templates, the variables are being imported from a csv file each line is a new VM with specific name, ip, gateway, host, datastore, etc.  The VM provisions no problem but I can't seem to modify the amount of cpu, memory, nic portgroup, IP of nic 1 or 2.  Any help in this would be great, also if there was a way to get the vm to start up after the provisioning process that would be even better.

Import-Csv deploy.csv -UseCulture | %{

    function UpdateVMSettings {

    Write-Host "Changing Portgroup and virtual Hardware..."

    Set-VM $"Server Name" | Get-OSCustomizationSpec $_.Customization | -MemoryMB $_.MemoryMB -NumCpu $_.NumCpu -Confirm:$false

    Set-VM $"Server Name" | Get-OSCustomizationSpec $_.Customization | Get-OSCustomizationNicMapping | where { $_.Position -eq '1'} | Set-OSCustomizationNicMapping -IpMode UseStaticIP -IpAddress $_."IP Address" -SubnetMask 255.255.255.0 -DefaultGateway $_."GW" -Confirm:$false

    Set-VM $"Server Name" | Get-OSCustomizationSpec $_.Customization | Get-OSCustomizationNicMapping | where { $_.Position -eq '2'} | Set-OSCustomizationNicMapping -IpMode UseStaticIP -IpAddress $_."Maint IP Address" -SubnetMask 255.255.0.0 -DefaultGateway $_."GW" -Confirm:$false

    Get-VM |Get-NetworkAdapter |Where {$_.NetworkName -eq 140 } |Set-NetworkAdapter -NetworkName $VLAN -Confirm:$false

    }

 

    $vm=New-VM -Name $_."Server Name" -Template $_.Template -Host $_."Esx Host" `

    -Datastore $_.Datastore -OSCustomizationSpec $_.Customization `

    -Confirm:$false -RunAsync

}

As I am sure you can tell I am not a programmer by any means, i play a little in powercli, look on the forums and try to adapt what I see to my needs, sometimes it works, sometimes it doesn't but I am trying Smiley Happy, thanks in advance for any advice anyone might have.

0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

I must have completely overlooked this, but why is there a function declaration in line 2 ?

Are you calling that function anywhere ?

The memory and CPU setting on line 14 will need a Get-VM first. Somethine like this

Get-vm -Name $_."Server Name" | Set-VM -MemoryGB $_.MemoryGB -NumCpu $_.NumCpu


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

View solution in original post

0 Kudos
20 Replies
LucD
Leadership
Leadership
Jump to solution

I think the way you are doing the customisation part is not the way it should be done.

First you adapt the OSCustomizationSpec like you defined in the CSV row

Get-OSCustomizationSpec $_.Customization | Set-OSCustomizationSpec -MemoryMB $_.MemoryMB -NumCpu $_.NumCpu -Confirm:$false

Then you apply the OSCustomizationSpec to the VM

Set-VM $"Server Name"-OSCustomizationSpec $_.Customization

If you don't want to change your OSCustomizationSpec all the time, you can work with a non-presistent one.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
imompero
Enthusiast
Enthusiast
Jump to solution

Something like this?

Import-Csv deploy.csv -UseCulture | %{

    function UpdateVMSettings {

    Write-Host "Changing Portgroup and virtual Hardware..."

    Get-OSCustomizationSpec $_.Customization | -MemoryMB $_.MemoryMB -NumCpu $_.NumCpu -Confirm:$false

    Get-OSCustomizationSpec $_.Customization | Get-OSCustomizationNicMapping | where { $_.Position -eq '1'} | Set-OSCustomizationNicMapping -IpMode UseStaticIP -IpAddress $_."IP Address" -SubnetMask 255.255.255.0 -DefaultGateway $_."GW" -Confirm:$false

    Get-OSCustomizationSpec $_.Customization | Get-OSCustomizationNicMapping | where { $_.Position -eq '2'} | Set-OSCustomizationNicMapping -IpMode UseStaticIP -IpAddress $_."Maint IP Address" -SubnetMask 255.255.0.0 -DefaultGateway $_."GW" -Confirm:$false

    Get-OSCustomizationSpec $_.Customization | Get-NetworkAdapter | Where {$_.NetworkName -eq 140 } |Set-NetworkAdapter -NetworkName $VLAN -Confirm:$false

    }

   

    $vm=New-VM -Name $_."Server Name" -Template $_.Template -Host $_."Esx Host" `

    -Datastore $_.Datastore -OSCustomizationSpec $_.Customization `

    -Confirm:$false -RunAsync

    }

0 Kudos
LucD
Leadership
Leadership
Jump to solution

That looks better, but I guess there is a typo on line 4.

That should be

Get-OSCustomizationSpec $_.Customization | Set-OSCustomizationSpec -MemoryMB $_.MemoryMB -NumCpu $_.NumCpu -Confirm:$false

And I don't think line 7 will work.

That should be something like this, and after the New-VM.

Get-VM -Name $_."Server Name" | Get-NetworkAdapter | Where {$_.NetworkName -eq 140 } |Set-NetworkAdapter -NetworkName $VLAN -Confirm:$false

Let me know if your script runs after these changes, and if it does what you want it to do ?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
imompero
Enthusiast
Enthusiast
Jump to solution

ok, So i ran this

Import-Csv deploy.csv -UseCulture | %{ 

    function UpdateVMSettings { 

    Write-Host "Changing Portgroup and virtual Hardware..." 

    Get-OSCustomizationSpec $_.Customization | Set-OSCustomizationSpec -MemoryMB $_.MemoryMB -NumCpu $_.NumCpu -Confirm:$false

    Get-OSCustomizationSpec $_.Customization | Get-OSCustomizationNicMapping | where { $_.Position -eq '1'} | Set-OSCustomizationNicMapping -IpMode UseStaticIP -IpAddress $_."IP Address" -SubnetMask 255.255.255.0 -DefaultGateway $_."GW" -Confirm:$false 

    Get-OSCustomizationSpec $_.Customization | Get-OSCustomizationNicMapping | where { $_.Position -eq '2'} | Set-OSCustomizationNicMapping -IpMode UseStaticIP -IpAddress $_."Maint IP Address" -SubnetMask 255.255.0.0 -DefaultGateway $_."GW" -Confirm:$false 

    } 

     

    $vm=New-VM -Name $_."Server Name" -Template $_.Template -Host $_."Esx Host" -Datastore $_.Datastore -OSCustomizationSpec $_.Customization -Confirm:$false -RunAsync

    Get-VM -Name $_."Server Name" | Get-NetworkAdapter | Where {$_.NetworkName -eq 140 } |Set-NetworkAdapter -StartConnected:$true -Connected:$true -NetworkName $_.VLAN -Confirm:$false

    }


But I get this error

Get-VM : 7/7/2013 10:44:59 PMGet-VM    VM with name 'testserver01' was

not found, using the specified filter(s).

At C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\Scripts\works\

VMs\test.ps1:10 char:11

+ Get-VM <<<<  -Name $_."Server Name" | Get-NetworkAdapter | where { $_.Pos

ition -eq '1'} | Set-NetworkAdapter -StartConnected:$true -Connected:$true -Net

workName $_.VLAN -Confirm:$false

+ CategoryInfo      : ObjectNotFound: (:) [Get-VM], VimException
+ FullyQualifiedErrorId : Core_OutputHelper_WriteNotFoundError,VMware.VimA

   utomation.ViCore.Cmdlets.Commands.GetVM

.

Seems like the server is not ready yet for the changing of the network name because it can't find the server name yet.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

That is because you run the New-VM with the RunAsync switch.

The VM will be created, but the script will immediately continue. Which means the VM is not yet created when the script reaches the Set-VM cmdlet.

You will have to build in a loop to wait till the VM is actually created.

You could do something like this

New-VM -Name $_."Server Name" ....

while(!(Get-VM -Name $_."Server Name" -ErrorAction SilentlyContinue)){

   sleep 5

}

Set-VM -VM $_."Server Name" ....


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
imompero
Enthusiast
Enthusiast
Jump to solution

Ok i made the change, not sure if it is right, when i run the script it proceeds to clone the vm but then prompts me if I want to configure parameters on testserver01, if i hit Y it gives an error(vm keeps cloning), then it starts the cloning of the second vm and prompts me again.  Below is the script and the error output.  THanks again for your help.

Import-Csv deploy.csv -UseCulture | %{ 

    function UpdateVMSettings { 

    Write-Host "Changing Portgroup and virtual Hardware..." 

    Get-OSCustomizationSpec $_.Customization | Set-OSCustomizationSpec -MemoryMB $_.MemoryMB -NumCpu $_.NumCpu -Confirm:$false

    Get-OSCustomizationSpec $_.Customization | Get-OSCustomizationNicMapping | where { $_.Position -eq '1'} | Set-OSCustomizationNicMapping -IpMode UseStaticIP -IpAddress $_."IP Address" -SubnetMask 255.255.255.0 -DefaultGateway $_."GW" -Confirm:$false 

    Get-OSCustomizationSpec $_.Customization | Get-OSCustomizationNicMapping | where { $_.Position -eq '2'} | Set-OSCustomizationNicMapping -IpMode UseStaticIP -IpAddress $_."Maint IP Address" -SubnetMask 255.255.0.0 -DefaultGateway $_."GW" -Confirm:$false 

    } 

     

    $vm=New-VM -Name $_."Server Name" -Template $_.Template -Host $_."Esx Host" -Datastore $_.Datastore -OSCustomizationSpec $_.Customization -Location "Deployed VMs" -Description $_.Description -Confirm:$false -RunAsync

    while(!(Get-VM -Name $_."Server Name" -ErrorAction SilentlyContinue)){

     sleep 120

   

    Set-vm -VM $_."Server Name" | Get-NetworkAdapter | Where {$_.NetworkName -eq 140 } |Set-NetworkAdapter -StartConnected:$true -Connected:$true -NetworkName $_.VLAN -Confirm:$false

    

    }`    

http://img825.imageshack.us/img825/5421/yfg.png

What I would like this to do is to clone the VM(s) first then when done to change the network adapter portgroup, is there a way to get it to clone the VM(s) first then change the portgroup?

0 Kudos
LucD
Leadership
Leadership
Jump to solution

The Set-VM in line 13 should be a Get-VM

Get-vm -VM $_."Server Name" | Get-NetworkAdapter | Where {$_.NetworkName -eq 140 } |Set-NetworkAdapter -StartConnected:$true -Connected:$true -NetworkName $_.VLAN -Confirm:$false

Can you try that ?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
imompero
Enthusiast
Enthusiast
Jump to solution

Ok the script ran without error, but when the vm was completed the portgroup had not been changed, the connected on startup was unchecked, and also the cpu/memory also had not been changed.

The script ended just after the second machine started cloning.

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Are you sure about the NetworkName.

Does

Get-vm -VM $_."Server Name" | Get-NetworkAdapter | Select NetworkName

actually display that value ?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
imompero
Enthusiast
Enthusiast
Jump to solution

This is what I get when I just run through powercli, Afterwards I powered on the VM and it was able to make the change.  So do I need to add something to the script to wait for the vm to be finished, power it on, then change the network adapter, memory, and cpu?

http://img191.imageshack.us/img191/8931/mfrr.png

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Yes, you need to do a Start-VM to power it on.

In fact the sysprep part of the OSCustomizationSpec will run during the first boot.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
lakey81
Enthusiast
Enthusiast
Jump to solution

Try the Set-NetworkAdapter without the -connected and -networkname.  I wouldn't think you could "connect" something that is powered off and you don't need to specify the networkname unless you want to change the port group.

imompero
Enthusiast
Enthusiast
Jump to solution

LucD wrote:

Yes, you need to do a Start-VM to power it on.

In fact the sysprep part of the OSCustomizationSpec will run during the first boot.

Well these are linux boxes that I am trying to deploy, when I do a Start-VM $_."Server Name", it tries to power on the VM before it is done cloning.  I have the while loop, but it doesn't seem to want to wait.  It should try to clone both machines and then once they are done to power it on.

This is what I have

Import-Csv deploy.csv -UseCulture | %{

    function UpdateVMSettings {

    Write-Host "Changing Portgroup and virtual Hardware..."

    Get-OSCustomizationSpec $_.Customization | Get-OSCustomizationNicMapping | where { $_.Position -eq '1'} | Set-OSCustomizationNicMapping -IpMode UseStaticIP -IpAddress $_."IP Address" -SubnetMask 255.255.255.0 -DefaultGateway $_."GW" -Confirm:$false

    Get-OSCustomizationSpec $_.Customization | Get-OSCustomizationNicMapping | where { $_.Position -eq '2'} | Set-OSCustomizationNicMapping -IpMode UseStaticIP -IpAddress $_."Maint IP Address" -SubnetMask 255.255.0.0 -DefaultGateway $_."GW" -Confirm:$false

    }

    

    $vm=New-VM -Name $_."Server Name" -Template $_.Template -Host $_."Esx Host" -Datastore $_.Datastore -OSCustomizationSpec $_.Customization -Location "Deployed VMs" -Description $_.Description -Confirm:$false -RunAsync

    while(!(Get-VM -Name $_."Server Name" -ErrorAction SilentlyContinue)){

     sleep 120

    }

    Start-VM $_."Server Name"

    Get-vm -Name $_."Server Name" | Get-NetworkAdapter | Where {$_.NetworkName -eq 140 } |Set-NetworkAdapter -StartConnected:$true -Connected:$true -NetworkName $_.VLAN -Confirm:$false

  

    }

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Or leave out the RunAsync for now on the New-VM line.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
imompero
Enthusiast
Enthusiast
Jump to solution

Is there a way to do that and have it clone the machines without waiting for it to finish one after another?

0 Kudos
LucD
Leadership
Leadership
Jump to solution

You could consider using the Start-Job cmdlet to introduce parallelism in the script.

See Re: Running a powercli from powershell for how it could be done.

There is another method as described by Vitali in Waiting for OS customization to complete.

It's based on the Events that a customization of a VM will produce.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
imompero
Enthusiast
Enthusiast
Jump to solution

hmm, i like the idea of the second option you provided, but seems a little above my skillset.  I think for now I will remove the -Runasync.

So now with this script it does change the portgroup from 140(staging network) to whatever the user puts in a csv file.  Only having two issues now.

1. is that IP address of the nic 1 & 2 are not being imported from the csv file

2. is that the MemoryGB and NumCpu changes are also not being changed.

Any hints? I Have looked all over the web for the memory and cpu changes but nothing seems to work

Import-Csv deploy.csv -UseCulture | %{ 

    function UpdateVMSettings { 

    

    Get-OSCustomizationSpec $_.Customization | Get-OSCustomizationNicMapping | where { $_.Position -eq '1'} | Set-OSCustomizationNicMapping -IpMode UseStaticIP -IpAddress $_."IP Address" -SubnetMask 255.255.255.0 -DefaultGateway $_."GW" -Confirm:$false 

    Get-OSCustomizationSpec $_.Customization | Get-OSCustomizationNicMapping | where { $_.Position -eq '2'} | Set-OSCustomizationNicMapping -IpMode UseStaticIP -IpAddress $_."Maint IP Address" -SubnetMask 255.255.0.0 -DefaultGateway $_."GW" -Confirm:$false 

    } 

     

    $vm=New-VM -Name $_."Server Name" -Template $_.Template -Host $_."Esx Host" -Datastore $_.Datastore -OSCustomizationSpec $_.Customization -Location "Deployed VMs" -Description $_.Description -Confirm:$false 

    while(!(Get-VM -Name $_."Server Name" -ErrorAction SilentlyContinue)){

     sleep 120

    }

    Start-VM $_."Server Name"

    Get-vm -Name $_."Server Name" | Get-NetworkAdapter | Where {$_.NetworkName -eq 140 } |Set-NetworkAdapter -StartConnected:$true -Connected:$true -NetworkName $_.VLAN -Confirm:$false

    Set-VM -MemoryGB $_.MemoryGB -NumCpu $_.NumCpu

   

    }

0 Kudos
LucD
Leadership
Leadership
Jump to solution

I must have completely overlooked this, but why is there a function declaration in line 2 ?

Are you calling that function anywhere ?

The memory and CPU setting on line 14 will need a Get-VM first. Somethine like this

Get-vm -Name $_."Server Name" | Set-VM -MemoryGB $_.MemoryGB -NumCpu $_.NumCpu


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
imompero
Enthusiast
Enthusiast
Jump to solution

Awesome, the function may have slipped in from another script I borrowed from, I made the changes you suggested and everything is working.  The script i have is below,along with what I have in the csv file.  Maybe it can be of use to someone else.  Thanks again so much, if you are going to be at vmware world let me know I will buy you a drink!

CSV File:

VMName,Esx Host,Datastore,Template,Customization,IP Address,VLAN,Maint IP Address,DNS,GW,NumCpu,MemoryGB,Description

Import-Csv deploy.csv -UseCulture | %{

  Write-Host

    Write-Host Setting IP for $_.VMName -nonewline; Write-Host .....

    Get-OSCustomizationNicMapping -spec $_.Customization | where { $_.Position -eq '1'} | Set-OSCustomizationNicMapping  -IpMode UseStaticIP -IpAddress $_."IP Address" -SubnetMask 255.255.255.0 -DefaultGateway $_."GW" -Confirm:$false

    Get-OSCustomizationNicMapping -spec $_.Customization | where { $_.Position -eq '2'} | Set-OSCustomizationNicMapping  -IpMode UseStaticIP -IpAddress $_."Maint IP Address" -SubnetMask 255.255.0.0 -DefaultGateway $_."GW" -Confirm:$false

        

    $vm=New-VM -Name $_."VMName" -Template $_.Template -Host $_."Esx Host" -Datastore $_.Datastore -OSCustomizationSpec $_.Customization -Location "Deployed VMs" -Description $_.Description -Confirm:$false | Out-Null

    while(!(Get-VM -Name $_."VMName" -ErrorAction SilentlyContinue)){

     sleep 120

    }

    Get-vm -Name $_."VMName" | Set-VM -MemoryGB $_.MemoryGB -NumCpu $_.NumCpu -Confirm:$false | Out-Null

        Write-Host

        Write-Host Adding $_.MemoryGB GB of memory and $_.NumCpu cpu to $_.VMName

    sleep 5

    Start-VM $_."VMName" | Out-Null

        Write-Host

        Write-Host Starting VM $_.VMName

    sleep 5

    Get-vm -Name $_."VMName" | Get-NetworkAdapter | Where {$_.NetworkName -eq 140 } |Set-NetworkAdapter -StartConnected:$true -Connected:$true -NetworkName $_.VLAN -Confirm:$false | Out-Null

        Write-Host

        Write-Host Changing VLAN for $_.VMName to $_.VLAN

        Write-Host ""

        Write-Host ""

        Write-Host ""

        Write-Host "#################################################################"

        Write-Host

        Write-Host Details:

        Write-Host Server Name:   $_.VMName

        Write-Host Memory:        $_.MemoryGB

        Write-Host CPU:           $_.NumCpu

        Write-Host VLAN:          $_.VLAN

        Write-Host

        Write-Host "#################################################################"

        Write-Host

    sleep 5                                    

0 Kudos