Sample Script for Managing Hosts

You can experiment with the Windows PowerShell script in this topic to learn how to script adding to Virtual Machine Manager computers that are running Virtual Server but that are not currently managed by Virtual Machine Manager.

AddVSServerAsHost.ps1

You can use the AddVSServerAsHost.ps1 script to search Active Directory for servers that have Virtual Server 2005 R2 installed but are not currently managed by Virtual Machine Manager. You can use the script to add those servers as managed virtual machine hosts.

How AddVSServerAsHost.ps1 Works

The following sections explain each part of the script AddVSServerAsHost.ps1.

Connect to VMM Server

The first command in the script AddVSServerAsHost.ps1 connects to the Virtual Machine Manager server so that subsequent commands can access objects in the Virtual Machine Manager database.

####################################################################
# Connect to the Virtual Machine Manager server
####################################################################
# Substitute the name of your VMM server and domain in this command:
Get-VMMServer -ComputerName "VMMServer1.Contoso.com"

Define a Function That Returns the FQDN of a Computer

The next set of commands in the script AddVSServerAsHost.ps1 defines a function in which Windows PowerShell uses C# commands to return the fully qualified domain name (FQDN) of a computer by performing the following tasks:

  • Retrieves the domain name and computer name of a computer from the Lightweight Directory Access Protocol (LDAP) string for that computer.
  • Concatenates the domain name and computer name to return the computer's FQDN.

The script invokes the defined function later (in the ForEach loop) after first using an LDAP (Lightweight Directory Access Protocol) query to return from Active Directory objects that represent all computers on which Virtual Server 2005 R2 is installed.

LDAP, an industry standard that is implemented by both Windows operating systems and non-Windows operating systems, is the primary directory access protocol that Windows operating systems use to add, modify, and delete information that is stored in Active Directory and to query and retrieve data from Active Directory. For more information about LDAP, see "Lightweight Directory Access Protocol" at https://go.microsoft.com/fwlink/?LinkId=104719.

####################################################################
# Define a function that selects the FQDN of a computer from the 
# LDAP string returned from Active Directory by the LDAP query. 
# (The LDAP query occurs later in this script.)
####################################################################
function Get-FQDN
{
   # Declare the parameter for the LDAP string.
   Param( $LDAPString )

   # Get the domain name from the LDAP string.
   $Domain = $LDAPString.ToString().SubString( $LDAPString.ToString().IndexOf(",DC=") + 4 )
   $Domain = $Domain.ToString().Replace(",DC=", ".")

   # Get the computer name from the LDAP string.
   $ComputerName = $LDAPString.Split(',')[1].Remove(0,3)

   # Return the FQDN from the function.
   Return $ComputerName + "." + $Domain
}

Define a Function That Adds a Computer to VMM as a Host

The next set of commands in the script AddVSServerAsHost.ps1 defines a function that adds a computer as a managed host to Virtual Machine Manager by performing the following tasks:

  • Displays a message each time a host is added.

  • Retrieves the object that represents the group to which the host will be added, and adds the host to that group.

  • Enables Virtual Machine Remote Control (VMRC) and configures several VMRC settings: The script allows only one connection at a time to a virtual machine by disabling multiple VMRC connections; sets the VMRC port to 5900 (the default port); enables a VMRC timeout interval (the length of time a VMRC connection remains idle before it is automatically disconnected); and sets the VMRC timeout interval to 30 minutes.

    Note

    VMRC is a feature of Microsoft Virtual Server 2005 that lets a VMRC client connect to an instance of Virtual Server to access that server's virtual machines. VMRC enables users to access their virtual machines remotely.

The script will invoke the defined function later (in the ForEach loop), after it uses the Get-FQDN function to retrieve the FQDN of computers that are running Virtual Server and after it selects only those computers that are running Virtual Server and that are not already managed by Virtual Machine Manager.

####################################################################
# Define a function that adds a computer as a host to VMM
####################################################################
function Add-NewVMHost
{
   # Declare the parameter for the name of the host.
   param( $HostName )

   # Display a message each time a host is added.
   "Adding host '" + $HostName + "'..."

   # Get the object that represents the host group in which you want 
   # to place a new host.
   $HostGroup = Get-HostGroup -Name "All Hosts"

   # Add the new host to the specified host group and configure VMRC.
   Add-VMHost -ComputerName $HostName -VMHostGroup $HostGroup -VMRCEnabled $TRUE -VMRCMultipleConnectionsEnabled $FALSE -VMRCPort 5900 -VMRCTimeoutEnabled $TRUE -VMRCTimeoutMinutes 30
}

Identify Servers Running Virtual Server 2005 R2

The next set of commands in the script AddVSServerAsHost.ps1 uses an LDAP query to identify servers that are running Virtual Server 2005 R2 by performing the following tasks:

  • Creates an object that represents the organizational unit (OU) container for all computers that are located in the Contoso.com domain, and stores the object in variable $Root. The name $Root is used to indicate that the root of the search to be performed is set at the OU in the directory hierarchy.
  • Creates a directory search object that is used to search $Root for objects that represent computers on which the Virtual Server service is installed, and then stores the search object in $Searcher.
  • Runs an LDAP query to find the object that represents each computer on which Virtual Server is installed and stores the returned objects as an object array in variable $Result.

The script loops through each object in $Result later (in the ForEach loop) to determine whether a given object is or is not already managed by Virtual Machine Manager.

####################################################################
# Use an LDAP query to get computers running Virtual Server 2005 R2.
####################################################################

# Create an object that represents the OU container for computers in 
# the Contoso.com domain, and store the new object in variable $Root.
$Root = New-Object DirectoryServices.DirectoryEntry "LDAP://OU=Computers,DC=contoso,DC=com"

# Create a directory search object to search $Root for objects that 
# represent computers on which Virtual Server is installed, and store 
# the search object in variable $Searcher.

$Searcher = New-Object DirectoryServices.DirectorySearcher $Root, "(&(objectCategory=serviceConnectionPoint)(CN=MS Virtual Server))"

# Run the LDAP query and store the returned objects as an 
# object array in variable $Result.
$Result = $Searcher.FindAll()

Add Non-VMM Computers Running Virtual Server to VMM

The last set of commands in the script AddVSServerAsHost.ps1 adds each computer to Virtual Machine Manager if it is running Virtual Server 2005 R2 but is not currently managed by Virtual Machine Manager by using a ForEach loop to perform the following tasks:

  • Loops through each object in $Result (that is, each server running Virtual Server) in turn.
  • Uses the Get-FQDN function that was defined earlier to get the FQDN of each computer in $Result.
  • Uses the Virtual Machine Manager cmdlet Get-VMHost to determine whether a computer in $Result is already managed by Virtual Machine Manager.
  • If a computer in $Result is not currently managed by Virtual Machine Manager, the script uses the Add-NewVMHost function that was defined earlier to add the computer to Virtual Machine Manager.
####################################################################
# Process each object in $Result (that is, each computer running 
# Virtual Server) and add that computer to the VMM database if it 
# has Virtual Server installed but is not yet a VMM host.
####################################################################
ForEach ($Object in $Result)
{
   # Get the fully qualified domain name.
   $FQDN = Get-FQDN( $Object.GetDirectoryEntry().DistinguishedName.ToString() )

   # Determine whether the computer is already managed by VMM and, 
   # if not, add it to VMM as a managed host. 
 
   If(!(Get-VMHost | where {$_.Name -Eq $FQDN}))
   {
       # Else (if the computer is not a host), add it to VMM as a host
       Add-NewVMHost $FQDN
   }
}

AddVSServerAsHost.ps1 - Complete Script

Copy the following complete version of AddVSServerAsHost.ps1 into a Notepad file, and save it as AddVSServerAsHost.ps1.

# Filename:    AddVSServerAsHost.ps1
# Description: Search Active Directory for servers on which 
#              Virtual Server 2005 R2 is installed that are 
#              not currently managed by System Center Virtual 
#              Machine Manager. Add those servers as hosts to 
#              Virtual Machine Manager.

# DISCLAIMER:
# Copyright © Microsoft Corporation. All rights reserved. This 
# script is made available to you without any express, implied or 
# statutory warranty, not even the implied warranty of 
# merchantability or fitness for a particular purpose, or the 
# warranty of title or non-infringement. The entire risk of the 
# use or the results from the use of this script remains with you.

####################################################################
# Connect to the Virtual Machine Manager server
####################################################################
# Substitute the name of your VMM server and domain in this command:
Get-VMMServer -ComputerName "VMMServer1.Contoso.com"

####################################################################
# Define a function that selects the FQDN of a computer from the 
# LDAP string returned from Active Directory by the LDAP query. 
# (The LDAP query occurs later in this script.)
####################################################################
function Get-FQDN
{
   # Declare the parameter for the LDAP string.
   Param( $LDAPString )

   # Get the domain name from the LDAP string.
   $Domain = $LDAPString.ToString().SubString( $LDAPString.ToString().IndexOf(",DC=") + 4 )
   $Domain = $Domain.ToString().Replace(",DC=", ".")

   # Get the computer name from the LDAP string.
   $ComputerName = $LDAPString.Split(',')[1].Remove(0,3)

   # Return the FQDN from the function.
   Return $ComputerName + "." + $Domain
}

####################################################################
# Define a function that addS a computer as a host to VMM
####################################################################
function Add-NewVMHost
{
   # Declare the parameter for the name of the host.
   param( $HostName )

   # Display a message each time a host is added.
   "Adding host '" + $HostName + "'..."

   # Get the object that represents the host group in which you want 
   # to place a new host.
   $HostGroup = Get-HostGroup -Name "All Hosts"

   # Add the new host to the specified host group and configure VMRC.
   Add-VMHost -ComputerName $HostName -VMHostGroup $HostGroup -VMRCEnabled $TRUE -VMRCMultipleConnectionsEnabled $FALSE -VMRCPort 5900 -VMRCTimeoutEnabled $TRUE -VMRCTimeoutMinutes 30
}

####################################################################
# Use an LDAP query to get computers running Virtual Server 2005 R2.
####################################################################

# Create an object that represents the OU container for computers in 
# the Contoso.com domain and store the new object in variable $Root.
$Root = New-Object DirectoryServices.DirectoryEntry "LDAP://OU=Computers,DC=contoso,DC=com"

# Create a directory search object to search $Root for objects that 
# represent computers on which Virtual Server is installed, and store 
# the search object in variable $Searcher.

$Searcher = New-Object DirectoryServices.DirectorySearcher $Root, "(&(objectCategory=serviceConnectionPoint)(CN=MS Virtual Server))"

# Run the LDAP query and then store the returned objects as an 
# object array in variable $Result.
$Result = $Searcher.FindAll()

####################################################################
# Process each object in $Result (that is, each computer running 
# Virtual Server) and add that computer to the VMM database if it 
# has Virtual Server installed but is not yet a VMM host.
####################################################################
ForEach ($Object in $Result)
{
   # Get the fully qualified domain name.
   $FQDN = Get-FQDN( $Object.GetDirectoryEntry().DistinguishedName.ToString() )

   # Determine whether the computer is already managed by VMM and, 
   # if not, add it to VMM as a managed host. 
 
   If(!(Get-VMHost | where {$_.Name -Eq $FQDN}))
   {
       # Else (if the computer is not a host), add it to VMM as a host
       Add-NewVMHost $FQDN
   }
}

QuickMigrate-VM.ps1

The QuickMigrate-VM.psi script quickly migrates a highly available virtual machine from its existing host to the best rated host that is part of the same host cluster.

The virtual machine must be configured as a highly available virtual machine (using Havm.vbs script) on Windows Server 2003 host cluster. The virtual machine must have its Custom7 property set to the name of the cluster resource group that it belongs to.

All the nodes of the Windows Server 2003 host cluster must be added as hosts in the Virtual Machine Manager 2007. All the clustered hosts must have their Custom7 property set to the name of the host cluster to which they belong.

QuickMigrate-VM.ps1 - Complete Script

# DISCLAIMER:
# Copyright (c) Microsoft Corporation. All rights reserved. This 
# script is made available to you without any express, implied or 
# statutory warranty, not even the implied warranty of 
# merchantability or fitness for a particular purpose, or the 
# warranty of title or non-infringement. The entire risk of the 
# use or the results from the use of this script remains with you.
##################################################################################
# Check usage
##################################################################################

param ($VMName, $VMMServerName)
if ($VMName -eq $null -or $VMMServerName -eq $null)
{
  Write-Host -foregroundcolor DarkGray "`nUsage: QuickMigrate-VM -VMName <String> -VMMServerName <String>"
  Write-Host -foregroundcolor DarkGray "`nQuickly migrates a highly available virtual machine from its existing"
  Write-Host -foregroundcolor DarkGray "host to the best rated host that is part of the same host cluster."
  Write-Host -foregroundcolor DarkGray "`nThe virtual machine must be configured as a highly available virtual"
  Write-Host -foregroundcolor DarkGray "machine (using havm.vbs script) on Windows Server 2003 host cluster."
  Write-Host -foregroundcolor DarkGray "The virtual machine must have its Custom7 property set to the name"
  Write-Host -foregroundcolor DarkGray "of the cluster resoruce group that it belongs to."
  Write-Host -foregroundcolor DarkGray "`nAll the nodes of the Windows Server 2003 host cluster must be added"
  Write-Host -foregroundcolor DarkGray "as hosts in the Virtual Machine Manager 2007. All the clustered hosts"
  Write-Host -foregroundcolor DarkGray "must have its Custom7 property set to the name of the host cluster"
  Write-Host -foregroundcolor DarkGray "that they belong to."
  Write-Host -foregroundcolor DarkGray "`nUser running the script must be VMM administrator as well as cluster"
  Write-Host -foregroundcolor DarkGray "administrator."
  Write-Host
  return
}
##################################################################################
# Connect to Virtual Machine Manager server
##################################################################################
Write-Host "`nTrying to connect to Virtual Machine Manager server $VMMServerName. This may take some time..."
$VMMServer = Get-VMMServer -ComputerName $VMMServerName

if ($VMMServer -eq $null)
{
  Write-Host "  ERROR: Cannot connect to Virtual Machine Manager server $VMMServerName`n" -foregroundcolor Red 
  return
}
else
{
  Write-Host "  Done!`n" -foregroundcolor Yellow
}
##################################################################################
# Get cluster resource group name which is Custom7 property of virtual machine
##################################################################################
Write-Host "Trying to find virtual machine $VMName..."
$VM = Get-VM -Name $VMName
if ($VM -eq $null)
{
  Write-Host "  ERROR: Cannot find virtual machine $VMName in VMM server $VMMServerName`n" -foregroundcolor Red
  return
}
else
{
  Write-Host "  Done!`n" -foregroundcolor Yellow
}
Write-Host "Trying to get cluster resource group name by reading Custom7 property of virtual machine $VMName..."
if ($VM.CustomProperties[6] -eq "")
{
  Write-Host "  ERROR: $VMName does not appear to be highly available virtual machine since its Custom7 property is blank`n" -foregroundcolor Red
  return
}
else
{
  $ResourceGroupName = $VM.CustomProperties[6]
  Write-Host "  Done! Cluster resource group name is '$ResourceGroupName'`n" -foregroundcolor Yellow
}
##################################################################################
# Get host cluster name which is Custom7 property of virtual machine host
##################################################################################
Write-Host "Trying to find current host of virtual machine $VMName..."
$VMHostName = ($VM.HostName).split(".")[0]
$VMHost = Get-VMHost -ComputerName $VMHostName
if ($VMHost -eq $null)
{
  Write-Host "  ERROR: Cannot find virtual machine host $VMHostName in VMM server $VMMServerName`n" -foregroundcolor Red
  return
}
else
{
  Write-Host "  Done! Current host is $VMHostName`n" -foregroundcolor Yellow
}
Write-Host "Trying to get host cluster name by reading Custom7 property of host $VMHostName..."
if ($VMHost.Custom7 -eq "")
{
  Write-Host "  ERROR: $VMHostName does not appear to be a clustered host since its Custom7 property is blank`n" -foregroundcolor Red
  return
}
else
{
  $ClusterName = $VMHost.Custom7
  Write-Host "  Done! Host cluster name is $ClusterName `n" -foregroundcolor Yellow
}
##################################################################################
# Ensure that the host cluster exists
##################################################################################
Write-Host "Trying to connect to host cluster $ClusterName. This may take some time..."
$Cluster = Get-WmiObject -class MSCluster_Cluster -namespace root\mscluster -computerName $ClusterName
if ($Cluster -eq $null)
{
  Write-Host "  ERROR: Cannot connect to host cluster $ClusterName `n" -foregroundcolor Red
  return 
}
else
{
  Write-Host "  Done!`n" -foregroundcolor Yellow
}
##################################################################################
# Ensure that the current host is part of the host cluster
##################################################################################
Write-Host "Trying to find current host $VMHostName in host cluster $ClusterName..."
$Node = Get-WmiObject -class MSCluster_Node -namespace root\mscluster -computerName $ClusterName -filter "Name='$VMHostName'"
if ($Node -eq $null)
{
  Write-Host "  ERROR: Cannot find current host $VMHostName in host cluster $ClusterName`n" -foregroundcolor Red
  return 
}
else
{
  Write-Host "  Done!`n" -foregroundcolor Yellow
}
##################################################################################
# Ensure that the cluster resource group is owned by the current host
##################################################################################
Write-Host "Trying to find cluster resource group $ResourceGroupName on current host $VMHostName..."
$Query = "select * from MSCluster_NodeToActiveGroup where GroupComponent=`"MSCluster_Node.Name='$VMHostName'`" and PartComponent=`"MSCluster_ResourceGroup.Name='$ResourceGroupName'`""
$NodeToActiveGroup = Get-WmiObject -namespace root\mscluster -computerName $ClusterName -query $Query
if ($NodeToActiveGroup -eq $null)
{
  Write-Host "  ERROR: Cannot find cluster resource group $ResourceGroupName on current host $VMHostName`n" -foregroundcolor Red
  return 
}
else
{
  $ResourceGroup = Get-WmiObject -class MSCluster_ResourceGroup -namespace root\mscluster -computerName $ClusterName -filter "Name='$ResourceGroupName'"
  Write-Host "  Done!`n" -foregroundcolor Yellow
}
##################################################################################
# Get the best rated target host
##################################################################################
Write-Host "Trying to select the best rated host having Custom7 set to $ClusterName as target for quick migration..."

$TargetVMHosts = @(Get-VMHost) | where {($_.Custom7 -eq $ClusterName) -and ($_.Name -ne $VMHost.Name)}
if ($TargetVMHosts -eq $null)
{
  Write-Host "  ERROR: Cannot find any target hosts having Custom7 set to $ClusterName`n" -foregroundcolor Red
  return
}
else
{
  $TargetVMHostRatings = @(Get-VMHostRating -VM $VM -VMHost $TargetVMHosts) | Sort-Object -property Rating -descending
  Write-Host
  Write-Host "    TARGET HOST`t`tVMM RATING" -foregroundcolor DarkGray
  Write-Host "    ===========`t`t==========" -foregroundcolor DarkGray
  foreach ($TargetVMHostRating in $TargetVMHostRatings)
  {
    Write-Host "   ", ($TargetVMHostRating.Name).split(".")[0], "`t`t", $TargetVMHostRating.Rating -foregroundcolor DarkGray
  }
  Write-Host
  $TargetHostName = (@($TargetVMHostRatings)[0].Name).split(".")[0]
  Write-Host "  Done! Selected target host $TargetHostName`n" -foregroundcolor Yellow
}
##################################################################################
# Ensure that the target host is part of the host cluster
##################################################################################
Write-Host "Trying to find target host $TargetHostName in host cluster $ClusterName..."
$Node = Get-WmiObject -class MSCluster_Node -namespace root\mscluster -computerName $ClusterName -filter "Name='$TargetHostName'"
if ($Node -eq $null)
{
  Write-Host "  ERROR: Cannot find target host $TargetHostName in host cluster $ClusterName`n" -foregroundcolor Red
  return 
}
else
{
  Write-Host "  Done!`n" -foregroundcolor Yellow
}
##################################################################################
# Move the cluster resource group to the target host 
##################################################################################
Write-Host "Quick-migrating virtual machine $VMName to the best rated host $TargetHostName. This may take some time. "
$ResourceGroup.MoveToNewNode($TargetHostName, 30)
Write-Host "  Done!`n" -foregroundcolor Yellow