I'm trying to modify the rightsizing script to Stop-VM without tools installed, rightsize, and turn back on from a CSV. It works for VMs with tools installed, but only touches the first VM from the CSV that doesn't have tools installed and doesn't turn the rest back on. How can I get it to work with all the VMs from the CSV?
Get-Module -Name VMware* -ListAvailable | Import-Module -Force
Connect-VIServer -Server IPADDRESS -User 'user'
Connect-OMServer -Server IPADDRESS -User 'user' -Password 'pass'
$Names = @()
$OMResources = Import-CSV C:\Users\username\Desktop\testsheetoff.csv | Foreach-Object { $Names += $_.Name }
$Names
Stop-VM -VM $Names -Confirm:$false
$View = @()
foreach ($OMResource in $OMResources){
$DownSize = ($OMResource | Get-OMStat -Key "summary|oversized" -From ([DateTime]::Now).AddMinutes(-120) | Select-Object -Last 1).Value
#$UpSize = ($OMResource | Get-OMStat -Key "summary|undersized" -From ([DateTime]::Now).AddMinutes(-120) | Select-Object -Last 1).Value
# Mem is in KB
if($DownSize -gt 0){
$DownSizeMem = ($OMResource | Get-OMStat -Key "summary|oversized|memory" -From ([DateTime]::Now).AddMinutes(-120) | Select-Object -Last 1).Value
$DownSizeCPU = ($OMResource | Get-OMStat -Key "summary|oversized|vcpus" -From ([DateTime]::Now).AddMinutes(-120) | Select-Object -Last 1).Value
}
else {
$DownSizeMem = 0
$DownSizeCPU = 0
}
# Mem is in KB
#if($UpSize -gt 0){
# $UpSizeMem = ($OMResource | Get-OMStat -Key "summary|undersized|memory" -From ([DateTime]::Now).AddMinutes(-120) | Select-Object -Last 1).Value
# $UpSizeCPU = ($OMResource | Get-OMStat -Key "summary|undersized|vcpus" -From ([DateTime]::Now).AddMinutes(-120) | Select-Object -Last 1).Value
#}
#else {
# $UpSizeMem = 0
# $UpSizeCPU = 0
#}
$Report = [PSCustomObject] @{
Name = $OMResource.name
DownSize = $DownSize
UpSize = $UpSize
DownSizeMem = $DownSizeMem
DownSizeMemGB = [Math]::Round(($DownSizeMem / 1048576), 0)
DownSizeCPU = $DownSizeCPU
UpSizeMem = $UpSizeMem
UpSizeMemGB = [Math]::Round(($UpSizeMem / 1048576), 0)
UpSizeCPU = $upSizeCPU
}
$View += $Report
}
$View | Sort-Object DownSizeMemGB, DownSizeCPU -Descending | Format-Table -AutoSize
function Apply-OMRightsizing {
<#
.NOTES
===========================================================================
Created by: Markus Kraus
===========================================================================
Changelog:
2020.07 ver 1.0 Base Release
===========================================================================
External Code Sources:
-
===========================================================================
Tested Against Environment:
vSphere Version: vSphere 6.7 U3
PowerCLI Version: PowerCLI 11.5
PowerShell Version: 5.1
OS Version: Windows 10
Keyword: vSphere, vRealize, Rightsizing
===========================================================================
.DESCRIPTION
This function views or applies rightsizing recommendations from vRealize Operations to your vSphere VMs.
.Example
Get-VM -Name test-* | Get-OMResource | Apply-OMRightsizing -ViewOnly | Sort-Object DownSizeMemGB, DownSizeCPU -Descending | Format-Table -AutoSize
.Example
Get-VM -Name test-* | Get-OMResource | Apply-OMRightsizing -Apply -NoUpsizing
.PARAMETER OMResources
vRealize Operations Ressources to process
.PARAMETER ViewOnly
View Recommendations
.PARAMETER Apply
Apply Recommendations
.PARAMETER NoUpsizing
Apply only Downsizing Recommendations
#Requires PS -Version 5.1
#Requires -Modules VMware.VimAutomation.Core, @{ModuleName="VMware.VimAutomation.Core";ModuleVersion="11.5.0.0"}
#>
[CmdletBinding()]
param(
[Parameter(Mandatory=$True, ValueFromPipeline=$True, Position=0, HelpMessage = "OM Ressources to process")]
[ValidateNotNullorEmpty()]
$OMResources,
[Parameter(Mandatory=$False, ValueFromPipeline=$False, ParameterSetName="ViewOnly", HelpMessage = "View Recommendations")]
[Switch] $ViewOnly,
[Parameter(Mandatory=$False, ValueFromPipeline=$False, ParameterSetName="Apply", HelpMessage = "Apply Recommendations")]
[Switch] $Apply,
[Parameter(Mandatory=$False, ValueFromPipeline=$False, ParameterSetName="Apply", HelpMessage = "Apply only Downsizing Recommendations")]
[Switch] $NoUpsizing
)
Process {
if ($ViewOnly -or $Apply){
"Collecting Report ..."
$View = @()
foreach ($OMResource in $OMResources){
$DownSize = ($OMResource | Get-OMStat -Key "summary|oversized" -From ([DateTime]::Now).AddMinutes(-120) | Select-Object -Last 1).Value
#$UpSize = ($OMResource | Get-OMStat -Key "summary|undersized" -From ([DateTime]::Now).AddMinutes(-120) | Select-Object -Last 1).Value
# Mem is in KB
if($DownSize -gt 0){
$DownSizeMem = ($OMResource | Get-OMStat -Key "summary|oversized|memory" -From ([DateTime]::Now).AddMinutes(-120) | Select-Object -Last 1).Value
$DownSizeCPU = ($OMResource | Get-OMStat -Key "summary|oversized|vcpus" -From ([DateTime]::Now).AddMinutes(-120) | Select-Object -Last 1).Value
}
else {
$DownSizeMem = 0
$DownSizeCPU = 0
}
# Mem is in KB
#if($UpSize -gt 0){
# $UpSizeMem = ($OMResource | Get-OMStat -Key "summary|undersized|memory" -From ([DateTime]::Now).AddMinutes(-120) | Select-Object -Last 1).Value
# $UpSizeCPU = ($OMResource | Get-OMStat -Key "summary|undersized|vcpus" -From ([DateTime]::Now).AddMinutes(-120) | Select-Object -Last 1).Value
#}
#else {
# $UpSizeMem = 0
# $UpSizeCPU = 0
#}
$Report = [PSCustomObject] @{
Name = $OMResource.name
DownSize = $DownSize
UpSize = $UpSize
DownSizeMem = $DownSizeMem
DownSizeMemGB = [Math]::Round(($DownSizeMem / 1048576), 0)
DownSizeCPU = $DownSizeCPU
UpSizeMem = $UpSizeMem
UpSizeMemGB = [Math]::Round(($UpSizeMem / 1048576), 0)
UpSizeCPU = $upSizeCPU
}
$View += $Report
}
}
if ($ViewOnly){
$View
}
if ($Apply){
foreach ($Object in $View) {
if ($Object.DownSize -gt 0 -or $Object.UpSize -gt 0){
"Processing '$($Object.Name)' ..."
$VM = Get-VM -Name $Object.Name
"Shut down '$($Object.Name)' ..."
#$VM | Stop-VM -Confirm:$False
$i = 0
while((Get-VM -Name $VM.Name).PowerState -eq "PoweredOn"){
$i++
Start-Sleep 1
Write-Progress -Activity "Check PowerState" -Status "Wait for PowerState Task..."
}
#"Create Snapshot for '$($Object.Name)' ..."
#$VM | New-Snapshot -Name "Pre Resize" -Memory:$false -Quiesce:$false
if ($Object.DownSize -gt 0){
"Downsize '$($Object.Name)' ..."
$VM | Set-VM -NumCPU $($VM.NumCpu - $Object.DownSizeCPU) -MemoryGB $($VM.MemoryGB - $Object.DownSizeMemGB) -Confirm:$False
}
#if ($Object.UpSize -gt 0 -and $NoUpsizing -eq $False){
# "Upsize '$($Object.Name)' ..."
# $VM = Get-VM -Name $Object.Name
# $VM | Set-VM -NumCPU $($VM.NumCpu + $Object.UpSizeCPU) #-MemoryGB $($VM.MemoryGB + $Object.UpSizeMemGB) #-Confirm:$False
#}
#$VM = Get-VM -Name $Object.Name
#$VM | Get-VMResourceConfiguration | Set-VMResourceConfiguration -CpuReservationMhz $($VM.NumCpu * 200) -MemReservationGB $($VM.MemoryGB / 2) -Confirm:$False
"Power on '$($Object.Name)' ..."
$VM | Start-VM -Confirm:$False
}
}
}
}
}
Get-VM -Name $Names | Get-OMResource | Apply-OMRightsizing -ViewOnly | Sort-Object DownSizeMemGB, DownSizeCPU -Descending | Format-Table -AutoSize
Get-VM -Name $Names | Get-OMResource | Apply-OMRightsizing -Apply -NoUpsizing
The output of VMs to rightsize looks like this, even though it shows up in vRO as needing to be downsized.
Name DownSize UpSize DownSizeMem DownSizeMemGB DownSizeCPU UpSizeMem UpSizeMe
mGB
---- -------- ------ ----------- ------------- ----------- --------- --------
vmtestmachine 1 8388608 8 4 0
vmtestmachine2 0 0 0 0 0
That looks more like a logic error in the function.
You can't, as the error explains, set the NumCpu value to something less than 1.
You can update the condition
if ($Object.DownSize -gt 0 -and ($VM.NumCpu - $Object.DownSizeCPU) -ge 1){
"Downsize '$($Object.Name)' ..."
$VM | Set-VM -NumCPU $($VM.NumCpu - $Object.DownSizeCPU) -MemoryGB $($VM.MemoryGB - $Object.DownSizeMemGB) -Confirm:$False
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
Why did you move the Stop-VM out of the function?
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
@LucD Stopping the VM in the function works too. I was just testing different things. Regardless though, it only picks up the first VM in list to do any actions against. So if I leave it in the function and don't turn them all off at first, the only VM that gets shutdown and powered back on is the first. The same method works from a CSV with vmtools installed, it hops through them sequentially. Its just the ones without tools.
What do you have in $names?
Are those the names of all intended VMs?
The function supports the Verbose switch, I would suggest using that on the call.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
That's right, every VM from the CSV is intended. $Names is the list of VMs and when it's echoed from the command line it looks like this:
vmname1
vmname2
etc..
Where exactly should I insert the verbose switch? I'm not very familiar with PS, I apologize
You could do like this
Get-VM -Name $Names | Get-OMResource | Apply-OMRightsizing -Apply -NoUpsizing -Verbose
Let's first see what this returns.
Then you could start adding Write-Verbose lines in the function to further debug.
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
So it seems like it's working as expected now. I guess the VMs just needed more time to show up as needed rightsized in the script as it did in the GUI? The only issue now is this which I also suspect is tied to the short lifespan of the VMs:
Set-VM : Cannot validate argument on parameter 'NumCpu'. The 0 argument is less than
the minimum allowed range of 1. Supply an argument that is greater than or equal to
1 and then try the command again.
At C:\Users\user\Desktop\shutdown.ps1:155 char:46
+ ... $VM | Set-VM -NumCPU $($VM.NumCpu - $Object.DownSizeCPU) -Memory ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Set-VM], ParameterBindingValidationE
xception
+ FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.
ViCore.Cmdlets.Commands.SetVM
That looks more like a logic error in the function.
You can't, as the error explains, set the NumCpu value to something less than 1.
You can update the condition
if ($Object.DownSize -gt 0 -and ($VM.NumCpu - $Object.DownSizeCPU) -ge 1){
"Downsize '$($Object.Name)' ..."
$VM | Set-VM -NumCPU $($VM.NumCpu - $Object.DownSizeCPU) -MemoryGB $($VM.MemoryGB - $Object.DownSizeMemGB) -Confirm:$False
}
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference