VMware Cloud Community
BBB36
Enthusiast
Enthusiast
Jump to solution

Update Video Ram. Wait for task to complete before proceeding to next action.

Hi all. My objective is the following:

1) Stop VM

2) Take snapshot

3) Update video ram to new value

4) Start VM

I want each task to be confirmed as complete before proceeding to the next task.

The VMs are in a CSV file.

The stop VM and take snapshot completes successfully. Although there's an error in the second part (screen output).

It doesn't actually update the video ram but just prints out the part stating the script will complete before powering on the VM and it gets stuck there because the VMs are actually not powered on.

The screen output is below:

*****************************************************************************************

PS C:\PowerCLI\scripts\set_video_ram> C:\PowerCLI\Scripts\set_video_ram\update_vram_poweroff_snapshot.ps1

vm1 is now being powered off. The script will confirm all VMs are powered off before proceeding to the next task...

vm2 is now being powered off. The script will confirm all VMs are powered off before proceeding to the next task...

Name                 PowerState Num CPUs MemoryGB      

----                 ---------- -------- --------      

vm1          PoweredOff 1        4.000         

Snapshot of vm1 is being taken before configuration change. The script will confirm all VM snapshots are complete before proceeding to the next task...

Exception calling "ContainsKey" with "1" argument(s): "Key cannot be null.

Parameter name: key"

At H:\PowerCLI\Scripts\set_video_ram\update_vram_poweroff_snapshot.ps1:68 char:2

+     elseif($taskTab.ContainsKey($_.Id) -and $_.State -eq "Error"){

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : ArgumentNullException

vm2          PoweredOff 1        2.000         

Snapshot of vm2 is being taken before configuration change. The script will confirm all VM snapshots are complete before proceeding to the next task...

Exception calling "ContainsKey" with "1" argument(s): "Key cannot be null.

Parameter name: key"

At H:\PowerCLI\Scripts\set_video_ram\update_vram_poweroff_snapshot.ps1:68 char:2

+     elseif($taskTab.ContainsKey($_.Id) -and $_.State -eq "Error"){

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

    + FullyQualifiedErrorId : ArgumentNullException

The scrript will wait for the configuration task to be complete before the VMs are powered on

The scrript will wait for the configuration task to be complete before the VMs are powered on

The scrript will wait for the configuration task to be complete before the VMs are powered on

The scrript will wait for the configuration task to be complete before the VMs are powered on

The scrript will wait for the configuration task to be complete before the VMs are powered on

The scrript will wait for the configuration task to be complete before the VMs are powered on

The scrript will wait for the configuration task to be complete before the VMs are powered on

The scrript will wait for the configuration task to be complete before the VMs are powered on

The scrript will wait for the configuration task to be complete before the VMs are powered on

The script snippet is below:

***********************************************************************************

$newVideoRamSize = 9000

$vmlist = Import-Csv .\vmlist.csv -UseCulture

$vmlist1 = $vmlist | select -ExpandProperty VM

$taskTab = @{}

#Shutdown VMs

    foreach ($vm in $vmlist1) {

    #if($vm.Powerstate -eq "PoweredOn") { //FYI If this part is not commented out, the script will run without doing anything.

    Write-Host $vm is now being powered off. The script will confirm all VMs are powered off before proceeding to the next task... -foregroundcolor green

    $taskTab[(Stop-VM -VM $vm -Confirm:$false -RunAsync).Id] = $vm

}

#}

#Take snapshot of VMs

    $runningTasks = $taskTab.Count

while($runningTasks -gt 0){

Get-Task | % {

if($taskTab.ContainsKey($_.Id) -and $_.State -eq "Success"){

    Get-VM $taskTab[$_.Id]

    Write-Host Snapshot of $taskTab[$_.Id] is being taken before configuration change. The script will confirm all VM snapshots are complete before proceeding to the next task... -foregroundcolor green

    $tasktab[(New-Snapshot -VM $taskTab[$_.Id] -Name BeforeVideoRamChange -RunAsync).Id] = $vm

    $taskTab.Remove($_.Id)

$runningTasks--

}

}

elseif($taskTab.ContainsKey($_.Id) -and $_.State -eq "Error"){

$taskTab.Remove($_.Id)

$runningTasks--

}

}

Start-Sleep -Seconds 15

#Update Video Ram

    $runningTasks = $taskTab.Count

while($runningTasks -gt 0){

Get-Task | % {

if($taskTab.ContainsKey($_.Id) -and $_.State -eq "Success"){

    Get-VM $taskTab[$_.Id]

    if($taskTab[$_.Id].Powerstate -eq "PoweredOn")

    {return "One or more VMs is still powered on. Manually power off VMs before re-attempting."}

$vid = $taskTab[$_.Id].ExtensionData.Config.Hardware.Device | ?{$_.GetType().Name -eq "VirtualMachineVideoCard"}

    $spec = New-Object VMware.Vim.VirtualMachineConfigSpec

    $devChange = New-Object VMware.Vim.VirtualDeviceConfigSpec

    $devChange.Operation = 'edit'

    $vid.videoRamSizeInKB = $newVideoRamSize

       

    if ((!$devChange.Operation) -or (!$vid.videoRamSizeInKB))

    {return "ERROR: Unable to set video memory on $taskTab[$_.Id]}. Ensure it is powered off."}

Write-Host Video Memory on VM: $taskTab[$_.Id] has been successfully set to $vid.videoRamSizeInKB -foregroundcolor green

       

$devChange.Device += $vid

$spec.DeviceChange += $devChange

$taskTab[$_.Id].ExtensionData.ReconfigVM($spec)

    $taskTab.Remove($_.Id)

$runningTasks--

}

elseif($taskTab.ContainsKey($_.Id) -and $_.State -eq "Error"){

$taskTab.Remove($_.Id)

$runningTasks--

}

Start-Sleep -Seconds 15

   

Write-Host The script will wait for the configuration task to be complete before the VMs are powered on -foregroundcolor green

    }

}

#Power on VMs

    $runningTasks = $taskTab.Count

while($runningTasks -gt 0){

Get-Task | % {

if($taskTab.ContainsKey($_.Id) -and $_.State -eq "Success"){

    Get-VM $taskTab[$_.Id]

    if($taskTab[$_.Id].Powerstate -eq "PoweredOff") {

    Write-Host $taskTab[$_.Id] is now being powered on. Please wait five to ten minutes before verifying new configuration -foregroundcolor green

    $taskTab[(Start-VM -VM $taskTab[$_.Id] -Confirm:$false -RunAsync).Id] = $vm

    }

}

}

}

*****************************************************************************************

Any help to point out the issues and/or fix the script would be greatly appreciated.

1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

The issue is most likely because you the VirtualMachine in the hash table (with the Key of the TakId).

But such a VirtualMachine object is not updated automatically.

You will for example not see that the powerstate of the VM has changed.

For that you have to 'refresh' the object, by doing a new Get-VM.

Something like this

$newVideoRamSize = 9000

$vmlist = Import-Csv .\vmlist.csv -UseCulture

$vmlist1 = $vmlist | select -ExpandProperty VM

$taskTab = @{ }

#Shutdown VMs

foreach ($vm in $vmlist1) {

    #if($vm.Powerstate -eq "PoweredOn") { //FYI If this part is not commented out, the script will run without doing anything.

    Write-Host $vm is now being powered off. The script will confirm all VMs are powered off before proceeding to the next task... -foregroundcolor green

    $taskTab[(Stop-VM -VM $vm -Confirm:$false -RunAsync).Id] = $vm

}

#}

#Take snapshot of VMs

$runningTasks = $taskTab.Count

while ($runningTasks -gt 0) {

    Get-Task | % {

        if ($taskTab.ContainsKey($_.Id) -and $_.State -eq "Success") {

            $vm = Get-VM $taskTab[$_.Id]

            Write-Host "Snapshot of $($vm.Name) is being taken before configuration change. The script will confirm all VM snapshots are complete before proceeding to the next task..." -foregroundcolor green

            $tasktab[(New-Snapshot -VM $vm -Name BeforeVideoRamChange -RunAsync).Id] = $vm

            $taskTab.Remove($_.Id)

            $runningTasks--

        }

        elseif ($taskTab.ContainsKey($_.Id) -and $_.State -eq "Error") {

            $taskTab.Remove($_.Id)

            $runningTasks--

        }

    }

    Start-Sleep -Seconds 15

    #Update Video Ram

    $runningTasks = $taskTab.Count

    while ($runningTasks -gt 0) {

        Get-Task | % {

            if ($taskTab.ContainsKey($_.Id) -and $_.State -eq "Success") {

                $vm = Get-VM -Name ($taskTab[$_.Id]).Name

                if ($vm.Powerstate -eq "PoweredOn") {

                    return "One or more VMs is still powered on. Manually power off VMs before re-attempting."

                }

                $vid = $vm.ExtensionData.Config.Hardware.Device | ? { $_.GetType().Name -eq "VirtualMachineVideoCard" }

                $spec = New-Object VMware.Vim.VirtualMachineConfigSpec

                $devChange = New-Object VMware.Vim.VirtualDeviceConfigSpec

                $devChange.Operation = 'edit'

                $vid.videoRamSizeInKB = $newVideoRamSize

     

                if ((!$devChange.Operation) -or (!$vid.videoRamSizeInKB)){

                    return "ERROR: Unable to set video memory on $taskTab[$_.Id]}. Ensure it is powered off."

                }

                Write-Host Video Memory on VM: $taskTab[$_.Id] has been successfully set to $vid.videoRamSizeInKB -foregroundcolor green

     

                $devChange.Device += $vid

                $spec.DeviceChange += $devChange

                $vm.ExtensionData.ReconfigVM($spec)

                $taskTab.Remove($_.Id)

                $runningTasks--

            }

            elseif ($taskTab.ContainsKey($_.Id) -and $_.State -eq "Error") {

                $taskTab.Remove($_.Id)

                $runningTasks--

            }

            Start-Sleep -Seconds 15

 

            Write-Host The script will wait for the configuration task to be complete before the VMs are powered on -foregroundcolor green

        }

    }

    #Power on VMs

    $runningTasks = $taskTab.Count

    while ($runningTasks -gt 0) {

        Get-Task | % {

            if ($taskTab.ContainsKey($_.Id) -and $_.State -eq "Success") {

                $vm = Get-VM -Name (Get-VM $taskTab[$_.Id]).Name

                if ($vm.Powerstate -eq "PoweredOff") {

                    Write-Host "$($vm.Name) is now being powered on. Please wait five to ten minutes before verifying new configuration" -foregroundcolor green

                    $taskTab[(Start-VM -VM $vm -Confirm:$false -RunAsync).Id] = $vm

                }

            }

        }

    }

}


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

View solution in original post

13 Replies
LucD
Leadership
Leadership
Jump to solution

If there are client-side tasks, there will not be an Id property, hence the error.

Try changing those lines to

    Get-Task | where{$_.Id} | % {


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

Reply
0 Kudos
BBB36
Enthusiast
Enthusiast
Jump to solution

Hi LucD,

Thanks for your response, and I appreciate your help always. I did make the changes as suggested but got the same errors.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

There must be one or more tasks that do not have an Id.

Can you check with

Get-Task | Select Name,StartTime,Id


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

Reply
0 Kudos
BBB36
Enthusiast
Enthusiast
Jump to solution

Do you mean logging in to the vCSA and running this?

PS C:\Users\myuserid> Get-Task | Select Name,StartTime,Id

Result of the above here:

Name            StartTime           Id

----            ---------           --

CloneVM_Task    10/08/2019 15:04:16 Task-task-234068

UpgradeVM_Task  10/08/2019 15:04:46 Task-task-234589

ReconfigVM_Task 10/08/2019 15:04:57 Task-task-234565

ReconfigVM_Task 10/08/2019 15:05:13 Task-task-234665

CloneVM_Task    10/08/2019 15:05:33 Task-task-234555

UpgradeVM_Task  10/08/2019 15:05:53 Task-task-233445

Or do you mean I need to update the script with the Get-Task | Select Name,StartTime,Id?

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

I had another look at your script, and there is a brace too much after the if-statement.
The elseif part was not inside the foreach block.
Change the code to

#Take snapshot of VMs

$runningTasks = $taskTab.Count

while ($runningTasks -gt 0) {

    Get-Task | % {

        if ($taskTab.ContainsKey($_.Id) -and $_.State -eq "Success") {

            Get-VM $taskTab[$_.Id]

            Write-Host Snapshot of $taskTab[$_.Id] is being taken before configuration change. The script will confirm all VM snapshots are complete before proceeding to the next task... -foregroundcolor green

            $tasktab[(New-Snapshot -VM $taskTab[$_.Id] -Name BeforeVideoRamChange -RunAsync).Id] = $vm

            $taskTab.Remove($_.Id)

            $runningTasks--

        } # Removed extra brace <===

        elseif ($taskTab.ContainsKey($_.Id) -and $_.State -eq "Error") {

            $taskTab.Remove($_.Id)

            $runningTasks--

        }

    }

    Start-Sleep -Seconds 15


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

Reply
0 Kudos
BBB36
Enthusiast
Enthusiast
Jump to solution

Hmm. Tried that but it says it's missing a closing brace. See attached Capture.PNGimage.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

When you take a brace away there, you have to add one at the end.

$newVideoRamSize = 9000

$vmlist = Import-Csv .\vmlist.csv -UseCulture

$vmlist1 = $vmlist | select -ExpandProperty VM

$taskTab = @{ }

#Shutdown VMs

foreach ($vm in $vmlist1) {

    #if($vm.Powerstate -eq "PoweredOn") { //FYI If this part is not commented out, the script will run without doing anything.

    Write-Host $vm is now being powered off. The script will confirm all VMs are powered off before proceeding to the next task... -foregroundcolor green

    $taskTab[(Stop-VM -VM $vm -Confirm:$false -RunAsync).Id] = $vm

}

#}

#Take snapshot of VMs

$runningTasks = $taskTab.Count

while ($runningTasks -gt 0) {

    Get-Task | % {

        if ($taskTab.ContainsKey($_.Id) -and $_.State -eq "Success") {

            Get-VM $taskTab[$_.Id]

            Write-Host Snapshot of $taskTab[$_.Id] is being taken before configuration change. The script will confirm all VM snapshots are complete before proceeding to the next task... -foregroundcolor green

            $tasktab[(New-Snapshot -VM $taskTab[$_.Id] -Name BeforeVideoRamChange -RunAsync).Id] = $vm

            $taskTab.Remove($_.Id)

            $runningTasks--

        }

        elseif ($taskTab.ContainsKey($_.Id) -and $_.State -eq "Error") {

            $taskTab.Remove($_.Id)

            $runningTasks--

        }

    }

    Start-Sleep -Seconds 15

    #Update Video Ram

    $runningTasks = $taskTab.Count

    while ($runningTasks -gt 0) {

        Get-Task | % {

            if ($taskTab.ContainsKey($_.Id) -and $_.State -eq "Success") {

                Get-VM $taskTab[$_.Id]

                if ($taskTab[$_.Id].Powerstate -eq "PoweredOn") {

                    return "One or more VMs is still powered on. Manually power off VMs before re-attempting."

                }

                $vid = $taskTab[$_.Id].ExtensionData.Config.Hardware.Device | ? { $_.GetType().Name -eq "VirtualMachineVideoCard" }

                $spec = New-Object VMware.Vim.VirtualMachineConfigSpec

                $devChange = New-Object VMware.Vim.VirtualDeviceConfigSpec

                $devChange.Operation = 'edit'

                $vid.videoRamSizeInKB = $newVideoRamSize

     

                if ((!$devChange.Operation) -or (!$vid.videoRamSizeInKB)){

                    return "ERROR: Unable to set video memory on $taskTab[$_.Id]}. Ensure it is powered off."

                }

                Write-Host Video Memory on VM: $taskTab[$_.Id] has been successfully set to $vid.videoRamSizeInKB -foregroundcolor green

     

                $devChange.Device += $vid

                $spec.DeviceChange += $devChange

                $taskTab[$_.Id].ExtensionData.ReconfigVM($spec)

                $taskTab.Remove($_.Id)

                $runningTasks--

            }

            elseif ($taskTab.ContainsKey($_.Id) -and $_.State -eq "Error") {

                $taskTab.Remove($_.Id)

                $runningTasks--

            }

            Start-Sleep -Seconds 15

 

            Write-Host The script will wait for the configuration task to be complete before the VMs are powered on -foregroundcolor green

        }

    }

    #Power on VMs

    $runningTasks = $taskTab.Count

    while ($runningTasks -gt 0) {

        Get-Task | % {

            if ($taskTab.ContainsKey($_.Id) -and $_.State -eq "Success") {

                Get-VM $taskTab[$_.Id]

                if ($taskTab[$_.Id].Powerstate -eq "PoweredOff") {

                    Write-Host $taskTab[$_.Id] is now being powered on. Please wait five to ten minutes before verifying new configuration -foregroundcolor green

                    $taskTab[(Start-VM -VM $taskTab[$_.Id] -Confirm:$false -RunAsync).Id] = $vm

                }

            }

        }

    }

}


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

Reply
0 Kudos
BBB36
Enthusiast
Enthusiast
Jump to solution

Yep. You're right. I updated the script. Thank you.

It took only the snapshot of one of the 2 VMs though. Also, now it's just stuck at "The script will wait for the configuration task to be complete before the VMs are powered on" and doesn't progress to update the video ram and start up the VMs. See results below. Any ideas?

*********************************************************************************************

PS C:\PowerCLI\> C:\PowerCLI\update_vram_poweroff_snapshot.ps1

VM1 is now being powered off. The script will confirm all VMs are powered off before proceeding to the next task...

VM2 is now being powered off. The script will confirm all VMs are powered off before proceeding to the next task...

Name                 PowerState Num CPUs MemoryGB      

----                 ---------- -------- --------      

VM1          PoweredOff 1        4.000         

Snapshot of VM1 is being taken before configuration change. The script will confirm all VM snapshots are complete before proceeding to the next task...

The script will wait for the configuration task to be complete before the VMs are powered on

The script will wait for the configuration task to be complete before the VMs are powered on

The script will wait for the configuration task to be complete before the VMs are powered on

The script will wait for the configuration task to be complete before the VMs are powered on

The script will wait for the configuration task to be complete before the VMs are powered on

The script will wait for the configuration task to be complete before the VMs are powered on

The script will wait for the configuration task to be complete before the VMs are powered on

The script will wait for the configuration task to be complete before the VMs are powered on

The script will wait for the configuration task to be complete before the VMs are powered on

The script will wait for the configuration task to be complete before the VMs are powered on

The script will wait for the configuration task to be complete before the VMs are powered on

The script will wait for the configuration task to be complete before the VMs are powered on

The script will wait for the configuration task to be complete before the VMs are powered on

The script will wait for the configuration task to be complete before the VMs are powered on

The script will wait for the configuration task to be complete before the VMs are powered on

PS C:\PowerCLI\>

Reply
0 Kudos
BBB36
Enthusiast
Enthusiast
Jump to solution

Do I need to change this:

$_.Id) -and $_.State -eq "Success") to this:

$_.Status) -and $_.State -eq "Completed") to match the tab name and actual results in vCenter tasks perhaps?

Reply
0 Kudos
BBB36
Enthusiast
Enthusiast
Jump to solution

I'd also like to add, I have another version of this script, which actually does everything but I don't think the wait-task works. Here it is:

******************************************************************************************************************************************************

$newVideoRamSize = 9000

$vmlist1 = $vmlist | select -ExpandProperty VM

#Shutdown VMs

    foreach ($vm in $vmlist1) {

    $guestname = Get-VM $vm

    if($guestname.Powerstate -eq "PoweredOn") {

    Write-Host $guestname is now being powered off. The script will confirm all VMs are powered off before proceeding to the next task... -foregroundcolor green

    $shutvmtask = Stop-VM -VM $guestname -Confirm:$false -RunAsync | Out-Null }

    Wait-Task $shutvmtask

    Start-Sleep -Seconds 15

}

#Take snapshot of VMs

    foreach ($vm in $vmlist1) {

    $guestname = Get-VM $vm

    Write-Host Snapshot of $guestname is being taken before configuration change. The script will confirm all VM snapshots are complete before proceeding to the next task... -foregroundcolor green

    $snapshotvmtask = New-Snapshot -VM $guestname -Name BeforeVideoRamChange -RunAsync | Out-Null }

    Wait-Task $snapshotvmtask

    Start-Sleep -Seconds 15

#Update Video Ram

    foreach ($vm in $vmlist1) {

        $guestname = Get-VM $vm

        if($guestname.Powerstate -eq "PoweredOn")

        {return "One or more VMs is still powered on. Manually power off VMs before re-attempting."}

         $vid = $guestname.ExtensionData.Config.Hardware.Device | ?{$_.GetType().Name -eq "VirtualMachineVideoCard"}

        $spec = New-Object VMware.Vim.VirtualMachineConfigSpec

        $devChange = New-Object VMware.Vim.VirtualDeviceConfigSpec

        $devChange.Operation = 'edit'

        $vid.videoRamSizeInKB = $newVideoRamSize

       

        if ((!$devChange.Operation) -or (!$vid.videoRamSizeInKB))

        {return "ERROR: Unable to set video memory on $guestname}. Ensure it is powered off."}

Write-Host Video Memory on VM: $guestname has been successfully set to $vid.videoRamSizeInKB -foregroundcolor green

       

$devChange.Device += $vid

$spec.DeviceChange += $devChange

$vramconfigtask = $guestname.ExtensionData.ReconfigVM($spec)

        Wait-Task $vramconfigtask

        Start-Sleep -Seconds 15

        Write-Host The script will wait for the configuration task to be complete before the VMs are powered on -foregroundcolor green

}

#Power on VMs

    foreach ($vm in $vmlist1) {

    $guestname = Get-VM $vm

    if($guestname.Powerstate -eq "PoweredOff") {

    Write-Host $guestname is now being powered on. Please wait five to ten minutes before verifying new configuration -foregroundcolor green

    Start-VM -VM $guestname -Confirm:$false -RunAsync | Out-Null }

}

******************************************************************************************************************************************************

The output is below:

******************************************************************************************************************************************************

VM1 is now being powered off. The script will confirm all VMs are powered off before proceeding to the next task...

Wait-Task : Cannot validate argument on parameter 'Task'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.

At C:\PowerCLI\update_vram_poweroff_snapshot-Copy.ps1:53 char:15

+     Wait-Task $shutvmtask

+               ~~~~~~~~~~~

    + CategoryInfo          : InvalidData: (:) [Wait-Task], ParameterBindingValidationException

    + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.WaitTask

VM2 is now being powered off. The script will confirm all VMs are powered off before proceeding to the next task...

Wait-Task : Cannot validate argument on parameter 'Task'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.

At C:\PowerCLI\update_vram_poweroff_snapshot-Copy.ps1:53 char:15

+     Wait-Task $shutvmtask

+               ~~~~~~~~~~~

    + CategoryInfo          : InvalidData: (:) [Wait-Task], ParameterBindingValidationException

    + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.WaitTask

Snapshot of VM1 is being taken before configuration change. The script will confirm all VM snapshots are complete before proceeding to the next task...

Snapshot of VM2 is being taken before configuration change. The script will confirm all VM snapshots are complete before proceeding to the next task...

Wait-Task : Cannot validate argument on parameter 'Task'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.

At C:\PowerCLI\update_vram_poweroff_snapshot-Copy.ps1:62 char:15

+     Wait-Task $snapshotvmtask

+               ~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidData: (:) [Wait-Task], ParameterBindingValidationException

    + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.WaitTask

Video Memory on VM: VM1 has been successfully set to 9000

Wait-Task : Cannot validate argument on parameter 'Task'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.

At C:\PowerCLI\update_vram_poweroff_snapshot-Copy.ps1:85 char:19

+         Wait-Task $vramconfigtask

+                   ~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidData: (:) [Wait-Task], ParameterBindingValidationException

    + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.WaitTask

The scrript will wait for the configuration task to be complete before the VMs are powered on

Video Memory on VM: VM2 has been successfully set to 9000

Wait-Task : Cannot validate argument on parameter 'Task'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.

At C:\PowerCLI\update_vram_poweroff_snapshot-Copy.ps1:85 char:19

+         Wait-Task $vramconfigtask

+                   ~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidData: (:) [Wait-Task], ParameterBindingValidationException

    + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.WaitTask

The scrript will wait for the configuration task to be complete before the VMs are powered on

VM1 is now being powered on. Please wait five to ten minutes before verifying new configuration

VM2 is now being powered on. Please wait five to ten minutes before verifying new configuration

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

The issue is most likely because you the VirtualMachine in the hash table (with the Key of the TakId).

But such a VirtualMachine object is not updated automatically.

You will for example not see that the powerstate of the VM has changed.

For that you have to 'refresh' the object, by doing a new Get-VM.

Something like this

$newVideoRamSize = 9000

$vmlist = Import-Csv .\vmlist.csv -UseCulture

$vmlist1 = $vmlist | select -ExpandProperty VM

$taskTab = @{ }

#Shutdown VMs

foreach ($vm in $vmlist1) {

    #if($vm.Powerstate -eq "PoweredOn") { //FYI If this part is not commented out, the script will run without doing anything.

    Write-Host $vm is now being powered off. The script will confirm all VMs are powered off before proceeding to the next task... -foregroundcolor green

    $taskTab[(Stop-VM -VM $vm -Confirm:$false -RunAsync).Id] = $vm

}

#}

#Take snapshot of VMs

$runningTasks = $taskTab.Count

while ($runningTasks -gt 0) {

    Get-Task | % {

        if ($taskTab.ContainsKey($_.Id) -and $_.State -eq "Success") {

            $vm = Get-VM $taskTab[$_.Id]

            Write-Host "Snapshot of $($vm.Name) is being taken before configuration change. The script will confirm all VM snapshots are complete before proceeding to the next task..." -foregroundcolor green

            $tasktab[(New-Snapshot -VM $vm -Name BeforeVideoRamChange -RunAsync).Id] = $vm

            $taskTab.Remove($_.Id)

            $runningTasks--

        }

        elseif ($taskTab.ContainsKey($_.Id) -and $_.State -eq "Error") {

            $taskTab.Remove($_.Id)

            $runningTasks--

        }

    }

    Start-Sleep -Seconds 15

    #Update Video Ram

    $runningTasks = $taskTab.Count

    while ($runningTasks -gt 0) {

        Get-Task | % {

            if ($taskTab.ContainsKey($_.Id) -and $_.State -eq "Success") {

                $vm = Get-VM -Name ($taskTab[$_.Id]).Name

                if ($vm.Powerstate -eq "PoweredOn") {

                    return "One or more VMs is still powered on. Manually power off VMs before re-attempting."

                }

                $vid = $vm.ExtensionData.Config.Hardware.Device | ? { $_.GetType().Name -eq "VirtualMachineVideoCard" }

                $spec = New-Object VMware.Vim.VirtualMachineConfigSpec

                $devChange = New-Object VMware.Vim.VirtualDeviceConfigSpec

                $devChange.Operation = 'edit'

                $vid.videoRamSizeInKB = $newVideoRamSize

     

                if ((!$devChange.Operation) -or (!$vid.videoRamSizeInKB)){

                    return "ERROR: Unable to set video memory on $taskTab[$_.Id]}. Ensure it is powered off."

                }

                Write-Host Video Memory on VM: $taskTab[$_.Id] has been successfully set to $vid.videoRamSizeInKB -foregroundcolor green

     

                $devChange.Device += $vid

                $spec.DeviceChange += $devChange

                $vm.ExtensionData.ReconfigVM($spec)

                $taskTab.Remove($_.Id)

                $runningTasks--

            }

            elseif ($taskTab.ContainsKey($_.Id) -and $_.State -eq "Error") {

                $taskTab.Remove($_.Id)

                $runningTasks--

            }

            Start-Sleep -Seconds 15

 

            Write-Host The script will wait for the configuration task to be complete before the VMs are powered on -foregroundcolor green

        }

    }

    #Power on VMs

    $runningTasks = $taskTab.Count

    while ($runningTasks -gt 0) {

        Get-Task | % {

            if ($taskTab.ContainsKey($_.Id) -and $_.State -eq "Success") {

                $vm = Get-VM -Name (Get-VM $taskTab[$_.Id]).Name

                if ($vm.Powerstate -eq "PoweredOff") {

                    Write-Host "$($vm.Name) is now being powered on. Please wait five to ten minutes before verifying new configuration" -foregroundcolor green

                    $taskTab[(Start-VM -VM $vm -Confirm:$false -RunAsync).Id] = $vm

                }

            }

        }

    }

}


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

BBB36
Enthusiast
Enthusiast
Jump to solution

Thanks. I updated the script but unfortunately it's the same result as before,i.e. "The script will wait for the configuration task to be complete before the VMs are powered on" and doesn't progress to update the video ram and start up the VMs.

I'll go through the script again more carefully and post results later today or tomorrow. Thank you so much for all your time!

Reply
0 Kudos
BBB36
Enthusiast
Enthusiast
Jump to solution

Hey LucD, I made some modifications. Now the script works. I had to however remove some of the "tasktab" and error control portions in the #Shutdown VMs and #Power on VMs sections of the script for it to work. I'm sure I'm just missing something small but I needed to get this working ASAP and also don't have the knowledge yet to fix it quickly. Anyway, here's the final script. If you or anyone else can enhance it that would be greatly appreciated! Thanks so much for all your help!

******************************************************************************************************************************************************************************

$newVideoRamSize = 9000

$vmlist = Import-Csv .\vmlist.csv -UseCulture

$vmlist1 = $vmlist | select -ExpandProperty VM

$taskTab = @{ }

#Shutdown VMs

foreach ($vm in $vmlist1) {

    Write-Host $vm will shutdown in preparation for the Video Ram configuration change. -foregroundcolor green

    $taskTab[(Stop-VM -VM $vm -Confirm:$false -RunAsync).Id] = $vm

}

Start-Sleep -Seconds 30

#Take snapshot of VMs

$runningTasks = $taskTab.Count

while ($runningTasks -gt 0) {

   Get-Task | % {

      if ($taskTab.ContainsKey($_.Id) -and $_.State -eq "Success") {

         $vm = Get-VM $taskTab[$_.Id]

         Write-Host $vm snapshot is being taken before the configuration change should a rollback be necessary. -foregroundcolor green

         $tasktab[(New-Snapshot -VM $taskTab[$_.Id] -Name BeforeVideoRamChange -RunAsync).Id] = $vm

         $taskTab.Remove($_.Id)

         $runningTasks--

       }

        elseif ($taskTab.ContainsKey($_.Id) -and $_.State -eq "Error") {

        $taskTab.Remove($_.Id)

        $runningTasks--

       }

    }

  }

Start-Sleep -Seconds 30

#Update Video Ram

foreach ($vm in $vmlist1) {

$runningTasks = $taskTab.Count

while ($runningTasks -gt 0) {

   Get-Task | % {

       if ($taskTab.ContainsKey($_.Id) -and $_.State -eq "Success") {

          $vm = Get-VM ($taskTab[$_.Id]).Name

             if ($vm.Powerstate -eq "PoweredOn") {

             return "$vm is still powered on. Manually power off VMs before re-attempting."

       }

          $vid = $vm.ExtensionData.Config.Hardware.Device | ? { $_.GetType().Name -eq "VirtualMachineVideoCard" }

          $spec = New-Object VMware.Vim.VirtualMachineConfigSpec

          $devChange = New-Object VMware.Vim.VirtualDeviceConfigSpec

          $devChange.Operation = 'edit'

          $vid.videoRamSizeInKB = $newVideoRamSize

          if ((!$devChange.Operation) -or (!$vid.videoRamSizeInKB)){

          return "ERROR: Unable to set video memory on $($vm.Name). Ensure it is powered off."

       }

          Write-Host $($vm.Name) video memory has been successfully set to $newVideoRamSize -foregroundcolor green

          $devChange.Device += $vid

          $spec.DeviceChange += $devChange

          $vm.ExtensionData.ReconfigVM($spec)

          $taskTab.Remove($_.Id)

          $runningTasks--

       }

          elseif ($taskTab.ContainsKey($_.Id) -and $_.State -eq "Error") {

          $taskTab.Remove($_.Id)

          $runningTasks--

       }

     }

   }

}

Start-Sleep -Seconds 30

#Power on VMs

foreach ($vm in $vmlist1) {

    Write-Host $vm is being powered back on. -foregroundcolor green

    $taskTab[(Start-VM -VM $vm -Confirm:$false -RunAsync).Id] = $vm

}

Start-Sleep -Seconds 30

Write-Host Configuration complete. Confirm new change in 5 to 10 minutes. -foregroundcolor green

Reply
0 Kudos