Shortly after TR9 I had the opportunity to talk with STB President Bob Muglia about Virtualization. Click the picture to open this 5 minute audio podcast from my public Skydrive (TR9 – Bob Muglia). Includes Bob’s thoughts about customer advantages of Microsoft’s virtualization solutions, including Hyper-V R2 and System Center, as well as thoughts about what the future holds as IT moves to the cloud.
For more information see http://www.microsoft.com/virtualization.
In this 5 minute video Windows Server Technical Writer Felipe Ayora demonstrates how to change the BIOS settings on your computer to make the hypervisor run. NOTE: remember to completely power off your computer after making the changes to the BIOS. Some computers will not take the changes unless they are powered off and back on.
This error (BIOS misconfig) stalls many users.
Link: http://www.microsoft.com/downloads/details.aspx?FamilyID=292de23c-845c-4d08-8d65-b4b8cbc8397b
Team Blog http://blogs.technet.com/systemcenter/archive/2009/08/24/system-center-virtual-machine-manager-vmm-2008-r2-rtms.aspx
Some friends here on the Hyper-V team shared a PowerShell 2.0 script for checking the integration services/integration components to see if they are current in your VMs:
# Test if the IC version is up to date param( [string]$vmName = $(throw "Must specify virtual machine name") ) $vm = gwmi -namespace root\virtualization Msvm_ComputerSystem -filter "ElementName='$vmName'" # Get the associated KVP Exchange component $kvp = gwmi -namespace root\virtualization ` -query "Associators of {$vm} where ResultClass=Msvm_KvpExchangeComponent" # Pull the Guest Intrinsic Exchange Items from XML into a hash $kvpHash = @{} if($kvp.GuestIntrinsicExchangeItems){ ([xml]("<xml>"+$kvp.GuestInstrinsicExchangeItems+"</xml>")).xml.instance | ` foreach{$kvphash.add($_.property[4].value,$_.property[1].value)} } # Save the guest's version $icVersionGuest = $kvpHash.IntegrationServicesVersion # Save the host's version $icVersionHost = (ls 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\GuestInstaller').` GetValue("Microsoft-Hyper-V-Guest-Installer-Win60-Package") return -not $icVersionGuest -lt $icVersionHost
# Test if the IC version is up to date
param( [string]$vmName = $(throw "Must specify virtual machine name") )
$vm = gwmi -namespace root\virtualization Msvm_ComputerSystem -filter "ElementName='$vmName'"
# Get the associated KVP Exchange component $kvp = gwmi -namespace root\virtualization ` -query "Associators of {$vm} where ResultClass=Msvm_KvpExchangeComponent"
# Pull the Guest Intrinsic Exchange Items from XML into a hash $kvpHash = @{} if($kvp.GuestIntrinsicExchangeItems){ ([xml]("<xml>"+$kvp.GuestInstrinsicExchangeItems+"</xml>")).xml.instance | ` foreach{$kvphash.add($_.property[4].value,$_.property[1].value)} }
# Save the guest's version $icVersionGuest = $kvpHash.IntegrationServicesVersion
# Save the host's version $icVersionHost = (ls 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\GuestInstaller').` GetValue("Microsoft-Hyper-V-Guest-Installer-Win60-Package")
return -not $icVersionGuest -lt $icVersionHost
For more info on how to use PS cmdlets see: http://www.microsoft.com/technet/scriptcenter/topics/msh/cmdlets/index.mspx
See also James O’Neil’s New and improved PowerShell Library for Hyper-V. Now with more functions and... documentation!
For all 35 sample Hyper-V PS1 scripts in a zipfile, go to: Hyper-V PowerShell Example Scripts.zip-download
Some friends here on the Hyper-V team shared a PowerShell 2.0 script for checking in the hypervisor is running on a Hyper-V server (host/parent partition):
# Check if Hypervisor is running $hypervisor = gwmi –ErrorAction SilentlyContinue Win32_PerfRawData_HvStats_HyperVHypervisor return $hypervisor.Partitions -ge 1
# Check if Hypervisor is running
$hypervisor = gwmi –ErrorAction SilentlyContinue Win32_PerfRawData_HvStats_HyperVHypervisor return $hypervisor.Partitions -ge 1
Some friends here on the Hyper-V team shared a PowerShell 2.0 script for taking a snapshot of your VMs:
# Take a snapshot of a VM param( [string]$vmName = $(throw "Must specify virtual machine name") ) # Get the virtual machine by name $vm = gwmi -namespace root\virtualization Msvm_ComputerSystem -filter "ElementName='$vmName'" # Get the management service and apply the snapshot $vmms = gwmi -namespace root\virtualization Msvm_VirtualSystemManagementService #Create the SnapShot $result = $vmms.CreateVirtualSystemSnapShot($vm) if($result.ReturnValue -eq 4096){ # A Job was started, and can be tracked using its Msvm_Job instance $job = [wmi]$result.Job # Wait for job to finish while($job.jobstate -lt 7){$job.get()} # Return the Job's error code return $job.ErrorCode } # Otherwise, the method completed return $result.ReturnValue
# Take a snapshot of a VM
# Get the virtual machine by name $vm = gwmi -namespace root\virtualization Msvm_ComputerSystem -filter "ElementName='$vmName'"
# Get the management service and apply the snapshot $vmms = gwmi -namespace root\virtualization Msvm_VirtualSystemManagementService
#Create the SnapShot $result = $vmms.CreateVirtualSystemSnapShot($vm)
if($result.ReturnValue -eq 4096){ # A Job was started, and can be tracked using its Msvm_Job instance $job = [wmi]$result.Job # Wait for job to finish while($job.jobstate -lt 7){$job.get()} # Return the Job's error code return $job.ErrorCode } # Otherwise, the method completed return $result.ReturnValue
Some friends here on the Hyper-V team shared a PowerShell 2.0 script for shutting down your VMs:
# Shutdown a Virtual Machine (requires Integration Components) param( [string]$vmName = $(throw "Must specify virtual machine name") ) # Get the VM by name and request state to change to Enabled $vm = gwmi -namespace root\virtualization Msvm_ComputerSystem -filter "ElementName='$vmName'" # Get the associated Shutdown Component $shutdown = gwmi -namespace root\virtualization ` -query "Associators of {$vm} where ResultClass=Msvm_ShutdownComponent" # Initiate a forced shutdown with simple reason string, return resulting error code return $shutdown.InitiateShutdown($true,"System Maintenance")
# Shutdown a Virtual Machine (requires Integration Components)
# Get the VM by name and request state to change to Enabled $vm = gwmi -namespace root\virtualization Msvm_ComputerSystem -filter "ElementName='$vmName'"
# Get the associated Shutdown Component $shutdown = gwmi -namespace root\virtualization ` -query "Associators of {$vm} where ResultClass=Msvm_ShutdownComponent"
# Initiate a forced shutdown with simple reason string, return resulting error code return $shutdown.InitiateShutdown($true,"System Maintenance")
Some friends here on the Hyper-V team shared a PowerShell 2.0 script for setting custom KVPs:
# Set a Custom KVP param( [string]$vmName = $(throw "Must specify virtual machine name"), [string]$Key = $(throw "Must specify a key"), [string]$Value = $(throw "Must specify a value") ) $vm = gwmi -namespace root\virtualization Msvm_ComputerSystem -filter "ElementName='$vmName'" # Get a new KVP Exchange Data Item and populate the Name, Data, and Source $newKvpClass = [wmiclass]"root\virtualization:Msvm_KvpExchangeDataItem" $newKvp = $newKvpClass.CreateInstance() $newKvp.Name = $Key $newKvp.Data = $Value $newKvp.Source = 0 # Use 4 here if the key should not be sent to the guest # Get the management service and set the KVP for this VM $vmms = gwmi -namespace root\virtualization Msvm_VirtualSystemManagementService $result = $vmms.AddKvpItems($vm, $newKvp) if($result.ReturnValue -eq 4096){ # A Job was started, and can be tracked using its Msvm_Job instance $job = [wmi]$result.Job # Wait for job to finish while($job.jobstate -lt 7){$job.get()} # Return the Job's error code return $job.ErrorCode } # Otherwise, the method completed return $result.ReturnValue
# Set a Custom KVP
param( [string]$vmName = $(throw "Must specify virtual machine name"), [string]$Key = $(throw "Must specify a key"), [string]$Value = $(throw "Must specify a value") )
# Get a new KVP Exchange Data Item and populate the Name, Data, and Source $newKvpClass = [wmiclass]"root\virtualization:Msvm_KvpExchangeDataItem" $newKvp = $newKvpClass.CreateInstance() $newKvp.Name = $Key $newKvp.Data = $Value $newKvp.Source = 0 # Use 4 here if the key should not be sent to the guest
# Get the management service and set the KVP for this VM $vmms = gwmi -namespace root\virtualization Msvm_VirtualSystemManagementService
$result = $vmms.AddKvpItems($vm, $newKvp)
Some friends here on the Hyper-V team shared a PowerShell 2.0 script for removing virtual NICs from your VMs:
# Remove a NIC (synthetic ethernet port) from a virtual machine param( [string]$vmName = $(throw "Must specify virtual machine name"), [string]$ethPortName = $(throw "Must specify virtual NIC name") ) $vm = gwmi -namespace root\virtualization Msvm_ComputerSystem -filter "ElementName='$vmName'" # Find the NIC from the virtual system setting data $vssd = gwmi -namespace root\virtualization ` -query "Associators of {$vm} where ResultClass = Msvm_VirtualSystemSettingData" |` where{$_.SettingType -eq 3} $synthEth = gwmi -namespace root\virtualization ` -query "Associators of {$vssd} where ResultClass = Msvm_SyntheticEthernetPortSettingData" |` where{$_.ElementName -eq $ethPortName} # Remove the NIC using the method available on the service $vmms = gwmi -namespace root\virtualization Msvm_VirtualSystemManagementService $result = $vmms.RemoveVirtualSystemResources($vm,@($synthEth)) if($result.ReturnValue -eq 4096){ # A Job was started, and can be tracked using its Msvm_Job instance $job = [wmi]$result.Job # Wait for job to finish while($job.jobstate -lt 7){$job.get()} # Return the Job's error code return $job.ErrorCode } # Otherwise, the method completed return $result.ReturnValue
# Remove a NIC (synthetic ethernet port) from a virtual machine
param( [string]$vmName = $(throw "Must specify virtual machine name"), [string]$ethPortName = $(throw "Must specify virtual NIC name") )
# Find the NIC from the virtual system setting data $vssd = gwmi -namespace root\virtualization ` -query "Associators of {$vm} where ResultClass = Msvm_VirtualSystemSettingData" |` where{$_.SettingType -eq 3} $synthEth = gwmi -namespace root\virtualization ` -query "Associators of {$vssd} where ResultClass = Msvm_SyntheticEthernetPortSettingData" |` where{$_.ElementName -eq $ethPortName}
# Remove the NIC using the method available on the service $vmms = gwmi -namespace root\virtualization Msvm_VirtualSystemManagementService
$result = $vmms.RemoveVirtualSystemResources($vm,@($synthEth))
Another Pun-tastic blog post title designed to defeat SEO!
Seriously though, in talking about Community (notice the capital C there?) with my peers, I encourage them to stop thinking of “us” as opposed “ them”, meaning YOU. “The Community” (another capital there…) includes us, at least that’s how it makes sense to me.
One “community” feature of interest to IT Pros (I’m going to stop both “quoting” and parens now…) is the Community Content feature on TechNet/MSDN.
For example, Hyper-V admins need to know the current list of patches for Hyper-V, so we list them here: Comprehensive List of Hyper-V Updates. However, since just about any workload might be running on that Hyper-V server host box, the admin might need to know about “related” patches too. So, we list those down at the bottom of the page in the Community Content.
Good idea? Useful? Leave comments.
Steve Holland has a new video on the Community Content feature of TechNet and MSDN. Click the image to watch the 10.5 minute video.
Check out the annotations page to grab the RSS feed of changes, then you can use your RSS reader to follow any updates to that page. I use Outlook and filter based on keywords of interest – saves a lot of time.
Some friends here on the Hyper-V team shared a PowerShell 2.0 script for getting a mapping your virtual network settings:
# Navigate Network Topology to determine Virtual Switch type # ie: Internal, External, External-Shared, or Private # Prompt for the Hyper-V Server to use $HyperVServer = Read-Host "Specify the Hyper-V Server to use (enter '.' for the local computer)" write-host # Get the list of all available network switches $query = "Select * From Msvm_VirtualSwitch" $VirtualSwitches = gwmi -namespace "root\virtualization" -Query $query -computername $HyperVServer # Iterate over each virtual switch foreach ($VirtualSwitch in $VirtualSwitches) { # Initialize variables for counting number of internal and external ports per switch $InternalPortCount = 0 $ExternalPortCount = 0 # Get the Switch ports on the virtual switch $query = "Associators of {$VirtualSwitch} where ResultClass=CIM_SwitchPort" $switchPorts = gwmi -namespace "root\virtualization" -Query $query -computername $HyperVServer # A VM only switch with no VMs connected will return null if ($switchPorts -ne $null) { # Iterate over each switch port foreach ($switchPort in @($switchPorts)) { # Get the Msvm_SwitchLANEndpoint associated with the switch port $query = "Associators of {$switchPort} where ResultClass=Msvm_SwitchLANEndpoint" $SwitchLANEndpoint = gwmi -namespace "root\virtualization" -Query $query -computername $HyperVServer # If there is no active connection on the switch port the results will be null if ($SwitchLANEndpoint -ne $null) { # Get the CIM_EthernetPort for the Msvm_SwitchLANEndpoint $query = "Associators of {$SwitchLANEndpoint} where ResultClass=CIM_EthernetPort" $EthernetPort = gwmi -namespace "root\virtualization" -Query $query -computername $HyperVServer # Check to see if the associated Ethernet port is an internal port if ($EthernetPort.__CLASS -eq "Msvm_InternalEthernetPort") { $InternalPortCount = $InternalPortCount + 1 } # Check to see if the associated Ethernet port is an external port if ($EthernetPort.__CLASS -eq "Msvm_ExternalEthernetPort") { $ExternalPortCount = $ExternalPortCount + 1 } } } } switch ($InternalPortCount) { 0 { switch ($ExternalPortCount) { 0 {$output = "The virtual switch '" + $VirtualSwitch.ElementName + "' is a virtual machine only virtual network."} 1 {$output = "The virtual switch '" + $VirtualSwitch.ElementName + "' is an external-only virtual network."} default {$output = "The virtual switch '" + $VirtualSwitch.ElementName + "' is not a standard virtual network."} } } 1 { switch ($ExternalPortCount) { 0 {$output = "The virtual switch '" + $VirtualSwitch.ElementName + "' is an internal virtual network."} 1 {$output = "The virtual switch '" + $VirtualSwitch.ElementName + "' is an external virtual network."} default {$output = "The virtual switch '" + $VirtualSwitch.ElementName + "' is not a standard virtual network."} } } default {$output = "The virtual switch '" + $VirtualSwitch.ElementName + "' is not a standard virtual network."} } write-host $output }
# Navigate Network Topology to determine Virtual Switch type # ie: Internal, External, External-Shared, or Private
# Prompt for the Hyper-V Server to use $HyperVServer = Read-Host "Specify the Hyper-V Server to use (enter '.' for the local computer)" write-host # Get the list of all available network switches $query = "Select * From Msvm_VirtualSwitch" $VirtualSwitches = gwmi -namespace "root\virtualization" -Query $query -computername $HyperVServer # Iterate over each virtual switch foreach ($VirtualSwitch in $VirtualSwitches) { # Initialize variables for counting number of internal and external ports per switch $InternalPortCount = 0 $ExternalPortCount = 0 # Get the Switch ports on the virtual switch $query = "Associators of {$VirtualSwitch} where ResultClass=CIM_SwitchPort" $switchPorts = gwmi -namespace "root\virtualization" -Query $query -computername $HyperVServer # A VM only switch with no VMs connected will return null if ($switchPorts -ne $null) { # Iterate over each switch port foreach ($switchPort in @($switchPorts)) { # Get the Msvm_SwitchLANEndpoint associated with the switch port $query = "Associators of {$switchPort} where ResultClass=Msvm_SwitchLANEndpoint" $SwitchLANEndpoint = gwmi -namespace "root\virtualization" -Query $query -computername $HyperVServer # If there is no active connection on the switch port the results will be null if ($SwitchLANEndpoint -ne $null) { # Get the CIM_EthernetPort for the Msvm_SwitchLANEndpoint $query = "Associators of {$SwitchLANEndpoint} where ResultClass=CIM_EthernetPort" $EthernetPort = gwmi -namespace "root\virtualization" -Query $query -computername $HyperVServer # Check to see if the associated Ethernet port is an internal port if ($EthernetPort.__CLASS -eq "Msvm_InternalEthernetPort") { $InternalPortCount = $InternalPortCount + 1 } # Check to see if the associated Ethernet port is an external port if ($EthernetPort.__CLASS -eq "Msvm_ExternalEthernetPort") { $ExternalPortCount = $ExternalPortCount + 1 } } } } switch ($InternalPortCount) { 0 { switch ($ExternalPortCount) { 0 {$output = "The virtual switch '" + $VirtualSwitch.ElementName + "' is a virtual machine only virtual network."} 1 {$output = "The virtual switch '" + $VirtualSwitch.ElementName + "' is an external-only virtual network."} default {$output = "The virtual switch '" + $VirtualSwitch.ElementName + "' is not a standard virtual network."} } } 1 { switch ($ExternalPortCount) { 0 {$output = "The virtual switch '" + $VirtualSwitch.ElementName + "' is an internal virtual network."} 1 {$output = "The virtual switch '" + $VirtualSwitch.ElementName + "' is an external virtual network."} default {$output = "The virtual switch '" + $VirtualSwitch.ElementName + "' is not a standard virtual network."} } } default {$output = "The virtual switch '" + $VirtualSwitch.ElementName + "' is not a standard virtual network."} } write-host $output }
Some friends here on the Hyper-V team shared a PowerShell 2.0 script for modifying hte VLAN settings on your VMs:
# Modify VLAN setting for VM param( $vmName = $(throw "Must supply a virtual machine name"), $vlanId = $(throw "Must supply vlan id"), $computer = "." ) $ns = "root\virtualization" # get the computer system $vm = gwmi -namespace $ns -computerName $computer Msvm_ComputerSystem -filter "ElementName = '$vmName'" if ($vm -eq $null) { "No virtual machine with name '$vmName'" return } # get its related vssd $vssd = gwmi -namespace $ns -computerName $computer -query "associators of {$vm} where AssocClass=Msvm_SettingsDefineState" # get its synthetic and enumlated NICs $nics = gwmi -namespace $ns -computerName $computer -query "associators of {$vssd} where AssocClass=Msvm_VirtualSystemSettingDataComponent" | where {$_.ResourceType -eq 10 -and ($_.ResourceSubType -eq 'Microsoft Synthetic Ethernet Port' -or $_.ResourceSubType -eq 'Microsoft Emulated Ethernet Port')} if ($nics -eq $null) { # vm does not have any NICs. "Virtual machine '$vmName' does not have any NICs" return } # Find the first nic which has a connection $nic = $nics | where {$_.Connection -ne $null} | select-object -first 1 if ($nic -eq $null) { "None of the NICs on virtual machine '$vmName' are connected" return } # get the connected switch port. $connectedPort = [wmi]$nic.Connection[0] # need to set the external trunk list of the external port on this same switch # to include this vlan id, else traffic won't get through. # first get its switch. $switch = gwmi -namespace $ns -computerName $computer -query "associators of {$connectedPort} where AssocClass=Msvm_HostedAccessPoint" # enumerate all of its ports. First the port which is externally connected. $ports = gwmi -namespace $ns -computerName $computer -query "associators of {$switch} where ResultClass=Msvm_SwitchPort" $externalPort = $null foreach ($p in $ports) { $switchLanEndpoint = gwmi -namespace $ns -computerName $computer -query "associators of {$p} where ResultClass=Msvm_SwitchLanEndpoint" if ($switchLanEndpoint -ne $null) { $externalEthernetPort = gwmi -namespace $ns -computerName $computer -query "associators of {$switchLanEndpoint} where resultclass=Msvm_ExternalEthernetPort" if ($externalEthernetPort -ne $null) { # we got it, we found the switch port connected to the external # port, save it and break out of the loop. $externalPort = $p break } } } if ($externalPort -ne $null) { # get the port's VlanEndpoint $vlan = gwmi -namespace $ns -computerName $computer -query "associators of {$externalPort} where AssocClass=Msvm_BindsTo" # get the vlan's setting object $vlanSetting = gwmi -namespace $ns -computerName $computer -query "associators of {$vlan} where AssocClass=Msvm_NetworkElementSettingData" # get the current trunk list and add the new vlan id into it. # one thing additionally we could do here, which the Hyper-V UI does is clean up # the old AccessVlan id of the port from the trunk list. But, we can't just remove the # old AccessVlan from the trunklist, because another port might be using the same vlan id. # We would have to enumerate all of the ports on the switch and build a new trunk list. # For the purposes of this script, don't worry about cleaning up old vlan id' from the trunk list. $trunkList = $vlanSetting.TrunkedVLANList if ($trunkList -notcontains $vlanid) { $trunkList = $trunkList + $vlanId $vlanSetting.TrunkedVLANList = $trunkList $result = $vlanSetting.Put() } # set the vlan mode into trunking mode. if ($vlan.DesiredEndpointMode -ne 5) { $vlan.DesiredEndpointMode = 5 $result = $vlan.Put() } } # Now that we have finished with the trunklist, set the vlan id of the original connected port. $vlan = gwmi -namespace $ns -computerName $computer -query "associators of {$connectedPort} where AssocClass=Msvm_BindsTo" $vlanSetting = gwmi -namespace $ns -computerName $computer -query "associators of {$vlan} where AssocClass=Msvm_NetworkElementSettingData" $vlanSetting.AccessVlan = $vlanId $vlanSetting.Put()
# Modify VLAN setting for VM
param( $vmName = $(throw "Must supply a virtual machine name"), $vlanId = $(throw "Must supply vlan id"), $computer = "." )
$ns = "root\virtualization"
# get the computer system $vm = gwmi -namespace $ns -computerName $computer Msvm_ComputerSystem -filter "ElementName = '$vmName'"
if ($vm -eq $null) { "No virtual machine with name '$vmName'" return }
# get its related vssd $vssd = gwmi -namespace $ns -computerName $computer -query "associators of {$vm} where AssocClass=Msvm_SettingsDefineState"
# get its synthetic and enumlated NICs $nics = gwmi -namespace $ns -computerName $computer -query "associators of {$vssd} where AssocClass=Msvm_VirtualSystemSettingDataComponent" | where {$_.ResourceType -eq 10 -and ($_.ResourceSubType -eq 'Microsoft Synthetic Ethernet Port' -or $_.ResourceSubType -eq 'Microsoft Emulated Ethernet Port')}
if ($nics -eq $null) { # vm does not have any NICs. "Virtual machine '$vmName' does not have any NICs" return }
# Find the first nic which has a connection $nic = $nics | where {$_.Connection -ne $null} | select-object -first 1
if ($nic -eq $null) { "None of the NICs on virtual machine '$vmName' are connected" return }
# get the connected switch port. $connectedPort = [wmi]$nic.Connection[0]
# need to set the external trunk list of the external port on this same switch # to include this vlan id, else traffic won't get through.
# first get its switch. $switch = gwmi -namespace $ns -computerName $computer -query "associators of {$connectedPort} where AssocClass=Msvm_HostedAccessPoint"
# enumerate all of its ports. First the port which is externally connected. $ports = gwmi -namespace $ns -computerName $computer -query "associators of {$switch} where ResultClass=Msvm_SwitchPort" $externalPort = $null
foreach ($p in $ports) { $switchLanEndpoint = gwmi -namespace $ns -computerName $computer -query "associators of {$p} where ResultClass=Msvm_SwitchLanEndpoint" if ($switchLanEndpoint -ne $null) { $externalEthernetPort = gwmi -namespace $ns -computerName $computer -query "associators of {$switchLanEndpoint} where resultclass=Msvm_ExternalEthernetPort" if ($externalEthernetPort -ne $null) { # we got it, we found the switch port connected to the external # port, save it and break out of the loop. $externalPort = $p break } } }
if ($externalPort -ne $null) { # get the port's VlanEndpoint $vlan = gwmi -namespace $ns -computerName $computer -query "associators of {$externalPort} where AssocClass=Msvm_BindsTo" # get the vlan's setting object $vlanSetting = gwmi -namespace $ns -computerName $computer -query "associators of {$vlan} where AssocClass=Msvm_NetworkElementSettingData"
# get the current trunk list and add the new vlan id into it. # one thing additionally we could do here, which the Hyper-V UI does is clean up # the old AccessVlan id of the port from the trunk list. But, we can't just remove the # old AccessVlan from the trunklist, because another port might be using the same vlan id. # We would have to enumerate all of the ports on the switch and build a new trunk list. # For the purposes of this script, don't worry about cleaning up old vlan id' from the trunk list. $trunkList = $vlanSetting.TrunkedVLANList if ($trunkList -notcontains $vlanid) { $trunkList = $trunkList + $vlanId $vlanSetting.TrunkedVLANList = $trunkList $result = $vlanSetting.Put() } # set the vlan mode into trunking mode. if ($vlan.DesiredEndpointMode -ne 5) { $vlan.DesiredEndpointMode = 5 $result = $vlan.Put() } }
# Now that we have finished with the trunklist, set the vlan id of the original connected port.
$vlan = gwmi -namespace $ns -computerName $computer -query "associators of {$connectedPort} where AssocClass=Msvm_BindsTo" $vlanSetting = gwmi -namespace $ns -computerName $computer -query "associators of {$vlan} where AssocClass=Msvm_NetworkElementSettingData" $vlanSetting.AccessVlan = $vlanId $vlanSetting.Put()
Some friends here on the Hyper-V team shared a PowerShell 2.0 script for merging VHDs:
# Merge VHDs param( [string]$mergePath = $(throw "Must specify full path for merging VHD"), [string]$parentPath = $(throw "Must specify full path of parent VHD") ) #obtain the Msvm_ImageManagementService class $ImageMgtService = get-wmiobject -class "Msvm_ImageManagementService" -namespace "root\virtualization" # Create the fixed VHD $result = $ImageMgtService.MergeVirtualHardDisk($mergePath,$parentPath) if($result.ReturnValue -eq 4096){ # A Job was started, and can be tracked using its Msvm_Job instance $job = [wmi]$result.Job # Wait for job to finish while($job.jobstate -lt 7){$job.get()} # Return the Job's error code return $job.ErrorCode } # Otherwise, the method completed return $result.ReturnValue
# Merge VHDs
param( [string]$mergePath = $(throw "Must specify full path for merging VHD"), [string]$parentPath = $(throw "Must specify full path of parent VHD") )
#obtain the Msvm_ImageManagementService class $ImageMgtService = get-wmiobject -class "Msvm_ImageManagementService" -namespace "root\virtualization"
# Create the fixed VHD $result = $ImageMgtService.MergeVirtualHardDisk($mergePath,$parentPath)
Some friends here on the Hyper-V team shared a PowerShell 2.0 script for loopback mounting a VHD, for example, if you need to use bcdedit to alter the boot configuration store offline:
# Loopback mount a VHD param( [string] $path = $(throw "Must supply a path"), [string] $computer = "." ) $ns = "root\virtualization" # get the Msvm_ImageManagementService $imageService = gwmi -Namespace $ns -ComputerName $computer Msvm_ImageManagementService # mount the disk $result = $imageService.Mount($path) $ret = $result.ReturnValue # handle the return parameter if ($ret -eq 0) { # success. This should never actually be the return value on # a successful mount. Instead it will return a job, which is # associated with the mounted storage image. # For completness, get the new mounted storage image. $filter = "Name='$path'" $filter = $filter.replace("\", "\\") gwmi -Namespace $ns -ComputerName $computer Msvm_MountedStorageImage -filter $filter } elseif ($ret -eq 4096) { $job = [wmi]$result.Job while ($job.jobstate -lt 7) {$job.Get()} if ($job.JobState -eq 7) { # job succeeded. Get the associated Msvm_MountedStorageImage gwmi -Namespace $ns -ComputerName $computer -query "associators of {$job}" } else { # job failed. Return its error code and description. $job.ErrorCode $job.ErrorDescription } } else { # method failed. Return the failure code. $ret }
# Loopback mount a VHD
param( [string] $path = $(throw "Must supply a path"), [string] $computer = "." )
# get the Msvm_ImageManagementService $imageService = gwmi -Namespace $ns -ComputerName $computer Msvm_ImageManagementService
# mount the disk $result = $imageService.Mount($path) $ret = $result.ReturnValue
# handle the return parameter if ($ret -eq 0) { # success. This should never actually be the return value on # a successful mount. Instead it will return a job, which is # associated with the mounted storage image. # For completness, get the new mounted storage image. $filter = "Name='$path'" $filter = $filter.replace("\", "\\") gwmi -Namespace $ns -ComputerName $computer Msvm_MountedStorageImage -filter $filter } elseif ($ret -eq 4096) { $job = [wmi]$result.Job while ($job.jobstate -lt 7) {$job.Get()} if ($job.JobState -eq 7) { # job succeeded. Get the associated Msvm_MountedStorageImage gwmi -Namespace $ns -ComputerName $computer -query "associators of {$job}" } else { # job failed. Return its error code and description. $job.ErrorCode $job.ErrorDescription } } else { # method failed. Return the failure code. $ret }
NOTE: If you use this - review the security recommendations at: http://support.microsoft.com/default.aspx/kb/954358
Some friends here on the Hyper-V team shared a PowerShell 2.0 script for getting a list of VMs:
# List VMs $vmList = gwmi -namespace root\virtualization Msvm_ComputerSystem |` where{$_.Name -ne $env:COMPUTERNAME} $vmList | select ElementName,Name,EnabledState,StatusDescriptions | format-list
# List VMs
$vmList = gwmi -namespace root\virtualization Msvm_ComputerSystem |` where{$_.Name -ne $env:COMPUTERNAME}
$vmList | select ElementName,Name,EnabledState,StatusDescriptions | format-list
Some friends here on the Hyper-V team shared a PowerShell 2.0 script for getting a list of snapshots:
# List Virtual System Snapshots #Obtain the VM name $VM_Name= Read-Host("Please specify the name of the VM ") $HostName = "." #obtain the Msvm_ComputerSystem reference $SourceSystem = get-wmiobject -namespace root\virtualization -class Msvm_ComputerSystem -filter " ElementName = '$VM_Name' " #List the existing VM snapshots Write-Host `n " $VM_Name Snapshots :" $i=1 get-wmiobject -namespace root\virtualization -class Msvm_VirtualSystemSettingData -filter "SystemName=`'$($SourceSystem.Name)`' and SettingType = 5”| ForEach-Object{ Write-Host "($i)" $_.ElementName $i++ }
# List Virtual System Snapshots
#Obtain the VM name $VM_Name= Read-Host("Please specify the name of the VM ") $HostName = "."
#obtain the Msvm_ComputerSystem reference $SourceSystem = get-wmiobject -namespace root\virtualization -class Msvm_ComputerSystem -filter " ElementName = '$VM_Name' "
#List the existing VM snapshots Write-Host `n " $VM_Name Snapshots :" $i=1 get-wmiobject -namespace root\virtualization -class Msvm_VirtualSystemSettingData -filter "SystemName=`'$($SourceSystem.Name)`' and SettingType = 5”| ForEach-Object{ Write-Host "($i)" $_.ElementName $i++ }
My teenage daughter never tires of reminding me how often I show my age. The punning title of this blog is no exception.
However, that should not take away from the awesomeness of the Clustering Team Blog post that lists 300+ useful documents, guides, information and utilities.
My favorites of course are on Hyper-V:
I prefer mine with PowerShell:
and a side of tools:
Utility: ClusPrep: Cluster Configuration Validation Wizard (2003)
Utility: Failover Cluster Management Pack for Operations Manager 2007
Utility: File Server Migration Toolkit (FSMT) (2008)
Utility: Microsoft iSCSI Target Software available to the public!
Utility: NLB Management Pack for SCOM 2007 Released
Utility: RSAT - Remote Server Administration Tools (2008)
Utility: RSAT – Remote Server Administration Tools (2008 R2)
Some friends here on the Hyper-V team shared a PowerShell 2.0 script for getting an intrinsic KVPS:
# Get Intrinsic KVPs (Included Guest machine name, IC Version, OS Version, etc) param( [string]$vmName = $(throw "Must specify virtual machine name") ) $vm = gwmi -namespace root\virtualization Msvm_ComputerSystem -filter "ElementName='$vmName'" # Get the associated KVP Exchange component $kvp = gwmi -namespace root\virtualization ` -query "Associators of {$vm} where ResultClass=Msvm_KvpExchangeComponent" # Pull the Guest Intrinsic Exchange Items from XML into a hash $kvpHash = @{} if($kvp.GuestIntrinsicExchangeItems){ ([xml]("<xml>"+$kvp.GuestInstrinsicExchangeItems+"</xml>")).xml.instance | ` foreach{$kvphash.add($_.property[4].value,$_.property[1].value)} } return $kvpHash
# Get Intrinsic KVPs (Included Guest machine name, IC Version, OS Version, etc)
# Pull the Guest Intrinsic Exchange Items from XML into a hash $kvpHash = @{} if($kvp.GuestIntrinsicExchangeItems){ ([xml]("<xml>"+$kvp.GuestInstrinsicExchangeItems+"</xml>")).xml.instance | ` foreach{$kvphash.add($_.property[4].value,$_.property[1].value)} } return $kvpHash
For all 35 sample Hyper-V PS1 scripts in a zipfile, go to: Hyper-V%20PowerShell%20Example%20Scripts.zip-download
Some friends here on the Hyper-V team shared a PowerShell 2.0 script for getting a custom KVPS:
# Get Custom KVPs param( [string]$vmName = $(throw "Must specify virtual machine name") ) $vm = gwmi -namespace root\virtualization Msvm_ComputerSystem -filter "ElementName='$vmName'" # Get the associated KVP Exchange component $kvp = gwmi -namespace root\virtualization ` -query "Associators of {$vm} where ResultClass=Msvm_KvpExchangeComponent" # Pull the Guest Exchange Items from XML into a hash $kvpHash = @{} if($kvp.GuestExchangeItems){ ([xml]("<xml>"+$kvp.GuestExchangeItems+"</xml>")).xml.instance | ` foreach{$kvphash.add($_.property[4].value,$_.property[1].value)} } return $kvpHash
# Get Custom KVPs
# Pull the Guest Exchange Items from XML into a hash $kvpHash = @{} if($kvp.GuestExchangeItems){ ([xml]("<xml>"+$kvp.GuestExchangeItems+"</xml>")).xml.instance | ` foreach{$kvphash.add($_.property[4].value,$_.property[1].value)} } return $kvpHash
# Expand a VHD param( [string]$vhdPath = $(throw "Must specify full path for VHD"), [string]$vhdSize = $(throw "Must specify expansion to add to VHD (in MB)") ) # Size in bytes $MB = [System.UInt64] $vhdSize*1024*1024 #obtain the Msvm_ImageManagementService class $ImageMgtService = get-wmiobject -class "Msvm_ImageManagementService" -namespace "root\virtualization" # Create the Dynamic VHD $result = $ImageMgtService.ExpandVirtualHardDisk($vhdPath,$MB) if($result.ReturnValue -eq 4096){ # A Job was started, and can be tracked using its Msvm_Job instance $job = [wmi]$result.Job # Wait for job to finish while($job.jobstate -lt 7){$job.get()} # Return the Job's error code return $job.ErrorCode } # Otherwise, the method completed return $result.ReturnValue
# Expand a VHD
param( [string]$vhdPath = $(throw "Must specify full path for VHD"), [string]$vhdSize = $(throw "Must specify expansion to add to VHD (in MB)") )
# Size in bytes $MB = [System.UInt64] $vhdSize*1024*1024
# Create the Dynamic VHD $result = $ImageMgtService.ExpandVirtualHardDisk($vhdPath,$MB)
Some friends here on the Hyper-V team shared a PowerShell 2.0 script for deleting a VM:
# Delete a VM param( [string]$VMName = $(throw "Must specify name of virtual machine to delete") ) #Obtain the VM object that we are going to destroy $query = "SELECT * FROM Msvm_ComputerSystem WHERE ElementName='" + $VMName + "'" $VM = gwmi -query $query -namespace "root\virtualization" #obtain the VirtualSystemManagementService class $VSMgtService = get-wmiobject -class "Msvm_VirtualSystemManagementService" -namespace "root\virtualization" #Destroy the virtual computer system. $result = $VSMgtService.DestroyVirtualSystem($VM) if($result.ReturnValue -eq 4096){ # A Job was started, and can be tracked using its Msvm_Job instance $job = [wmi]$result.Job # Wait for job to finish while($job.jobstate -lt 7){$job.get()} # Return the Job's error code return $job.ErrorCode } # Otherwise, the method completed return $result.ReturnValue
# Delete a VM
param( [string]$VMName = $(throw "Must specify name of virtual machine to delete") ) #Obtain the VM object that we are going to destroy $query = "SELECT * FROM Msvm_ComputerSystem WHERE ElementName='" + $VMName + "'" $VM = gwmi -query $query -namespace "root\virtualization" #obtain the VirtualSystemManagementService class $VSMgtService = get-wmiobject -class "Msvm_VirtualSystemManagementService" -namespace "root\virtualization" #Destroy the virtual computer system. $result = $VSMgtService.DestroyVirtualSystem($VM)
The updated TN page Requirements and Limits for Virtual Machines and Hyper-V in Windows Server 2008 R2 is live. Enjoy.
Some friends here on the Hyper-V team shared a PowerShell 2.0 script for deleting a VM snapshot:
However BEFORE you go deleting snapshots, please read the Hyper-V Snapshot FAQ, and have a look at the Ben Armstrong Snapshot FAQ Video.
# Delete Virtual System Snapshot param( [string]$vmName = $(throw "Must specify virtual machine name"), [string]$vmSnapName = $(throw "Must specify snapshot name") ) # Get the virtual machine by name $vm = gwmi -namespace root\virtualization Msvm_ComputerSystem -filter "ElementName='$vmName'" # Get the setting data for the snapshot by name $snapshot = get-wmiobject -namespace root\virtualization Msvm_VirtualSystemSettingData ` -filter "SystemName='$($vm.Name)' and SettingType = 5 and ElementName = '$vmSnapName'” if($snapshot -eq $null -or $snapshot -is [array]){ throw "Unable to find single snapshot with name `"$vmSnapName`"" } # Get the management service and apply the snapshot $vmms = gwmi -namespace root\virtualization Msvm_VirtualSystemManagementService $result = $vmms.RemoveVirtualSystemSnapshot($snapshot) if($result.ReturnValue -eq 4096){ # A Job was started, and can be tracked using its Msvm_Job instance $job = [wmi]$result.Job # Wait for job to finish while($job.jobstate -lt 7){$job.get()} # Return the Job's error code return $job.ErrorCode } # Otherwise, the method completed return $result.ReturnValue
# Delete Virtual System Snapshot
param( [string]$vmName = $(throw "Must specify virtual machine name"), [string]$vmSnapName = $(throw "Must specify snapshot name") )
# Get the setting data for the snapshot by name $snapshot = get-wmiobject -namespace root\virtualization Msvm_VirtualSystemSettingData ` -filter "SystemName='$($vm.Name)' and SettingType = 5 and ElementName = '$vmSnapName'” if($snapshot -eq $null -or $snapshot -is [array]){ throw "Unable to find single snapshot with name `"$vmSnapName`"" } # Get the management service and apply the snapshot $vmms = gwmi -namespace root\virtualization Msvm_VirtualSystemManagementService
$result = $vmms.RemoveVirtualSystemSnapshot($snapshot)
Some customers are having trouble with snapshots in Hyper-V. I recently had the opportunity to discuss these issues and best practices to avoid them with Ben Armstrong, a.k.a. Virtual PC Guy
Click the image to view the 12 minute video on Showcase (not to be confused with my old team – IT Showcase…but I digress).
Read Ben’s blog at http://blogs.msdn.com/Virtual_PC_Guy/
See also the Hyper-V Snapshot FAQ at http://technet.microsoft.com/en-us/library/dd560637.aspx
Some friends here on the Hyper-V team shared a PowerShell 2.0 script for creating a virtual switch:
# Create a Virtual Switch param( [string]$vsName = $(throw "Must specify virtual switch name") ) # Get the Virtual Switch Management Service $vsms = gwmi -namespace root\virtualization Msvm_VirtualSwitchManagementService # Use CreateSwitch method to specify the name, friendly name, learnable addresses, # and authorization scope of the created switch (use "" for the root scope) $result = $vsms.CreateSwitch($vsName,$vsName,2048,"") if($result.ReturnValue -ne 0){ throw "Error: $($result.ReturnValue)" } return ([wmi]$result.CreatedVirtualSwitch)
# Create a Virtual Switch
param( [string]$vsName = $(throw "Must specify virtual switch name") )
# Get the Virtual Switch Management Service $vsms = gwmi -namespace root\virtualization Msvm_VirtualSwitchManagementService
# Use CreateSwitch method to specify the name, friendly name, learnable addresses, # and authorization scope of the created switch (use "" for the root scope) $result = $vsms.CreateSwitch($vsName,$vsName,2048,"") if($result.ReturnValue -ne 0){ throw "Error: $($result.ReturnValue)" } return ([wmi]$result.CreatedVirtualSwitch)