VMware Cloud Community
gbouziden
Enthusiast
Enthusiast
Jump to solution

Rightsizing VMs without VM tools installed

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

 

 

Labels (3)
Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

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

View solution in original post

7 Replies
LucD
Leadership
Leadership
Jump to solution

Why did you move the Stop-VM out of the function?


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

Reply
0 Kudos
gbouziden
Enthusiast
Enthusiast
Jump to solution

@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.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
gbouziden
Enthusiast
Enthusiast
Jump to solution

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

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
gbouziden
Enthusiast
Enthusiast
Jump to solution

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

 

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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