Virtual machine migration via Windows PowerShell scripts
These Windows PowerShell scripts will help solutions providers to ensure that the process for both single and multiple virtual machine migrations will be completed quickly.
|
||||
Virtual Machine Migrations
When you're migrating a virtual machine through Virtual Machine Manager, the transfer type (or speed) for the migration is determined during Intelligent Placement and it is based upon the properties and capabilities of the source virtual machine and the destination host along with the connectivity between them. In Listing 8.5, we attempt to migrate a virtual machine while enforcing a requirement that only SAN or cluster migrations are eligible. This puts a requirement on the script to not only check for good host ratings but also to ensure that the transfer can be accomplished quickly using a SAN or a failover cluster.
Listing 8.5: Migrating a virtual machine using cluster or SAN and tracking the migration progress
# Get a connection to the VMM server
$c = Get-VMMServer "localhost"
# Get the VM to migrate
$VM = Get-VM "virtualmachine1"
# Get all the hosts
$AllHosts = Get-VMHost
# The IsMigration flag allows the current host of the VM
# to be considered as the migration target
$hostrating = Get-VMHostRating -VMHost $AllHosts -VM $VM -IsMigration
# Order the host ratings
$orderedrating = $hostrating | sort-object rating -descending
Write-Output $orderedrating
# Now search for the top rated host that can do a Cluster or a SAN migration
# All other migration options are not considered here
$targethost = $null
foreach ($rating in $orderedrating)
{
if ($rating.Rating -gt 0)
{
switch ($rating.TransferType)
{
# These options are listed in order of decreasing transfer speed
"Live"
{
Write-Output "$rating.Name has a transfer type of Live"
$targethost = $rating.Name
break
}
"Cluster"
{
Write-Output "$rating.Name has a transfer type of Cluster"
$targethost = $rating.Name
break
}
"San"
{
Write-Output "$rating.Name has a transfer type of SAN"
$targethost = $rating.Name
break
}
"Network"
{
Write-Output "$rating.Name has a transfer type of Network"
}
default
{
Write-Output "$rating.Name has an invalid TransferType"
}
}
}
}
if ($targethost -eq $null)
{
Write-Warning "We were not able to find a suitable destination
host for this VM with a fast transfer (SAN or Cluster)"
break
}
# Migrate the VM to the target host
$VMHost = Get-VMHost -ComputerName $targethost
$resultvm = Move-VM -VM $VM -vmhost $VMHost -Path $VMHost.VMPaths[0]
-RunAsynchronously
# Get the VMM Job that was launched for this migration $job = $resultvm.MostRecentTask
# Iterate the loop until the Job is finished while reporting progress while ($job.Status -eq "Running")
{
$progress = $job.Progress
Write-Progress $VM Progress -PercentComplete $job.ProgressValue -ID 1
Start-Sleep 3
}
# The VMM job is now finished (either with a failed or a completed status)
$status = $job.Status
Write-Warning "Migration of $VM to host $VMHost finished
with a status of: $status"
$error = $job.ErrorInfo | select DisplayableErrorCode,
Problem, RecommendedActionCLI
Write-Warning $error
In some cases, it is beneficial to force a LAN migration even when a faster migration option is available. The only change from the code in Listing 8.5 would be a small change in the Move-VM cmdlet to add the UseLAN option as indicated here.
# Use the -UseLAN option to force a Network transfer of the Virtual Machine
$resultvm = Move-VM -VM $VM -vmhost $VMHost -Path $VMHost.VMPaths[0]
-RunAsynchronously -UseLAN
Provisioning Multiple Virtual Machines
Virtual machines are usually provisioned on demand based on customer requirements. However, there are cases where having many virtual machines available for immediate use is a requirement. Such scenarios might include hosted desktops allocating virtual machines from a pool of VMs or allocating VMs to an enterprise application based on load. In the PowerShell script in Listing 8.6, we read the input from a text file and create virtual machines in blocks of five at a time (the throttling rate is customizable). This allows us to customize and repeat the automated provisioning process by updating a text file rather than having to adjust a PowerShell script.
Listing 8.6: PowerShell script for creating multiple VMs based on an input file
# get the command line arguments passed to this script
$length = $args.length
$expectedArgsLength = 2
# The script takes as input the customization filepath and the VMM server name
$usage = "Usage: ScriptName.ps1
if ($length -ne $expectedArgsLength)
{
write-warning $usage;
break
}
# The ArrayList to use for tracking new-vm creations
$arraylist = New-Object System.Collections.ArrayList
$arraylist.Clear()
# The max number of concurrent VM creations (throttling rate)
$MaxCreations = 5
|
||||
# Get a connection to the VMM server
$servername = $args[1]
get-vmmserver -ComputerName $servername
# now open the customization file to read its input
$customFile = $args[0]
$content = get-content $customFile
foreach ($values in $content)
{
# $values contains one line of input. Each line represents a VM
# now split the CSV input line
$newvalues = $values |% {$_.split(",")}
# Perform a test to ensure the proper number of parameters exist
if ($newvalues.length -ne 14)
{
write-warning "The proper number of parameters does not exist for $values";
break
}
# get the input variables from the file and into the specific variables
$vmname = $newvalues[0] # The virtual machine name
$computername = $newvalues[1] # The guest OS computer name
$memory = $newvalues[2] # The amount of RAM to allocate to the VM
$OSSKU = $newvalues[3] # The OS name (VMM has these
already defined)
$ProductID = $newvalues[4] # The Windows Product ID
$description = $newvalues[5] # A description for the VM
$vmpath = $newvalues[6] # The path where to create this VM
$vnetworkname = $newvalues[7] # The Virtual Network Name
$hostname = $newvalues[8] # The name of the host to place this VM on
$cpuvalue = $newvalues[9] # The CPU Name (VMM has these
already defined)
$cpucount = $newvalues[10] # The number of CPUs
$owner = $newvalues[11] # The owner of the VM
$adminpwd = $newvalues[12] # The guest OS administrator password
$templatename = $newvalues[13] # The template name from
which to create this VM
# Create the Job Group ID and the hardware profile name
$jobguid = [guid]::NewGuid().ToString()
$profilename = "Profile" + $jobguid
# create the VM based on the settings in the file - this will happen asynchronously
Set-VirtualFloppyDrive -RunAsynchronously -VMMServer $servername
-NoMedia -JobGroup $jobguid
New-VirtualNetworkAdapter -VMMServer $servername -JobGroup
$jobguid -PhysicalAddressType Dynamic -VirtualNetwork $vnetworkname
-VLanEnabled $false
New-VirtualDVDDrive -VMMServer $servername -JobGroup $jobguid -Bus 1 -LUN 0
$CPUType = Get-CPUType -VMMServer $servername | where {$_.Name -eq $cpuvalue}
New-HardwareProfile -VMMServer $servername -Owner $owner
-CPUType $CPUType -Name $profilename -Description "Profile used to
create a VM/Template" -CPUCount $cpucount -MemoryMB
$memory -ExpectedCPUUtilization 20 -DiskIO 0 -NetworkUtilization
10 -RelativeWeight 100 -HighlyAvailable $false -NumLock $false
-BootOrder "CD", "IdeHardDrive", "PxeBoot", "Floppy"
-LimitCPUFunctionality $false -JobGroup $jobguid
$Template = Get-Template -VMMServer $servername | where
{$_.Name -eq $templatename}
$VMHost = Get-VMHost -VMMServer $servername | where {$_.Name -eq $hostname} $HardwareProfile = Get-HardwareProfile -VMMServer localhost |
where {$_.Name -eq $profilename}
$OperatingSystem = Get-OperatingSystem -VMMServer localhost |
where {$_.Name -eq $OSSKU}
# Before we start the new-vm creation we need to check
# if we reached the maximum number of concurrent creations while ($arraylist.Count -eq $MaxCreations)
{
$toremove = $null
foreach ($jobid in $arraylist)
{
# get the current status of the job
$tempjobid = [string]::join("", $jobid.Keys)
$tempjob = Get-Job -ID $tempjobid;
if ($tempjob.Status -ne "Running")
{
# This job completed, so remove it from the tracking list
so that new VMs can be created
Write-Output "Job $tempjobid finished running"
$toremove = $jobid
break
}
}
if ($toremove -ne $null)
{
$arraylist.Remove($jobid)
}
Start-Sleep 2
}
# if we reached here, it is safe to create the new VM
$resultvm = New-VM -Template $Template -Name $vmname
-Description $description -VMHost $VMHost -Path $vmpath -JobGroup
$jobguid -Owner $owner -HardwareProfile $HardwareProfile
-ComputerName $computername -FullName "" -OrgName "" -ProductKey
$ProductID -TimeZone 4 -JoinWorkgroup "WORKGROUP" -OperatingSystem
$OperatingSystem -RunAsSystem -StartAction
NeverAutoTurnOnVM -UseHardwareAssistedVirtualization $false
-StopAction SaveVM -RunAsynchronously
# Now start tracking this new-vm instance
if ($resultvm -ne $null)
{
# Get the VMM Job that was launched for this migration
$job = $resultvm.MostRecentTask
$arraylist.Add(@{$job.ID = $job})
}
}
write-output "Done creating All VMs!"
The following code contains a sample line from an input text file that can be used in the script in Listing 8.6. This line contains the values for the different virtual machine properties that are needed by the PowerShell script. These values need to be specified in order, and their descriptions are as follows:
- The virtual machine name
- The guest OS computer name
- The amount of RAM or memory to allocate to the VM
- The OS name (VMM has these already defined)
- The Windows product ID
- A description for the VM
- The path describing where to create this VM
- The virtual network name
- The name of the host on which to place this VM
- The CPU name (VMM has these already defined.)
- The number of CPUs
- The owner of the VM
- The guest OS administrator password
- The name of the template from which to create this VM
vmname1,vmname1ComputerName,1024,64-bit edition of Windows Server 2008
Enterprise,55555-55555-55555-55555-55555,scripted VM,D:ProgramDataMicrosoft
WindowsHyper-V,Broadcom NetXtreme 57xx Gigabit Controller - Virtual Network,hypervhost1.vmmdomain.com,2.40 GHz Xeon,1,vmmdomainadministrator,
password,MyTemplate
Automation Using PowerShell
Using Windows Powershell scripts for task automation
Virtual machine migration via Windows PowerShell scripts
New virtual machine management using VMM, PowerShell
Printed with permission from Wiley Publishing Inc. Copyright 2009. Mastering Virtual Machine Manager 2008 R2 by Michael Michael and Hector Linares. For more information about this title and other similar books, please visit Wiley Publishing Inc.