Jumlins TechBlog

The coding hell and the daily IT of Niklas Jumlin

May 13th, 2015 by Niklas Jumlin

I recently wrote this script to schedule Memory and vCPU up/downgrades on virtual machines from a VMware PowerCLI enabled vCenter server running Windows.
The script is built upon many useful parts from a script that I found here:
http://ict-freak.nl/2010/05/07/powercli-script-to-schedule-memory-and-or-vcpu-updowngrade/

I mainly had to make changes in order for the script to be able to run from Task Scheduler. First of, the script needed to be executed as a different account, one that has permissions in your VMware Cluster to reboot and change configuration of virtual machines. So I created the user svc_sched_script in VMware vCenter and gave it enough permission.

I then needed to save the password (not in clear text) and pass it to the script somehow.

Use this command to generate the XML-file containing credentials for connecting to vCenter. This is a one-time thing.

New-VICredentialStoreItem -Host ESX-or-vCenter-Hostname -User username -Password 'password' -File C:\path-where-to-store-file.xml

The script will then read that file and fetch the username and encrypted password to connect to the vCenter and execute the PowerCLI commands as that user.

$Credential = Get-VICredentialStoreItem -Host $vCenter[0] -File c:\scripts\encrypted_credentials.xml
$VIServer = Connect-VIServer $vCenter -user $Credential.User -Password $Credential.Password

To configure the script to run form Task Scheduler, follow these instructions:

In the Actions tab, press New and enter the below into the Program/Script input field:

C:\WINDOWS\System32\WindowsPowershell\v1.0\powershell.exe

Use this as arguments:

-Command "& 'C:\scripts\Change_VM_Memory_CPU_Count.ps1' -vCenter 'IP to your vcenter' -vmName 'Name of VM as it appears in vCenter' -EMail 'recipient@domain.com' -MemoryMB 'Memory in MB' -MemoryOption 'Add or Remove' -CPUCount 'Number of vCPUs' -CPUOption 'Add or Remove'"

Then just have the script running as a user with administrative permission on the Windows machine (for creating logs under C:\scripts)

Here is the full script:

###################################################################
# Example:
# .\Change_VM_Memory_CPU_Count.ps1 -vCenter vc01 
# -vmName NAGIOS -MemoryMB 512 -MemoryOption Add 
# -CPUCount 1 -CPUOption Remove
#
# Version 1.1 2015-02-09 Niklas Jumlin nj@qd.se
# Sample code by Arne Fokkema www.ict-freak.nl @afokkema
 
#
####################################################################
 
param(
    [parameter(Mandatory = $true)]
    [string[]]$vCenter,
    [parameter(Mandatory = $true)]
    [string]$vmName,
    [int]$MemoryMB,
    [string]$MemoryOption,
    [int]$CPUCount,
    [string]$CPUOption,
	[string]$EMail
)
 
add-pssnapin VMware.VimAutomation.Core
## This will create a timestamp like yyyy-mm-yy
$TIMESTAMP = get-date -uformat "%Y-%m%-%d"
 
## This will get the time like HH:MM:SS
## $TIME = get-date -uformat "%T"
$global:TIME= Set-PSBreakpoint -Variable TIME -Mode Read -Action { $global:TIME= Get-Date -uformat "%T" }
 
$VM_LOG = "C:\scripts\$vmName-reconfiguration.log"
 
If (Test-Path $VM_LOG){
	Remove-Item $VM_LOG
}
 
function PowerOff-VM{
    param([string] $vm)
 
    Shutdown-VMGuest -VM (Get-VM $vm) -Confirm:$false | Out-Null
    Write-Host "Shutdown $vm"
	Add-Content $VM_LOG "$TIMESTAMP $TIME Shutdown $vm"
    do {
        $status = (get-VM $vm).PowerState
    }until($status -eq "PoweredOff")
    return "OK"
}
 
function PowerOn-VM{
    param( [string] $vm)
 
    if($vm -eq ""){    
	Write-Host "Please enter a valild VM name"
	Add-Content $VM_LOG "$TIMESTAMP $TIME Please enter a valild VM name"
	}
 
    if((Get-VM $vm).powerstate -eq "PoweredOn"){
        Write-Host "$vm is already powered on"
        Add-Content $VM_LOG "$TIMESTAMP $TIME $vm is already powered on"
		}
 
    else{
        Start-VM -VM (Get-VM $vm) -Confirm:$false | Out-Null
        Write-Host "Starting $vm"
        Add-Content $VM_LOG "$TIMESTAMP $TIME Starting $vm"
        do {
            $status = (Get-vm $vm | Get-View).Guest.ToolsRunningStatus
        }until($status -eq "guestToolsRunning")
        return "OK"
    }
}
 
function Change-VMMemory{
    param([string]$vmName, [int]$MemoryMB, [string]$Option)
    if($vmName -eq ""){
        Write-Host "Please enter a VM Name"
        Add-Content $VM_LOG "$TIMESTAMP $TIME Please enter a VM Name"
 
        return
    }
    if($MemoryMB -eq ""){
        Write-Host "Please enter an amount of Memory in MB"
        Add-Content $VM_LOG "$TIMESTAMP $TIME Please enter an amount of Memory in MB"
        return
    }
    if($Option -eq ""){
        Write-Host "Please enter an option to add or remove memory"
        Add-Content $VM_LOG "$TIMESTAMP $TIME Please enter an option to add or remove memory"
        return
    }
 
    $vm = Get-VM $vmName    
    $CurMemoryMB = ($vm).MemoryMB
 
    if($vm.Powerstate -eq "PoweredOn"){
        Write-Host "The VM must be Powered Off to continue"
        Add-Content $VM_LOG "$TIMESTAMP $TIME The VM must be Powered Off to continue"
        return
    }
 
    if($Option -eq "Add"){
        $NewMemoryMB = $CurMemoryMB + $MemoryMB
    }
    elseif($Option -eq "Remove"){
        if($MemoryMB -ge $CurMemoryMB){
            Write-Host "The amount of memory entered is greater or equal than the current amount of memory allocated to this VM"
			Add-Content $VM_LOG "$TIMESTAMP $TIME The amount of memory entered is greater or equal than the current amount of memory allocated to this VM"
            return
        }
        $NewMemoryMB = $CurMemoryMB - $MemoryMB
    }
 
    $vm | Set-VM -MemoryMB $NewMemoryMB -Confirm:$false
    Write-Host "The new configured amount of memory is"(Get-VM $VM).MemoryMB
	$VMNewMem=(Get-VM $VM).MemoryMB
    Add-Content $VM_LOG "$TIMESTAMP $TIME The new configured amount of memory is $VMNewMem"
}
 
function Change-VMCPUCount{
    param([string]$vmName, [int]$NumCPU, [string]$Option)
    if($vmName -eq ""){
        Write-Host "Please enter a VM Name"
        Add-Content $VM_LOG "$TIMESTAMP $TIME Please enter a VM Name"
        return
    }
    if($NumCPU -eq ""){
        Write-Host "Please enter the number of vCPU's you want to add"
        Add-Content $VM_LOG "$TIMESTAMP $TIME Please enter the number of vCPU's you want to add"
        return
    }
    if($Option -eq ""){
        Write-Host "Please enter an option to add or remove vCPU"
        Add-Content $VM_LOG "$TIMESTAMP $TIME Please enter an option to add or remove vCPU"
        return
    }
 
    $vm = Get-VM $vmName    
    $CurCPUCount = ($vm).NumCPU
 
    if($vm.Powerstate -eq "PoweredOn"){
        Write-Host "The VM must be Powered Off to continue"
        Add-Content $VM_LOG "$TIMESTAMP $TIME The VM must be Powered Off to continue"
        return
    }
 
    if($Option -eq "Add"){
        $NewvCPUCount = $CurCPUCount + $NumCPU
    }
    elseif($Option -eq "Remove"){
        if($NumCPU -ge $CurCPUCount){
            Write-Host "The number of vCPU's entered is higher or equal than the current number of vCPU's allocated to this VM"
            Add-Content $VM_LOG "$TIMESTAMP $TIME The number of vCPU's entered is higher or equal than the current number of vCPU's allocated to this VM"
            return
        }
        $NewvCPUCount = $CurCPUCount - $NumCPU
    }
 
    $vm | Set-VM -NumCPU $NewvCPUCount -Confirm:$false
    Write-Host "The new configured number of vCPU's is"(Get-VM $VM).NumCPU
	$VMNewCPU=(Get-VM $VM).NumCPU
    Add-Content $VM_LOG "$TIMESTAMP $TIME The new configured number of vCPU's is $VMNewCPU"
}
 
#######################################################################################
# Main script
#######################################################################################
Add-Content $VM_LOG "$TIMESTAMP $TIME Script started"
 
#
# Use this command to generate the XML-file containing credentials for connecting to vCenter
# New-VICredentialStoreItem -Host ESX-or-vCenter-Hostname -User username -Password 'password' -File C:\path-where-to-store-file.xml
#
 
$Credential = Get-VICredentialStoreItem -Host $vCenter[0] -File c:\scripts\encrypted_credentials.xml
$VIServer = Connect-VIServer $vCenter -user $Credential.User -Password $Credential.Password
If ($VIServer.IsConnected -ne $true){
    Write-Host "error connecting to $vCenter" -ForegroundColor Red
    Add-Content $VM_LOG "$TIMESTAMP $TIME error connecting to $vCenter"
    exit
}
 
if($MemoryMB -or $CPUCount -ne "0"){
    $poweroff = PowerOff-VM $vmName
    if($poweroff -eq "Ok"){
    Write-Host "PowerOff OK"
    Add-Content $VM_LOG "$TIMESTAMP $TIME PowerOff OK"
 
        if($MemoryMB -ne "0"){
            if($MemoryOption -eq " ") {
			Write-Host "Please enter an option to add or remove memory"
			Add-Content $VM_LOG "$TIMESTAMP $TIME Please enter an option to add or remove memory"
			}
            else{
                Change-VMMemory $vmName $MemoryMB $MemoryOption
            }
        }
 
        if($CPUCount -ne "0"){
            if($CPUOption -eq " ") {
			Write-Host "Please enter an option to add or remove cpu"
			Add-Content $VM_LOG "$TIMESTAMP $TIME Please enter an option to add or remove cpu"
			}
            else{
                Change-VMCPUCount $vmName $CPUCount $CPUOption
            }
        }
 
        $poweron = PowerOn-VM $vmName
        if($poweron -eq "Ok"){
            Write-Host "PowerOn OK"
            Add-Content $VM_LOG "$TIMESTAMP $TIME PowerOn OK"
			}
    }
}
Disconnect-VIServer -Confirm:$false
 
##  Email settings, seperate each recipient with comma and no spaces
$recipient = "$EMail"
$from= "from@domain.com"
$smtpServer = "smtp.domain.com"
 
$file = "$VM_LOG"
$att = new-object Net.Mail.Attachment($file)
 
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
 
$msg.From = $from
$msg.To.Add("$recipient")
$msg.Subject = ('Scheduled VM Configuration Results')
$msg.Body = "Message attached"
 
$msg.Attachments.Add($att)
 
$smtp.Send($msg)
 
$att.Dispose()
 
Return
Share on Facebook

2 Responses to “ Script to Schedule Mem and or vCPU up/downgrade ”

  1. Silvio says:

    mmm
    Shutdown-VMGuest : Termine ‘Shutdown-VMGuest’ not recognize name of cmdlet

    not use powershellcli but normal powershel with this script…how i can fix it? bye

  2. Silvio says:

    Solve it
    for versione 6 of CLI

    function PowerOff-VM

    Shutdown-VMGuest now use Stop-VMguest

Leave a Reply