VMware Cloud Community
Arkady
Contributor
Contributor

Decreasing number of CPUs on multiple VMs

Hello,

We have many VMs with over provisioned CPUs, need to remove 1 CPU from them.

Appreciate any help.

Thank you in advance!

0 Kudos
18 Replies
LucD
Leadership
Leadership

Is there a list of VMs, in a text file?
Are these VMs powered off?

Or does the script need to take care of that?

And do all the VMs have the VMware Tools installed and running?


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

0 Kudos
LucD
Leadership
Leadership

This is for a specific VM.
The script checks the powerstate, and brings the VM back to that state when the CPU number is lowered by 1.

Also I builtin a safety for VMs that only have 1 vcpu

$vmName = 'MyVM'

foreach($vm in Get-VM -Name $vmName){

    if($vm.NumCpu -ne 1){

        $wasPoweredOn = $false

        if($vm.PowerState -ne 'PoweredOff'){

            $wasPoweredOn = $true

            Shutdown-VMGuest -VM $vm

            while($vm.PowerState -ne 'PoweredOff'){

                sleep 5

                $vm = Get-VM -Name $vm.Name

            }

        }

        $vm = Set-VM -VM $vm -NumCpu ($vm.NumCpu - 1) -Confirm:$false

        if($wasPoweredOn){

            Start-VM -VM $vm -Confirm:$false

        }

    }

    else{

        Write-Output "VM $vm.Name only has 1 vcpu"

    }

}


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

0 Kudos
Arkady
Contributor
Contributor

Yes, there will be a list of VMs in a text file.

These VMs are powered on with VMware tools installed

0 Kudos
LucD
Leadership
Leadership

That is a slight modification of the previous script

$vmnames = '.\vmnames.txt'

foreach($vm in Get-VM -Name (Get-Content -Path $vmnames)){

    if($vm.NumCpu -ne 1){

        $wasPoweredOn = $false

        if($vm.PowerState -ne 'PoweredOff'){

            $wasPoweredOn = $true

            Shutdown-VMGuest -VM $vm

            while($vm.PowerState -ne 'PoweredOff'){

                sleep 5

                $vm = Get-VM -Name $vm.Name

            }

        }

        $vm = Set-VM -VM $vm -NumCpu ($vm.NumCpu - 1) -Confirm:$false

        if($wasPoweredOn){

            Start-VM -VM $vm -Confirm:$false

        }

    }

    else{

        Write-Output "VM $vm.Name only has 1 vcpu"

    }

}


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

0 Kudos
Arkady
Contributor
Contributor

Thank you!

I will test and let you know.

0 Kudos
Arkady
Contributor
Contributor

These VMs are Windows 7 and support maximum 2 CPUs but any number of cores.

So to configure 3 CPUs VM has 1 CPU and 3 cores  for example. So to decrease a number of CPUs we need to decrease a number of cores.

Would be possible to modify the script?

0 Kudos
LucD
Leadership
Leadership

If you 1 CPU block with 3 cores and you change NumCPU to 2, you will end up with 1 CPU block with 2 cores.

Or do you mean something else?


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

0 Kudos
Arkady
Contributor
Contributor

Current configuration for example 1 CPU and 3 cores. Need to change to 1 CPU and 2 cores instead

0 Kudos
LucD
Leadership
Leadership

Ok, got you.

Try like this, but note that this solution has a flaw if you have more than 1 CPU block.

Assume you have configured 2 CPU blocks, each with 3 cores. That gives 6 for NumCPU.

Lowering that to 5 will not work, you can only lower to 4, and change the CoresPerBlock from 3 to 2.

$vmName = 'MyVM'

foreach($vm in Get-VM -Name $vmName){

   if($vm.NumCpu -ne 1){

   $wasPoweredOn = $false

   if($vm.PowerState -ne 'PoweredOff'){

   $wasPoweredOn = $true

  Shutdown-VMGuest -VM $vm

   while($vm.PowerState -ne 'PoweredOff'){

  sleep 5

   $vm = Get-VM -Name $vm.Name

   }

   }

   if($vm.CoresPerSocket -gt 1){

     $vm = Set-VM -VM $vm -NumCpu ($vm.NumCpu - 1) -CoresPerSocket ($vm.CoresPersocket - 1) -Confirm:$false

   }

   else{

     $vm = Set-VM -VM $vm -NumCpu ($vm.NumCpu - 1) -Confirm:$false

   }


   if($wasPoweredOn){

   Start-VM -VM $vm -Confirm:$false

   }

   }

   else{

   Write-Output "VM $vm.Name only has 1 vcpu"

   }

}


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

0 Kudos
Arkady
Contributor
Contributor

This is what happened - please attached screen shot6-21-2018 2-28-34 PM.jpg

Changed Total number of cores to 2 but still report Number of cores per socket as 3

0 Kudos
LucD
Leadership
Leadership

Did you start the VM?


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

0 Kudos
Arkady
Contributor
Contributor

Yes

0 Kudos
LucD
Leadership
Leadership

That seems ot be an issue with the Set-VM cmdlet, because it actually says total number of cores is 2.

While the cores per socket keeps saying 3.

Perhaps we should try the ReconfigVM method?


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

0 Kudos
Arkady
Contributor
Contributor

Not familiar with this

0 Kudos
LucD
Leadership
Leadership

Try this way.

$vmName = 'MyVM'

foreach($vm in Get-VM -Name $vmName){

   if($vm.NumCpu -ne 1){

   $wasPoweredOn = $false

   if($vm.PowerState -ne 'PoweredOff'){

   $wasPoweredOn = $true

  Shutdown-VMGuest -VM $vm

   while($vm.PowerState -ne 'PoweredOff'){

  sleep 5

   $vm = Get-VM -Name $vm.Name

   }

   }

   if($vm.CoresPerSocket -gt 1){

   $spec = New-Object VMware.Vim.VirtualMachineConfigSpec

   $spec.NumCoresPerSocket = $vm.CoresPersocket - 1

   $spec.NumCPUs = $vm.NumCpu - 1


   $vm.ExtensionData.ReconfigVM($spec)

   }

   else{

   $vm = Set-VM -VM $vm -NumCpu ($vm.NumCpu - 1) -Confirm:$false

   }


   if($wasPoweredOn){

   Start-VM -VM $vm -Confirm:$false

   }

   }

   else{

   Write-Output "VM $vm.Name only has 1 vcpu"

   }

}


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

0 Kudos
Arkady
Contributor
Contributor

Unfortunately same result

0 Kudos
LucD
Leadership
Leadership

Works for me.
No clue why it doesn't work for you.

Which vSphere version are you using?


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

0 Kudos
LucD
Leadership
Leadership

It looks as if the CoresPerSocket behaviour has been changed in vSphere 6.5.

I tested my script in vSphere 6.7.
If you're on vSphere 6, or older, that might explain our different results.

Frank's post Decoupling of Cores per Socket from Virtual NUMA Topology in vSphere 6.5

gives some more details on this.


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

0 Kudos