Hello friends,
I have been working on an script that basically clones a virtual machine and reconfigures the new virtual machines according to the variables that I have specified. All of this is working as expected. The area that I am having trouble with is using the Invoke-VMScript function to call a specific powershell script that only applies to the new VM.
What I would like to do is rely on the Invoke-VMScript to basically select the appropriate Guest OS powershell script as part of the execution. For example, inside the cloned VM there are powershell scripts for 3 VM's that basically rename and re-IP the VM according to its VM name.
What I would like to accomplish here, is clone the VM and either be able to specify the corresponding guest OS script via variable or be prompted to enter the location for its corresponding script. See workflow below:
Workflow:
Source VM ---> Cloned VM1 ---> Invoke-VMScript poweshell script that would apply to VM1 inside the OS = This Guest OS poweshell script renames the cloned OS to the same VM1 name and provides its IP.
Source VM ---> Cloned VM2 ---> Invoke-VMScript poweshell script that would apply to VM2 inside the OS = This Guest OS poweshell script renames the cloned OS to the same VM2 name and provides its IP.
Source VM ---> Cloned VM3 ---> Invoke-VMScript poweshell script that would apply to VM3 inside the OS = This Guest OS poweshell script renames the cloned OS to the same VM3 name and provides its IP.
Part of my script prompts the user to enter the name of the new clone. I then use this as a variable to create the new clone. It would be awesome if I could also use this to automatically execute the correct Guest OS powershell script based on the name that I am using.
Script:
##Variables to be used for constructing the VM
$Datastorecls = "VMFSCLS-01"
$ESXCLS = "ESXCLS"
$Folder = "POC"
$Network = "DMZ"
$SourceVM = "POCVM"
$NewDemoInstance = Read-host "Enter the name of the VM you wish to create"
##Script that will clone the VM
New-VM -Name $NewDemoInstance -VM $SourceVM -Location $Folder -Datastore $Datastorecls -ResourcePool $ESXCLS | Get-NetworkAdapter | Where {$_.NetworkName -eq "PROD"} | Set-NetworkAdapter -NetworkName $Network -Confirm:$false
Get-VM $NewDemoInstance | Where-Object {$_.PowerState -eq "PoweredOff"} | Start-VM
sleep 120
##Script that will reconfigure the interface for DHCP, remove any static routes and configure the new IP
Invoke-VMScript -VM $NewDemoInstance -GuestUser Admin -GuestPassword '******' -ScriptText c:\Scripts\SetIP_Name_POC.ps1 -Confirm:$false ---> Here's where I would like either a variable or a prompt.
Thanks so much guys!!
The New-VM needs to be moved after the selection.
Something like this.
PS: you will probably need to use the ScriptType parameter as well on the Invoke-VMScript cmdlet.
##Variables to be used for constructing the VM
$Datastorecls = "VMFSCLS-01"
$ESXCLS = "ESXCLS"
$Folder = "POC"
$Network = "DMZ"
$SourceVM = "POCVM"
##Script to execute based on user input
$answer = 0
Write-Host "1. POCVM1"
Write-Host "2. POCVM2"
Write-Host "3. POCVM3"
while(1,2,3 -notcontains $answer){
$answer = Read-host "Enter the type of script you wish to execute"
}
if($answer -eq 1){
$NewDemoInstance = 'POCVM1'
$scriptName = 'POCVM1.ps1'
}
if($answer -eq 2){
$NewDemoInstance = 'POCVM2'
$scriptName = 'POCVM2.ps1'
}
if($answer -eq 3){
$NewDemoInstance = 'POCVM3'
$scriptName = 'POCVM3.ps1'
}
##Script that will clone the VM
New-VM -Name $NewDemoInstance -VM $SourceVM -Location $Folder -Datastore $Datastorecls -ResourcePool $ESXCLS |
Get-NetworkAdapter | Where {$_.NetworkName -eq "PROD"} |
Set-NetworkAdapter -NetworkName $Network -Confirm:$false
Get-VM $NewDemoInstance | Where-Object {$_.PowerState -eq "PoweredOff"} | Start-VM
sleep 120
Invoke-VMScript -VM $NewDemoInstance -GuestUser Admin -GuestPassword '******' -ScriptText "C:\Scripts\$scriptName" -Confirm:$false
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Not sure I'm following 100%, but my interpretation:
If my assumption is correct, can't you do something along these lines in that case?
$answer = 0
Write-Host "1 Clone type A"
Write-Host "2 Clone type B"
Write-Host "3 Clone type C"
while(1,2,3 -notcontains $answer){
$answer = Read-host "Enter the type of close you wish to create"
}
if($answer -eq 1){
$NewDemoInstance = 'AAA'
$scriptName = 'a.ps1'
}
if($answer -eq 2){
$NewDemoInstance = 'BBB'
$scriptName = 'b.ps1'
}
if($answer -eq 3){
$NewDemoInstance = 'CCC'
$scriptName = 'c.ps1'
}
Invoke-VMScript -VM $NewDemoInstance -GuestUser Admin -GuestPassword '******' -ScriptText "C:\Scripts\$scriptName" -Confirm:$false
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks Luc!! I think your code will do the job, but I'm a bit confused as to where I should I include your code snipped? Would it go at the bottom?
Here's the whole script:
##Variables to be used for constructing the VM
$Datastorecls = "VMFSCLS-01"
$ESXCLS = "ESXCLS"
$Folder = "POC"
$Network = "DMZ"
$SourceVM = "POCVM"
$NewDemoInstance = Read-host "Enter the name of the VM you wish to create"
##Script that will clone the VM
New-VM -Name $NewDemoInstance -VM $SourceVM -Location $Folder -Datastore $Datastorecls -ResourcePool $ESXCLS | Get-NetworkAdapter | Where {$_.NetworkName -eq "PROD"} | Set-NetworkAdapter -NetworkName $Network -Confirm:$false
Get-VM $NewDemoInstance | Where-Object {$_.PowerState -eq "PoweredOff"} | Start-VM
sleep 120
##Script to execute based on user input
$answer = 0
Write-Host "POCVM1"
Write-Host "POCVM2"
Write-Host "POCVM3"
while(1,2,3 -notcontains $answer){
$answer = Read-host "Enter the type of script you wish to execute"
}
if($answer -eq 1){
$NewDemoInstance = 'POCVM1'
$scriptName = 'POCVM1.ps1'
}
if($answer -eq 2){
$NewDemoInstance = 'POCVM2'
$scriptName = 'POCVM2.ps1'
}
if($answer -eq 3){
$NewDemoInstance = 'POCVM3'
$scriptName = 'POCVM3.ps1'
}
Invoke-VMScript -VM $NewDemoInstance -GuestUser Admin -GuestPassword '******' -ScriptText "C:\Scripts\$scriptName" -Confirm:$false
The New-VM needs to be moved after the selection.
Something like this.
PS: you will probably need to use the ScriptType parameter as well on the Invoke-VMScript cmdlet.
##Variables to be used for constructing the VM
$Datastorecls = "VMFSCLS-01"
$ESXCLS = "ESXCLS"
$Folder = "POC"
$Network = "DMZ"
$SourceVM = "POCVM"
##Script to execute based on user input
$answer = 0
Write-Host "1. POCVM1"
Write-Host "2. POCVM2"
Write-Host "3. POCVM3"
while(1,2,3 -notcontains $answer){
$answer = Read-host "Enter the type of script you wish to execute"
}
if($answer -eq 1){
$NewDemoInstance = 'POCVM1'
$scriptName = 'POCVM1.ps1'
}
if($answer -eq 2){
$NewDemoInstance = 'POCVM2'
$scriptName = 'POCVM2.ps1'
}
if($answer -eq 3){
$NewDemoInstance = 'POCVM3'
$scriptName = 'POCVM3.ps1'
}
##Script that will clone the VM
New-VM -Name $NewDemoInstance -VM $SourceVM -Location $Folder -Datastore $Datastorecls -ResourcePool $ESXCLS |
Get-NetworkAdapter | Where {$_.NetworkName -eq "PROD"} |
Set-NetworkAdapter -NetworkName $Network -Confirm:$false
Get-VM $NewDemoInstance | Where-Object {$_.PowerState -eq "PoweredOff"} | Start-VM
sleep 120
Invoke-VMScript -VM $NewDemoInstance -GuestUser Admin -GuestPassword '******' -ScriptText "C:\Scripts\$scriptName" -Confirm:$false
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Awesome sir!! I will try it and will let you know how things go. Much appreciated and thanks again.
Thanks again Luc! Your code was dead on spot!!
Mr. Luc,
Need your help again on this one. Is there a way I can have the script ignore the user input if the VM they were supposed to delete is no longer there? In other words, if the VM is no longer present, how can I ignore the code below and continue with the VM creation that comes next?
Code:
##Delete VM
Get-VM *sls*
$DemoInstance = Read-Host "Enter the name of the VM you wish to delete"
##Script to delete VM
Get-VM $DemoInstance | Where-Object {$_.PowerState -eq "PoweredOn"} | Stop-VM -Confirm:$false
Remove-VM $DemoInstance -DeletePermanently -Confirm:$false
##VM Creation
##Variables and user input to be used for constructing the demo VM##
$Datastorecls = "VMFSCLS-01"
$ESXCLS = "ESXCLS"
$Folder = "Sls"
$Network = "Network"
$SourceVM = "POC"
$NewDemoInstance = Read-host "Enter the name of the VM you wish to create"
Much appreciated sir!!
You could do something like this
##Delete VM
Get-VM *sls*
$DemoInstance = Read-Host "Enter the name of the VM you wish to delete"
##Script to delete VM
$vm = Get-VM $DemoInstance -ErrorAction SilentlyContinue
if($vm){
$vm | Where-Object {$_.PowerState -eq "PoweredOn"} | Stop-VM -Confirm:$false
Remove-VM -VM $vm -DeletePermanently -Confirm:$false
}
else{
Write-Host "Can't find VM $DemoInstance"
return
}
##VM Creation
##Variables and user input to be used for constructing the demo VM##
$Datastorecls = "VMFSCLS-01"
$ESXCLS = "ESXCLS"
$Folder = "Sls"
$Network = "Network"
$SourceVM = "POC"
$NewDemoInstance = Read-host "Enter the name of the VM you wish to create"
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks again for your help sir. I tried using the code you provided and here's the output.
Enter the name of the VM you wish to delete: sls
Can't find VM sls
After this, the script halts and does not continue with the VM creation. How can I get the script to keep going?
Just remove the line with return on it.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thank you very much sir!! It worked perfectly,.