VMware Cloud Community
RickDaviesDT
Contributor
Contributor

Power CLI Script to Adjust vCPU and vMEM of Specific VM's

I am using a script I found in this forum to take a .CSV input file of specific VM's with recommendations of the "correct" number of vCPU's and vMEM according to a vRops rightsizing report. The numbers can go up or down depending on the rightsizing so I am trying to feed it a file named vropsreport.csv that has three columns in it with column titles "Name", "vCPU", and "vMEM" (sans quotes)

Here is the script:

function PowerOff-VM{ 

    param([string] $vm) 

     

    Shutdown-VMGuest -VM (Get-VM $vm) -Confirm:$false | Out-Null 

    Write-Host "Shutdown $vm" 

    do { 

        $status = (get-VM $vm).PowerState 

    }until($status -eq "PoweredOff") 

    return "OK" 

 

function PowerOn-VM{ 

    param( [string] $vm) 

     

    if($vm -eq ""){    Write-Host "Please enter a valild VM name"} 

     

    if((Get-VM $vm).powerstate -eq "PoweredOn"){ 

        Write-Host "$vm is already powered on"} 

     

    else{ 

        Start-VM -VM (Get-VM $vm) -Confirm:$false | Out-Null 

        Write-Host "Starting $vm" 

        do { 

            $status = (Get-vm $vm | Get-View).Guest.ToolsRunningStatus 

        }until($status -eq "guestToolsRunning") 

        return "OK" 

    } 

 

$VIServer = Connect-VIServer "vcenter"  

If ($VIServer.IsConnected -ne $true){ 

  Write-Host "Error connecting to your vCenter" -ForegroundColor Red 

  exit 

}

$vms = Import-CSV .\vcopsreport.csv 

foreach($vm in Get-VM -Name ($vm | Select -ExpandProperty "Name")){ 

 

  if($vm."vMEM" -or $vms."vCPU" -ne "0"){ 

    $poweroff = PowerOff-VM $vm.Name 

    if($poweroff -eq "Ok"){ 

      Write-Host "PowerOff OK" 

      if($vm."vMEM" -ne "0"){ 

         

      Set-VM $vm.name -MemoryGB $vm."vMEM" -Confirm:$False 

      Write-Host "The new configured amount of memory is"(Get-VM $VM).MemoryGB 

         

      } 

 

     if($vms."vCPU" -ne "0"){ 

     Set-VM $vm.name -NumCPU $vm."vCPU" -Confirm:$False 

     Write-Host "The new configured number of vCPU's is"(Get-VM $VM).NumCPU 

    
      } 

 

      $poweron = PowerOn-VM $vm.Name 

      if($poweron -eq "Ok"){ 

        Write-Host "PowerOn OK"} 

    } 

  } 

 

Disconnect-VIServer -Confirm:$false

Stepping through the script I can watch it connect to the vCenter, pull in the file and see it delineate the specific name, vCPU, and vMEM settings:

image1.png

However, when it gets down to doing the evaluation of each machine's specific numbers, in the if portion of the script:

if($vms."vMEM" -or $vms."vCPU" -ne "0"){ 

    $poweroff = PowerOff-VM $vms.Name 

    if($poweroff -eq "Ok"){ 

      Write-Host "PowerOff OK" 

      if($vms."vMEM" -ne "0"){ 

I get this:

image2.png

but I can see the vCPU but that also fails:

image4.png

The script doesnt seem to be parsing out the individual VM entries from the .CSV file and Ive been banging my head against the wall to figure out why.  When the script runs the rest of the way, this is the ultimate error message I get when it tries to apply the changes to the individual VM's:

image3.png

and then this is the error I see in the debug window for the vMEM:

Set-VM : Cannot bind parameter 'MemoryGB' to the target. Exception setting "MemoryGB": "Cannot convert null to type "System.Decimal"."

At C:\Users\daviesri\Desktop\RightSize.ps1:48 char:38

+           Set-VM $vms.name -MemoryGB $vms."vMEM" -Confirm:$False

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

    + CategoryInfo          : WriteError: (:) [Set-VM], ParameterBindingException

    + FullyQualifiedErrorId : ParameterBindingFailed,VMware.VimAutomation.ViCore.Cmdlets.Commands.SetVM

and then this is the error I see when trying to change the CPU:

image5.png

and the associated error in the debugger:

Set-VM : Cannot validate argument on parameter 'NumCpu'. The argument is null, empty, or an element of the argument collection contains a null value.

Supply a collection that does not contain any null values and then try the command again.

At C:\Users\daviesri\Desktop\RightSize.ps1:54 char:34

+         Set-VM $vms.name -NumCPU $vms."vCPU" -Confirm:$False

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

    + CategoryInfo          : InvalidData: (:) [Set-VM], ParameterBindingValidationException

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

I believe the errors are because the numbers arent being passed but I cant figure out why and Im sure it is something simple I am missing.

I would greatly appreciate some assistance from some PowerCLI Masters please on what I am doing wrong.

I am running Windows 10 using PowerShell as admin with the PowerCLI add-on for PowerShell.

If there is any more info you need me to provide, please let me know and Ill respond as soon as I can. I am not a scriptwriter normally but am trying to automate some things in our lab to "fix" vCPU and vMEM overuse.

Thanks,

--Rick

0 Kudos
3 Replies
LucD
Leadership
Leadership

From the 1st screenshot it looks as if you use $vms to read the CSV file, but also as the variable in the foreach loop.

While the script itself says $vm in the foreach loop, the screenshot seems to say $vms.


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

0 Kudos
RickDaviesDT
Contributor
Contributor

Hi Luc,

Thanks and yes, they are different from me trying numerous ways of defining the variables. My eyes are crossed (and Im off work at the moment for now) so I will go back and make sure everything is defined correctly, but even at its base, when I just changed the few items from the original script it didnt seem to work then.  Ill fix the variable issues tomorrow and follow-up then if I find it still not working.

Thanks for responding!

--Rick

0 Kudos
Proviant
Contributor
Contributor

Hi Rick,

Did you ever get this working?

0 Kudos