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 , thanks in advance for any advice anyone might have.
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
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
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
}
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
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 PM | Get-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.
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
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
}`
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?
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
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.
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
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?
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
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.
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
}
Or leave out the RunAsync for now on the New-VM line.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Is there a way to do that and have it clone the machines without waiting for it to finish one after another?
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
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
}
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
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