I recently wrote this PowerCLI-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
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
Solve it
for versione 6 of CLI
function PowerOff-VM
Shutdown-VMGuest now use Stop-VMguest