PowerCLI: Linked VMs Refresh

April 1, 2015 – 5:19 pm

And here is the follow up script for the pre-prod environment. This script can be scheduled to run daily to provide a fresh pre-production or test environment when your team arrives in the office.

#=============================================================================
# Script       : Pre-Production environment refresh
# Author       : Marc Bouchard
# Credits      : Rob Girard
# Version      : 1.0
# Revision     : 03/31/2015
# Purpose      : Refresh non-persistent copies of production VMs
# Requirements : 
# 1. Source VM snapshot is created
# 2. New VM is created, configured to use the base virtual HD of the source VM.
#    This drive is configured as a non-persistent disk to prevent corruption of
#    the reference image. This basically makes a point in time reference image
#    for testing changes to the production environment.
# 3. Both VMs must be powered on
#
# Parameters   : List of source (production) VMs
#=============================================================================

#=============================================================================
# --- Command line parameters
#=============================================================================

param (
	[Parameter(Mandatory=$true)]
	[String[]]$ListOfVMs = $(throw "List of source (production) VMs required")
)

#=============================================================================
# Screen setup
#=============================================================================

# set regular console colours
[console]::backgroundcolor = "black"
[console]::foregroundcolor = "white"

# clear screen
clear-host

#=============================================================================
# --- Load Powershell Snap-ins
#=============================================================================

if (!(get-pssnapin -name VMware.VimAutomation.Core -erroraction 'SilentlyContinue')) {
	Write-Host "[INFO] Adding PowerCLI Snapin"
	add-pssnapin VMware.VimAutomation.Core -ErrorAction 'SilentlyContinue'
	if (!(get-pssnapin -name VMware.VimAutomation.Core -erroraction 'SilentlyContinue')) {
		Write-Host "[ERROR] PowerCLI snapin NOT added" -ForegroundColor Red
	} Else {
		Write-Host "[INFO] PowerCLI snapin added"
	}
}

#=============================================================================
# --- CUSTOMIZE THIS SECTION ONLY FOR YOUR ENVIRONMENT
#=============================================================================

$DateOnly = Get-Date -f yyyy-MM-dd
$ScriptLocation="C:\Scripts\PreProd\"
$CredUser = "ServiceAccountUserID"
$CredFile = $ScriptLocation + "Refresh-PreProd.crd"
$ReptFile = $ScriptLocation + "Refresh-PreProd_" + $DateOnly + ".log"
$vCenter = "vCenterServerName"
$Prefix = "PRE_"

#SMTP relay
$smtpServer = "smtp.companyname.com"
$Sender = "refresh-preprod@companyname.com"
$Recipient = "sysadmin@companyname"

#=============================================================================
# --- FUNCTION: Send e-mail
#=============================================================================

function SendMail{
   Write-Host "[INFO]    Sending e-mail"

	#Creating a Mail object
	$msg = new-object Net.Mail.MailMessage

	#Creating email attachment object
	$att = new-object Net.Mail.Attachment($ReptFile)

	#Creating SMTP server object
	$smtp = new-object Net.Mail.SmtpClient($smtpServer)

	#Email structure 
	$msg.From = $Sender
	$msg.To.Add($Recipient)
	$msg.subject = "Pre-production environment refresh " + $DateOnly
	$msg.body = "Please see attached file."
	$msg.Attachments.Add($att)
	
	#Sending email 
	$smtp.Send($msg)
	$att.Dispose()
}

#=============================================================================
# --- Log Messages to journal
#=============================================================================

function LogMessages($LogMessage, $LogErrorMsg) {
	
	$(Get-Date -Format s) + " [INFO]    " + $LogMessage | Out-file $ReptFile -Encoding ASCII -append
	if ($LogErrorMsg -ne $null)
	{
		$(Get-Date -Format s) + " [ERROR]   " + $LogErrorMsg | Out-file $ReptFile -Encoding ASCII -append
	}
}

#=============================================================================
# --- MAIN PROGRAM
#=============================================================================

Write-Host "[INFO]    ======================================"
Write-Host "[INFO]           Refresh Linked VM Script"
Write-Host "[INFO]    ======================================"
Write-Host "[INFO]"

#=============================================================================
# --- Credentials management
#=============================================================================

if ((Test-Path $CredFile) -eq $false) {
	$cred = new-object system.management.automation.pscredential $CredUser,
		(read-host -assecurestring -prompt "Enter administrator password")
      try
      {
         $cred.Password | ConvertFrom-SecureString | Set-Content $CredFile -ErrorAction Stop
      }
      catch
      {
         $Message = "Error saving credentials"
         $ErrorMessage = $_.Exception.Message
         LogMessages $Message $ErrorMessage 
         SendMail
         Exit
      }
}
else {
   $password = get-content $CredFile | convertto-securestring
	$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $CredUser,$password
}

#=============================================================================
# --- Connect to vCenter server
#=============================================================================

Write-Host "[INFO]    Connecting to vCenter: " $vCenter

try
{
	Connect-VIServer -server $vCenter -credential $cred -ErrorAction Stop -WarningAction SilentlyContinue | Out-Null
	$Message = "Connecting to vCenter: " + $vCenter
	LogMessages $Message
}
Catch
{
	$Message = "Failed connecting to " + $vCenter
	$ErrorMessage = $_.Exception.Message
	LogMessages $Message $ErrorMessage 
	SendMail
	Exit
}

#=============================================================================
# --- Shutdown current clones
#=============================================================================

ForEach ($SourceVM in $ListOfVMs)
{
	try
	{
		$TargetVM = $Prefix + $SourceVM
      Write-Host "[INFO]    Shutting down" $TargetVM
		$task = Stop-VM -VM $TargetVM -confirm:$false -runasync -ErrorAction Stop
		wait-task -Task $task  | Out-Null
		$Message = "Stopping " + $TargetVM
		LogMessages $Message
	}
	Catch
	{
      Write-Host "[ERROR]   Shutting down " $TargetVM -foregroundcolor Red
	   $Message = "Error powering off "+ $Prefix + $SourceVM 
		$ErrorMessage = $_.Exception.Message
		LogMessages $Message $ErrorMessage
		SendMail
		Exit
	}
}

#=============================================================================
# --- Remove old snapshots
#=============================================================================

ForEach ($SourceVM in $ListOfVMs)
{
	Try
	{
      Write-Host "[INFO]    Deleting Snapshots for" $SourceVM
		$task = Get-VM $SourceVM | Get-Snapshot | Remove-Snapshot -confirm:$false -runasync -ErrorAction Stop
		wait-task -Task $task | Out-Null
		$Message = "Deleting snapshot for " + $SourceVM
		LogMessages $Message
	}
	Catch
	{
      Write-Host "[ERROR]   Failed removing snapshot for" $SourceVM -foregroundcolor Red
      $Message = "Error removing snapshot for " + $SourceVM 
		$ErrorMessage = $_.Exception.Message
		LogMessages $Message $ErrorMessage
		SendMail
		Exit
	}
}

#=============================================================================
# --- Create new snapshots
#=============================================================================

ForEach ($SourceVM in $ListOfVMs)
{
	try
	{
      Write-Host "[INFO]    Creating snapshot for" $SourceVM
		$task = New-Snapshot -VM $SourceVM -Name ($(Get-Date -format s)) -runasync -ErrorAction Stop
		wait-task -Task $task | Out-Null
		$Message = "Creating snapshot for " + $SourceVM
		LogMessages $Message
	}
	Catch
	{
      Write-Host "[ERROR]   Failed creating snapshot for" $SourceVM -foregroundcolor Red
	   $Message = "Error creating snapshot for " + $SourceVM 
		$ErrorMessage = $_.Exception.Message
		LogMessages $Message $ErrorMessage
		SendMail
		Exit
	}
}

#=============================================================================
# --- Power up refreshed environment
#=============================================================================

ForEach ($SourceVM in $ListOfVMs)
{
	try
	{
		$TargetVM = $Prefix + $SourceVM
      Write-Host "[INFO]    Powering up " $TargetVM
		Start-VM -VM $TargetVM -confirm:$false -runasync -ErrorAction Stop | Out-Null
		$Message = "Restarting " + $TargetVM
		LogMessages $Message
	}
	catch
	{
      Write-Host "[ERROR]   Failure starting " $SourceVM -foregroundcolor Red
	   $Message = "Error starting " + $SourceVM 
		$ErrorMessage = $_.Exception.Message
		LogMessages $Message $ErrorMessage
		SendMail
		Exit
	}
}

#=============================================================================
# --- Close session
#=============================================================================

Disconnect-VIServer -server $vCenter -confirm:$false -force
Write-Host "[INFO]    Disconnecting from vCenter"
$Message = "Disconnecting from vCenter"
LogMessages $Message
SendMail
Write-Host

Post a Comment