Using CPU Reserve to enforce virtual processor ratio
On Monday I posted a script for configuring virtual machine CPU scheduler settings. This script got me to thinking about another use for the virtual machine CPU reserve.
You see, it can also be used to ensure that you do not unintentionally start too many virtual machines at once.
If you were to set the CPU reserve on each virtual machine at 20% (or at 20,000 using the underlying API) then it is not possible to start extra virtual machines once you hit a ratio of 5 virtual processors for each physical processor. This is actually what System Center Virtual Machine Manager does to enforce limits on the system.
Here is a script that will do just that:
# Function for handling WMI jobs / return values
Function ProcessResult($result, $successString, $failureString)
{
#Return success if the return value is "0"
if ($result.ReturnValue -eq 0)
{write-host $successString}
#If the return value is not "0" or "4096" then the operation failed
ElseIf ($result.ReturnValue -ne 4096)
{write-host $failureString " Error value:" $result.ReturnValue}
Else
{#Get the job object
$job=[WMI]$result.job
#Provide updates if the jobstate is "3" (starting) or "4" (running)
while ($job.JobState -eq 3 -or $job.JobState -eq 4)
{write-host $job.PercentComplete "% complete"
start-sleep 1
#Refresh the job object
$job=[WMI]$result.job}
#A jobstate of "7" means success
if ($job.JobState -eq 7)
{write-host $successString}
Else
{write-host $failureString
write-host "ErrorCode:" $job.ErrorCode
write-host "ErrorDescription" $job.ErrorDescription}
}
}
# Prompt for the Hyper-V Server to use
$HyperVServer = Read-Host "Specify the Hyper-V Server to use (enter '.' for the local computer)"
# Prompt for the new CPU reservation
$NewReservation = Read-Host "Specify the CPU reservation (from 0-100000)"
# Get the management service
$VMMS = gwmi -namespace root\virtualization Msvm_VirtualSystemManagementService -computername $HyperVServer
# Get all VSSDs for non-snapshots
$VSSDs = gwmi "MSVM_VirtualSystemSettingData" -namespace "root\virtualization" -computername $HyperVServer | ? {$_.SettingType -eq 3}
foreach ($VSSD in $VSSDs)
{
# Get the related VM
$VM = $VSSD.getRelated("MSVM_ComputerSystem") | select -first 1
# Get the processor setting data
$ProcSetting = $VSSD.getRelated("Msvm_ProcessorSettingData") | select -first 1
# Update ProcSetting with the new value
$ProcSetting.Reservation = $NewReservation
# Apply the changes to the processor setting data back to the virtual machine
$result = $VMMS.ModifyVirtualSystemResources($VM, $ProcSetting.GetText(1))
# Process the result
$successMessage = "Updated processor scheduling settings on '" + $VM.ElementName + "'"
$failureMessage = "Failed to update processor scheduling settings on " + $VM.ElementName + "'"
ProcessResult $result $successMessage $failureMessage
}
If you run this script and specify “20000” then you will be able to run at a ratio of 5 virtual processors for each physical processor. If you run this script and specify “25000” then you will be able to run at a ratio of 4 virtual processors for each physical processor.
Note that this will not apply to any virtual machine snapshots, or to any newly created virtual machines, so it is a little fragile as a solution.
Cheers,
Ben
Comments
Anonymous
November 26, 2011
There are many things that should be considered and you have made a good point. Thanks for that. <a href="http://www.fragenet.com">fragen</a>Anonymous
January 29, 2013
You should update your zip file, still is missing a 0 from the reservation boundaries. 0-10000 instead of 0-100000 Not sure if there are other errors. Thanks for the info.