VMware Cloud Community
RahmanK
Contributor
Contributor

PowerCLI script to sanity check whether hosts can accommodate multiple VM environments

We have a training VCenter which we run courses for students.


We have a datacenter containing resource pools for each course we run. Each resource pool contains multiple VMs relevant to the course.

We have another datacenter which contains the hosts we deploy student environments to. Each student environment is contained in a resource pool.

I need to create a Powercli script which would calculate the percentage of free storage, cpu and memory left on each host if we deployed a course.

For example.

Course is starting with 6 students and I have provisioned 3 hosts for this course. 2 student environments per host.

Prior to deploying the VMs I want to check if my hosts can accommodate all the VMs by making sure there is atleast x percentage of Storage, Memory and CPU

I have started writing a script to do a storage check however I' am not getting accurate results and when deploying all student environments to a single host I get the error below the script.

SCRIPT

param($folder, $resourcePool, $students)

Function Percentcal {

    param(

    [parameter(Mandatory = $true)]

    [int]$InputNum1,

    [parameter(Mandatory = $true)]

    [int]$InputNum2)

  $size = (get-vm -location $resourcePool | get-harddisk | measure-object -property capacityGB -sum | select-object -ExpandProperty sum)

    $realsize = [math]::Round($size*1024)

    $totalsize = $realsize*$students

  $totalvmhosts = $hosts.count

  $sizeperhost = $totalsize / $totalvmhosts

  $realsizeperhost = [math]::Round($sizeperhost)

    $actualfreespace = $InputNum1-$realsizeperhost

  $actualfreespace / $InputNum2*100

}

$hosts = Get-VMHost -Location $folder

ForEach ($vhost in $hosts)

{

  $ds = Get-Datastore -VMHost $vhost | Where-Object {$_.Name -like "datastore*"} | Sort Name

  if ($ds.Name)

  {

        $PercentFree = Percentcal $ds.FreeSpaceMB $ds.CapacityMB

        $PercentFree = "{0:N2}" -f $PercentFree

        $ds | Add-Member -type NoteProperty -name PercentFree -value $PercentFree

  }

  if([int]$PercentFree -gt 5){

  Write-Host -ForegroundColor "Yellow" ("Storage on $vhost is OK ")

  }

  else {

  Write-Host -ForegroundColor "Red" ("Storage on $vhost is Insufficient ")

  }

}

$ds | Select Name,FreeSpaceMB,CapacityMB,PercentFree | Export-Csv c:\Scripts\Dev\datastorereport.csv -NoTypeInformation

ERROR

Cannot convert value "-Infinity" to type "System.Int32". Error: "Input string was not in a correct

format."

At C:\Scripts\Dev\StorageCheck.ps1:29 char:23

+         if([int]$PercentFree <<<<  -gt 5){

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

    + FullyQualifiedErrorId : RuntimeException

0 Kudos
9 Replies
LucD
Leadership
Leadership

You seem to end up with negative infinity in the $PercentFree variable.

That is most probably due to a division by zero somewhere.


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

0 Kudos
RahmanK
Contributor
Contributor

Thanks I will have a look at where division of zero is occurring.

Would you know how to script something similar for Memory and CPU.

Thanks.

0 Kudos
LucD
Leadership
Leadership

For memory you could do something like the following.

Mind, I don't really think that assigned memory is a good criteria, I would rather see what a VM is actively using.

$vms = Get-VM | where{$_.PowerState -eq 'PoweredOn'}

$vmMem = $vms | Measure-Object -Property MemoryGB -Sum | Select -ExpandProperty Sum

$esxMem = $vms | Measure-Object -Property {$_.VMHost.MemoryTotalGB} -Sum | select -ExpandProperty Sum

$memPercent = $vmMem/$esxMem*100

For CPU is a bit more tricky.

Do you just count the number of assigned vCPU over the number of available vCPU over all the hosts ?

If yes, then you could use something similar to the memory.

A better, in my opinion, method would be to look again what these VMs are actually using (in MHz).

And then take the percentage from the available MHz over all the ESXi nodes.


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

0 Kudos
RahmanK
Contributor
Contributor

I agree however the VMs are powered off so retrieving the VMs memory/cpu usage is not possible.

The script seems to get a percentage of available memory on the host the VMs are currently residing on.

However I would like to know if I were to clone my VMs onto other hosts how much free memory would be left on each of those hosts.

Kind of like a pre-flight check to make sure we do not consume all the resources when deploying VMs.

Also $esxMem stores total host memory, is there a way or a property which returns free memory.

Thanks

0 Kudos
LucD
Leadership
Leadership

When you do a Get-VMHost, you get the properties MemoryTotalGB and MemoryUsageGB.

That should allow you determine the free/available physical memory


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

0 Kudos
RahmanK
Contributor
Contributor

Thanks for the info.

I have written the script below however I get an error 'Attempted to divide by zero' on line 14 which is calculating $memPercent.

Param($resourcePool, $students, $folder)

$vms = Get-VM -Location $resourcePool

$vmhosts = Get-VMHost -Location $folder

$vmMem = $vms | Measure-Object -Property MemoryGB -Sum | Select -ExpandProperty Sum

$totalvmMem = $vmMem*$students

foreach ($esxhost in $vmhosts) {

  $totalMem = [math]::Round($_.MemoryTotalGB)

  $usedMem = [math]::Round($_.MemoryUsageGB)

  $freeMem = [math]::Round($_.MemoryTotalGB - $_.MemoryUsageGB)

  $memPercent = $totalvmMem/$freeMem*100

      if([int]$memPercent -gt 10){

      Write-Host -ForegroundColor "Yellow" ("Memory on $esxhost is OK ")

      }

      else {

      Write-Host -ForegroundColor "Red" ("Memory on $esxhost is Insufficient ")

      }

}

0 Kudos
LucD
Leadership
Leadership

You should be using $esxhost, not the pipeline variable

Param($resourcePool, $students, $folder)

$vms = Get-VM -Location $resourcePool

$vmhosts = Get-VMHost -Location $folder

$vmMem = $vms | Measure-Object -Property MemoryGB -Sum | Select -ExpandProperty Sum

$totalvmMem = $vmMem*$students

foreach ($esxhost in $vmhosts) {

  $totalMem = [math]::Round($esxhost.MemoryTotalGB)

  $usedMem = [math]::Round($esxhost.MemoryUsageGB)

  $freeMem = [math]::Round($esxhost.MemoryTotalGB - $esxhost.MemoryUsageGB)

  $memPercent = $totalvmMem/$freeMem*100

  if([int]$memPercent -gt 10){

       Write-Host -ForegroundColor "Yellow" ("Memory on $esxhost is OK ")

  }

  else {

      Write-Host -ForegroundColor "Red" ("Memory on $esxhost is Insufficient ")

  }

}

 


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

0 Kudos
RahmanK
Contributor
Contributor

Thanks that resolved the issue.

How would I do the same for assigned vCPUs over available vCPUs.

I tried running Get-VMHost -Name hostname | Select Name,  NumvCPUs.

However NumvCPUs column is blank.

I get the same result with Get-VM.

Thanks

0 Kudos
LucD
Leadership
Leadership

You could do.

Get-VMHost | %{$_.ExtensionData.Hardware.CpuInfo.NumCpuThreads} | Measure-Object  -Sum

For the VMs you can do

Get-VM | Measure-Object -Property NumCpu  -Sum


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

0 Kudos