Hi
I've a maintenance is coming up for which I need to shutdown 1000+ VMs and once the Maintenance is complete, Need to start those VMs back on.
I've a list of 1000 VMs and I can run in for loop but that will take hours to shutdown these VMs and I only have 2 hours of Maintenance window, Can someone please help ?
Here is the script which I got from the community and it works as expected but it runs serially.
foreach ($vmlist in (Get-Content -Path C:\vmlist1.txt)){
$vm = Get-VM -Name $vmlist
Start-VM -VM $vm -Confirm:$false -RunAsync
}
Thanks & Regards
To cover that we can indeed adapt the background job script.
param(
[string]$VMName,
[string]$vcServer,
[string]$vcId
)
Import-Module VMware.VimAutomation.Core
Connect-VIServer -Server $vcServer -Session $vcId
$vm = Get-VM -Name $VMName
if($vm.Guest.State -eq "Running"){
Shutdown-VMGuest -VM $vm -Confirm:$false -RunAsync
}
else{
Stop-VM -VM $vm -Confirm:$false -RunAsync
}
}
$fileName = '.\input.csv'
$MaxJobs = 10
$jobs = @()
Import-Csv -Path $fileName | ForEach-Object -Process {
if ($jobs.Count -le $MaxJobs) {
$job = (Start-Job -Verbose -ScriptBlock $script -ArgumentList $_.VMName, $global:DefaultVIServer.Name, $global:DefaultVIServer.SessionId)
$jobs += $job
}
else {
Wait-Job -Job $jobs
$jobs = @()
}
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
You can use the Start-Job cmdlet to launch these cmdlets in the background.
You probably want to impose a maximum number of jobs to run in the background, hence the MaxJobs test.
param(
[string]$VMName,
[string]$vcId
)
Connect-VIServer -Session $vcId
Get-VM -Name $VMName | Shutdown-VMGuest -Confirm:$false
}
$fileName = '.\input.csv'
$MaxJobs = 10
Import-Csv -Path $fileName | ForEach-Object -Process {
$jobs = @()
while ($jobs.Count -le $MaxJob) {
$jobs += (Start-Job -ScriptBlock $script -ArgumentList $_.VMName, $global:DefaultVIServer.SessionId)
}
Wait-Job -Job $jobs
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thank you LuCD. Greatly appreciate your quick response.
I'm not great at powercli so please bear me if my questions are silly.
1) When I run it , I get the following error -
2) Connect-VIServer -Session $vcId -> Where do we put vCenter name to login to ?
on the other hand, can we just login to vCenter and then just run the script and remove tht line ?
Thanks a lot LuCD for your help.
1) Sorry, I had a type in there.
The Wait-Job -Job $jobs.Id should have been Wait-Job -Job $jobs.Id.
I corrected the code above.
2) In a background job you don't inherit the connection to the vCenter.
That is why the SessionId is passed to the background job.
And also why we have the Connect-VIServer in there.
To run the script, connect to your vCenter.
Then run the script.
It will pass the SessionId to the background jobs.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks again LuCD
Understood #2 Greatly appreciate it.
I changed the Wait-Job line to Wait-Job -Job $jobs and I still get the same error .
Sorry for bugging you.
Are you sure about the same error?
Just tried it, and it works for me.
Which PowerShell version are you running (check $PSVersionTable)?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Yes, Here is the error -
Can you attach the script as you are running it?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
You are missing a closing brace at the end of the script.
Does your CSV contain a column with the name VMname?
The CSV should look something like this
VMName
vm1
vm2
vm3
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Yes, I added VMName and closing brace . Sorry that was missing.
Here is the new error -
I have a different version, can you try that one?
param(
[string]$VMName,
[string]$vcId
)
Connect-VIServer -Session $vcId
Get-VM -Name $VMName | Shutdown-VMGuest -Confirm:$false
}
$fileName = '.\input.csv'
$MaxJobs = 10
$jobs = @()
Import-Csv -Path $fileName | ForEach-Object -Process {
if ($jobs.Count -le $MaxJob) {
Write-Host "Job for $($_.VMName)"
$job = (Start-Job -Verbose -ScriptBlock $script -ArgumentList $_.VMName, $global:DefaultVIServer.SessionId)
Write-Host "`tStarted job $($job.Id)"
Write-Host "`tRunning jobs $($jobs.Count)"
$jobs += $job
}
else {
Wait-Job -Job $jobs
$jobs = @()
}
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Thanks again for your time and support LuCD
Here is the error after new code -
Did none of the Write-Host lines produce any output?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Unfortunately not LuCD
That would mean that the following returns nothing.
Can you check?
Import-Csv -Path $fileName
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Here is my input.csv
VMName
cvp-master1
cvp-master2
its in the same path as the script.
$fileName = '.\input.csv'
Am I doing anything wrong here?
The relative path starts from your current location.
Did you try the code I just gave?
Does it return the content of the CSV?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Yes, it does
I think I found it, there is a typo (missing 's' in $MaxJobs).
The line
if ($jobs.Count -le $MaxJob) {
should say
if ($jobs.Count -le $MaxJobs) {
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference