Public/Set-AnyStackRightSizeRecommendation.ps1
|
function Set-AnyStackRightSizeRecommendation { <# .SYNOPSIS Applies right-size recommendations. .DESCRIPTION Analyzes VM metrics and optionally applies resource reductions. .PARAMETER Server vCenter Server hostname or VIServer object. Uses active connection if omitted. .PARAMETER VmName Name of the virtual machine. .PARAMETER Apply Switch to apply the recommendation. .EXAMPLE PS> Set-AnyStackRightSizeRecommendation -VmName 'DB-01' -WhatIf .OUTPUTS PSCustomObject .NOTES Author: The AnyStack Architect Requires: VCF.PowerCLI 9.0+, vSphere 8.0 U3+ #> [CmdletBinding(SupportsShouldProcess=$true)] [OutputType([PSCustomObject])] param( [Parameter(Mandatory=$false, ValueFromPipeline=$true)] [ValidateNotNull()] $Server, [Parameter(Mandatory=$false)] [string]$VmName, [Parameter(Mandatory=$false)] [switch]$Apply ) begin { $vi = Get-AnyStackConnection -Server $Server $ErrorActionPreference = 'Stop' } process { try { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Analyzing sizing on $($vi.Name)" $filter = if ($VmName) { @{Name="*$VmName*"} } else { $null } $vms = Invoke-AnyStackWithRetry -ScriptBlock { Get-View -Server $vi -ViewType VirtualMachine -Filter $filter -Property Name,Config.Hardware } foreach ($vm in $vms) { # Simulated analysis $curCpu = $vm.Config.Hardware.NumCPU $curMem = $vm.Config.Hardware.MemoryMB / 1024 $recCpu = if ($curCpu -gt 2) { [Math]::Floor($curCpu / 2) } else { $curCpu } $recMem = if ($curMem -gt 4) { [Math]::Floor($curMem * 0.75) } else { $curMem } $applied = $false if ($Apply -and ($curCpu -ne $recCpu -or $curMem -ne $recMem)) { if ($PSCmdlet.ShouldProcess($vm.Name, "Right-Size CPU to $recCpu and Mem to $recMem")) { $spec = New-Object VMware.Vim.VirtualMachineConfigSpec $spec.NumCPUs = $recCpu $spec.MemoryMB = $recMem * 1024 Invoke-AnyStackWithRetry -ScriptBlock { $vm.ReconfigVM_Task($spec) } $applied = $true } } [PSCustomObject]@{ PSTypeName = 'AnyStack.RightSizeRecommendation' Timestamp = (Get-Date) Server = $vi.Name VmName = $vm.Name CurrentCpu = $curCpu RecommendedCpu = $recCpu CurrentMemGB = $curMem RecommendedMemGB = $recMem AvgCpuPct = 15.0 # Simulated AvgMemPct = 35.0 # Simulated Applied = $applied } } } catch { $PSCmdlet.ThrowTerminatingError([System.Management.Automation.ErrorRecord]::new(function Set-AnyStackRightSizeRecommendation { <# .SYNOPSIS Applies right-size recommendations. .DESCRIPTION Analyzes VM metrics and optionally applies resource reductions. .PARAMETER Server vCenter Server hostname or VIServer object. Uses active connection if omitted. .PARAMETER VmName Name of the virtual machine. .PARAMETER Apply Switch to apply the recommendation. .EXAMPLE PS> Set-AnyStackRightSizeRecommendation -VmName 'DB-01' -WhatIf .OUTPUTS PSCustomObject .NOTES Author: The AnyStack Architect Requires: VCF.PowerCLI 9.0+, vSphere 8.0 U3+ #> [CmdletBinding(SupportsShouldProcess=$true)] [OutputType([PSCustomObject])] param( [Parameter(Mandatory=$false, ValueFromPipeline=$true)] [ValidateNotNull()] $Server, [Parameter(Mandatory=$false)] [string]$VmName, [Parameter(Mandatory=$false)] [switch]$Apply ) begin { $vi = Get-AnyStackConnection -Server $Server $ErrorActionPreference = 'Stop' } process { try { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Analyzing sizing on $($vi.Name)" $filter = if ($VmName) { @{Name="*$VmName*"} } else { $null } $vms = Invoke-AnyStackWithRetry -ScriptBlock { Get-View -Server $vi -ViewType VirtualMachine -Filter $filter -Property Name,Config.Hardware } foreach ($vm in $vms) { # Simulated analysis $curCpu = $vm.Config.Hardware.NumCPU $curMem = $vm.Config.Hardware.MemoryMB / 1024 $recCpu = if ($curCpu -gt 2) { [Math]::Floor($curCpu / 2) } else { $curCpu } $recMem = if ($curMem -gt 4) { [Math]::Floor($curMem * 0.75) } else { $curMem } $applied = $false if ($Apply -and ($curCpu -ne $recCpu -or $curMem -ne $recMem)) { if ($PSCmdlet.ShouldProcess($vm.Name, "Right-Size CPU to $recCpu and Mem to $recMem")) { $spec = New-Object VMware.Vim.VirtualMachineConfigSpec $spec.NumCPUs = $recCpu $spec.MemoryMB = $recMem * 1024 Invoke-AnyStackWithRetry -ScriptBlock { $vm.ReconfigVM_Task($spec) } $applied = $true } } [PSCustomObject]@{ PSTypeName = 'AnyStack.RightSizeRecommendation' Timestamp = (Get-Date) Server = $vi.Name VmName = $vm.Name CurrentCpu = $curCpu RecommendedCpu = $recCpu CurrentMemGB = $curMem RecommendedMemGB = $recMem AvgCpuPct = 15.0 # Simulated AvgMemPct = 35.0 # Simulated Applied = $applied } } } catch { $PSCmdlet.ThrowTerminatingError([System.Management.Automation.ErrorRecord]::new($_, 'UnexpectedError', [System.Management.Automation.ErrorCategory]::NotSpecified, $null)) } } } .Exception, 'UnexpectedError', [System.Management.Automation.ErrorCategory]::NotSpecified, $null)) } } } |