Quantcast
Channel: Taylor Brown's Blog
Viewing all 29 articles
Browse latest View live

Hyper-V WMI Using PowerShell Scripts – Part 1 (Worker Process ID to Virtual Machine Mapping)

$
0
0

Hello out there in blog land… This is Taylor Brown some of you may know me from the Virtualization Deployment Summit or from my posts on the TechNet Forums, for those who don’t know me I am a test lead on the Hyper-V team.  One of my team’s responsibilities is validating end-to-end integration of all the different parts of Hyper-V such as networking, storage, user-interface or installation.  We are also responsible for the relationship between you the customer and the rest of the Hyper-V test team. 

Last week I did a demo of some Hyper-V WMI scripts in Powershell and enough people asked for them I figured I'll just post them for everyone…  So without further delay here's part 1.

PowerShell 2.0 CTP – Graphical PowerShell Interface

I highly recommend the PowerShell Graphical Interface that is included in the PowerShell 2.0 CTP. 

You can read more about it and download the installation package at http://www.microsoft.com/technet/scriptcenter/topics/msh/download2.mspx.

It offers a nice tabbed interface and color coding, its a CTP build so it’s far from bug-free but the benefits out way the pitfalls.  You have to uninstall the PowerShell 1.0 Windows update before you can install the CTP build.  I don't think I would install the CTP on your production servers, but the PowerShell scripts are generally compatible.

The biggest downside to this interface for me is that it makes me want more features like auto-complete.

PowerShell20CTP

 

Mapping Worker Process ID's to Virtual Machines

Each virtual machine has it's own worker process (vmwp.exe) instance when it's running.  Some people have asked how they can map worker process to a specific virtual machine so here's the answer... This is also a great example of the power that WMI and PowerShell have with Hyper-V. 

   1: $Vm = Get-WmiObject -Namespace root\virtualization -ComputerName "." `
   2: -Query "Select * From Msvm_ComputerSystem Where ElementName='Server 2008 - Test1'"
   3: $Vm.ProcessID
   4:  
   5: $Vm = Get-WmiObject -Namespace root\virtualization -ComputerName "." `
   6:    -Query "Select * From Msvm_ComputerSystem Where ProcessID=4044"
   7: $Vm.ElementName

Lines 1 and 2 retrieves a WMI object for the virtual machine with the friendly name of 'Server 2008 - Test1'.  Then line 4 outputs the value in the ProcessID field to the console.

Lines 5 and 6 retrieves the same WMI object as lines 1 and 2 did but retrieves it via the process id.  Then line 7 outputs the value in the ElementName (friendly name) of the virtual machine to the console.

Other WMI Properties Of the Msvm_ComputerSystem

msvm_computersystem

One of the best parts about writing scripts in PowerShell over VBScript or JScript is that like a command or batch script you can run commands in the shell window and see the results right away...

In this screen capture I just ran the command from line 1 and 2 above (hint remove the ` and carriage return from the end of line 1 to make the command a single line).

Then I ran $Vm, which is the WMI object I retrieved.  This will output all of the properties that object contains.  Here's the list - stay tuned for later posts and I will talk about what these properties mean.

PS C:\> $Vm = Get-WmiObject -Namespace root\virtualization -ComputerName "." -Query "Select * From Msvm_ComputerSystem Where ElementName='Server 2008 - Test1'"
PS C:\> $Vm

__GENUS                       : 2
__CLASS                       : Msvm_ComputerSystem
__SUPERCLASS                  : CIM_ComputerSystem
__DYNASTY                     : CIM_ManagedElement
__RELPATH                     : Msvm_ComputerSystem.CreationClassName="Msvm_ComputerSystem",Name="A1223A4B-887D-4F01-895E-FBFB636F76D8"
__PROPERTY_COUNT              : 29
__DERIVATION                  : {CIM_ComputerSystem, CIM_System, CIM_EnabledLogicalElement, CIM_LogicalElement...}
__SERVER                      : TAYLORB-DP490
__NAMESPACE                   : root\virtualization
__PATH                        :
\\localhost\root\virtualization:Msvm_ComputerSystem.CreationClassName="Msvm_ComputerSystem",Name="A1223A4B-887D-4F01-895E-FBFB636F76D8"

AssignedNumaNodeList          : {0}
Caption                       : Virtual Machine
CreationClassName             : Msvm_ComputerSystem
Dedicated                     :
Description                   : Microsoft Virtual Machine
ElementName                   : Server 2008 - Test1
EnabledDefault                : 2
EnabledState                  : 2
HealthState                   : 5
IdentifyingDescriptions       :
InstallDate                   : 20080502051703.000000-000
Name                          : A1223A4B-887D-4F01-895E-FBFB636F76D8
NameFormat                    :
OnTimeInMilliseconds          : 3783756
OperationalStatus             : {2}
OtherDedicatedDescriptions    :
OtherEnabledState             :
OtherIdentifyingInfo          :
PowerManagementCapabilities   :
PrimaryOwnerContact           :
PrimaryOwnerName              :
ProcessID                     : 4044
RequestedState                : 12
ResetCapability               : 1
Roles                         :
Status                        :
StatusDescriptions            :
TimeOfLastConfigurationChange : 20080502051707.000000-000
TimeOfLastStateChange         : 20080502051707.000000-000

 


Hyper-V WMI Using PowerShell Scripts – Part 2 (VHD Creation)

$
0
0

In part 1 we went over some basic scripts and tools for gathering information about running virtual machines.  In part 2 I am going to cover two things, first basic VHD creation and second determining if Hyper-V WMI methods are succeeding or failing and what the error message is.

PowerShellPlus

Last time I showed the PowerShell 2.0CTP which includes the Graphical PowerShell interface… Those of you that plan to do a lot PowerShell development might want to check out PowerShellPlus (http://www.powershell.com/index.html).  It’s a $79 investment if you are using it for commercial use, but there is a 30 day trial – 1 day down and so far I think it’s worth $79…  As you can see from the screen capture below the editor offers auto-complete as well as a pretty good debugger.

PowerShellPlus

Creating a VHD Using PowerShell WMI

Creating a VHD using the Hyper-V WMI is pretty easy… And once again PowerShell makes it even easier… 

The first command retrieves a WMI object for Msvm_ImageManagmentService

The second command executes the CreateDynamicVirtualHardDisk method to create a new dynamic VHD.  PowerShell is smart enough to know that 20GB = 20 * 1073741824... That’s so COOL!.

PS D:\> $VHDService = get-wmiobject -class "Msvm_ImageManagementService" -namespace "root\virtualization"
PS D:\> $VHDService.CreateDynamicVirtualHardDisk("D:\vhds\TestVhd1.vhd", 20GB)

__GENUS          : 2
__CLASS          : __PARAMETERS
__SUPERCLASS     :
__DYNASTY        : __PARAMETERS
__RELPATH        :
__PROPERTY_COUNT : 2
__DERIVATION     : {}
__SERVER         :
__NAMESPACE      :
__PATH           :
Job              : \\TAYLORB-DP490\root\virtualization:Msvm_StorageJob.InstanceID='Microsoft:Msvm_{B5A1A0EC-6A86-4CB0-AF7A-B336CBA2DCFF}'
ReturnValue      : 4096

Finding Out If Your VHD Creation Succeeded Or Not…

Let’s say you actually want to know if the VHD was created successfully or not (crazy I know…).  Well normally you would just check ReturnValue, but what the heck does 4096 mean?  4096 means that the method is executing asynchronously (in the background) and you need to check it’s Job object to see when it’s finished and if it was successful…

As you can see from the ErrorDescription below my job actually failed since I didn’t delete the VHD between the first and second sample…  Most of the Hyper-V WMI uses these Job objects so this is a pretty handy bit of code to know…

Again the first command just retrieves a WMI object for Msvm_ImageManagmentService.

The second command is mostly the same except for three key parts, first you can see it stores the return object in $Job but the real magic is the [WMI] before the $VHDSer…  What’s happening is your telling PowerShell to make you a PowerShell WMI object for the Job path stored in the Job field. Look at the output from the sample above the Job field is a path to a WMI job object...

The third command is just showing the output of the $Job… You could do $Job.ErrorDesciption if you wanted to just get the ErrorDescription..

PS D:\> $VHDService = get-wmiobject -class "Msvm_ImageManagementService" -namespace "root\virtualization"
PS D:\> $Job = [WMI]$VHDService.CreateDynamicVirtualHardDisk("D:\Users\Public\Documents\Hyper-V\Virtual hard disks\TestVhd1.vhd", 20GB).Job
PS D:\> $Job

__GENUS                 : 2
__CLASS                 : Msvm_StorageJob
__SUPERCLASS            : CIM_ConcreteJob
__DYNASTY               : CIM_ManagedElement
__RELPATH               : Msvm_StorageJob.InstanceID="Microsoft:Msvm_{22FE6994-4CD8-4D06-9F3D-906A23A4BB09}"
__PROPERTY_COUNT        : 43
__DERIVATION            : {CIM_ConcreteJob, CIM_Job, CIM_LogicalElement, CIM_ManagedSystemElement...}
__SERVER                : TAYLORB-DP490
__NAMESPACE             : root\virtualization
__PATH                  : \\TAYLORB-DP490\root\virtualization:Msvm_StorageJob.InstanceID="Microsoft:Msvm_{22FE6994-4CD8-4D06-9F3D-906A23A4B
                          B09}"
Caption                 : Storage Job
Child                   :
DeleteOnCompletion      : True
Description             : Disk Creation Job.
ElapsedTime             : 00000000000000.000000:000
ElementName             : Storage Job
ErrorCode               : 32768
ErrorDescription        : The system failed to create 'D:\Users\Public\Documents\Hyper-V\Virtual hard disks\TestVhd1.vhd' with error 'The f
                          ile exists..' (0x80070050)
ErrorSummaryDescription :
HealthState             : 5
InstallDate             : 00000000000000.000000+000
InstanceID              : Microsoft:Msvm_{22FE6994-4CD8-4D06-9F3D-906A23A4BB09}
JobCompletionStatusCode : 2147942480
JobRunTimes             : 1
JobState                : 10
JobStatus               : Error
LocalOrUtcTime          : 2
Lun                     : 0
Name                    : Msvm_StorageJob
Notify                  :
OperationalStatus       : {2}
OtherRecoveryAction     :
Owner                   :
Parent                  :
PathId                  : 0
PercentComplete         : 0
PortNumber              : 0
Priority                : 0
RecoveryAction          : 3
RunDay                  :
RunDayOfWeek            :
RunMonth                :
RunStartInterval        :
ScheduledStartTime      :
StartTime               :
Status                  : Error
StatusDescriptions      : {Error}
TargetId                : 0
TimeBeforeRemoval       : 00000000000000.000000:000
TimeOfLastStateChange   : 00000000000000.000000+000
TimeSubmitted           :
Type                    : 1
UntilTime               :

 

Well I think that's going to have to do it for tonight… Stay tuned I have A LOT more to show. 

If you prefer the examples in this format tell me, if you prefer the format from yesterday tell me, if you want a different format altogether tell me…

-Good Night and Good Weekend
-Taylor Brown

Hyper-V WMI Using PowerShell Scripts – Part 3 (KVP's - Guest OS Version)

$
0
0

Update 12/5/12

A lot has changed since 2008 and many things have stayed the same…  I wanted to provide an update to some of the most commonly viewed posts and this was one of them.

For updated information on this topic please refer to my latest post Retrieving the IP Address Of A VM In Hyper-V.

 

Original Post

In part 1 we went over basic scripts and tools for gathering some generic information about virtual machines and in part 2 we went over VHD creation and WMI job’s.  In part 3 I am going to cover getting more detailed information about a guest operating system by using the KVP Exchange integration component.  KVP stands for Key Value Pair this is a service that runs in the guest operating system and allows some limited information to be passed from the guest to the host or parent and vice-verse.  For now we are going to focus only on the intrinsic KVP’s these are provided by default on virtual machines that have the integration components installed.  The intrinsic KVP’s include: FullyQualifiedDomainName, OsName, OsVersion, CSDVersion, OsMajorVersion, OsMinorVersion, OsBuildNumber, OsPlatformID, ServicePackMajor, SuiteMask, ProductType, ProcessorArhitecture.

I’ll start with the PowerShell script and results and then explain how to decipher each of the KVP’s values but first I want to thank Ed one of our top notch developers that provided me this script...

In the gray box is the body of the script, it’s a bit different then what we have seen in the past primarily because is what looks like a function at the top.  This function looking thing is a PowerShell filter, what the filter does is take a bunch of XML known in WMI as an “embedded instance" and converts it into objects.  If you want to see the XML in it’s raw form remove the "|Import-CimXml” from the last line of the script and you’ll see how handy this little filter is.

So what’s happening in this script?  I will ignore the filter for a moment so the first line is the the $Vm = Get-Wmi… So the first line should look pretty common now, we are getting a Msvm_ComputerSystem WMI object for a given virtual machine “Server 2008 – Test1".  The second line is new, we are running an Association query to get a Msvm_KvpExchangeCompoents WMI object for this VM, associations are an optimization in WMI you can think of them like a SQL join statement “Please give me all of the X that corresponds to Y”.  The third line is just taking the GuestIntrinsicExchangeItems property of the Msvm_KvpExchangeCompoents and piping or sending it (that’s the | character) to the Import-CimXml filter that’s written above.  Now for the filter, so all this filter is doing is using an XML xpath query to go over each “Instance/Property” node and adding it’s name and value to this CimObj object and then returning that object…

WMIKVP.ps1 PowerShell Script

filter Import-CimXml
{
    $CimXml = [Xml]$_
    $CimObj = New-Object -TypeName System.Object
    foreach ($CimProperty in $CimXml.SelectNodes("/INSTANCE/PROPERTY"))
    {
        $CimObj | Add-Member -MemberType NoteProperty -Name $CimProperty.NAME -Value $CimProperty.VALUE
    }
    $CimObj
}

$Vm = Get-WmiObject -Namespace root\virtualization -Query "Select * From Msvm_ComputerSystem Where ElementName='Server 2008 - Test1'"
$Kvp = Get-WmiObject -Namespace root\virtualization -Query "Associators of {$Vm} Where AssocClass=Msvm_SystemDevice ResultClass=Msvm_KvpExchangeComponent"


$Kvp.GuestIntrinsicExchangeItems | Import-CimXml

 

Output of the WMIKVP.ps1 Script

PS C:\> . 'D:\BlogsDemo\powerShell\Demo\WMIKVP.ps1'

Caption     :
Data        : AUTOBVT-M02LJSS
Description :
ElementName :
Name        : FullyQualifiedDomainName
Source      : 2

Caption     :
Data        : Windows Server (R) 2008 Enterprise
Description :
ElementName :
Name        : OSName
Source      : 2

Caption     :
Data        : 6.0.6001
Description :
ElementName :
Name        : OSVersion
Source      : 2

Caption     :
Data        : Service Pack 1
Description :
ElementName :
Name        : CSDVersion
Source      : 2

Caption     :
Data        : 6
Description :
ElementName :
Name        : OSMajorVersion
Source      : 2

Caption     :
Data        : 0
Description :
ElementName :
Name        : OSMinorVersion
Source      : 2

Caption     :
Data        : 6001
Description :
ElementName :
Name        : OSBuildNumber
Source      : 2

Caption     :
Data        : 2
Description :
ElementName :
Name        : OSPlatformId
Source      : 2

Caption     :
Data        : 1
Description :
ElementName :
Name        : ServicePackMajor
Source      : 2

Caption     :
Data        : 0
Description :
ElementName :
Name        : ServicePackMinor
Source      : 2

Caption     :
Data        : 274
Description :
ElementName :
Name        : SuiteMask
Source      : 2

Caption     :
Data        : 3
Description :
ElementName :
Name        : ProductType
Source      : 2

Caption     :
Data        : 9
Description :
ElementName :
Name        : ProcessorArchitecture
Source      : 2

Ok now how do you decipher all of these values like SuiteMask?   All of this data except the fully qualified domain name come from a Windows API GetVersionEx but what you really want to look at is the OSVERSIONINFOEX structure.  That documents each of these values, for example SuiteMask has a value of 274 above that's 0x112 and according to the documents that means this guest has: Remote Desktop support, Terminal Services is installed, and it's running an Enterprise SKU of Windows... 

There's a lot more you can do with the KVP's such as pushing custom data into the guest from the parent partition/host or providing data from the guest so that the parent partition/host can query it.  I can provide samples for this in a future post but only if you want me to - so tell me, actually tell me what posts you want maybe networking or offline vhd servicing or maybe import/export?

--Taylor Brown
--Hyper-V test team

Hyper-V WMI Using PowerShell - Part 4 and Negative 1 (Shutdown IC Powershell/C#)

$
0
0

I hope everyone is enjoying Hyper-V RC1 (yep I just linked to my own post -shamless maybe) but, as promissed here's some more WMI goodness.   

Title got your attention?  Well this is a two part post…  First I will show how to use the Shutdown IC to initiate a shutdown of a guest using PowerShell (that's part 4)  Ok so why Negative 1?  Well what did we do before PowerShell (yeah yeah vbscript but go with me) one option was C# so Part Negative 1 is a C# Example…

Here’s the PowerShell to shutdown a VM named “Vista”… Just like previous examples, we get the Msvm_ComputerSystem… then we use the Associators of query to get the Msvm_ShutdownComponent associated with that VM.  Then we just call InitiateShutdown, the first parameter is wether to force a shutdown (like running shutdown /f inside the virtual machine) and the second is the reason for the shutdown.  It really is that simple.

$Vm = Get-WmiObject -Namespace root\virtualization  -Query "Select * From Msvm_ComputerSystem Where ElementName='Vista'"


$ShutdownIC = Get-WmiObject -Namespace root\virtualization  -Query "Associators of {$Vm} Where AssocClass=Msvm_SystemDevice ResultClass=Msvm_ShutdownComponent"


$ShutdownIC.InitiateShutdown("TRUE", "Need to shutdown")

And here’s the same code in C#…

using System;using System.Collections;using System.Text;using System.Management;namespace ShutdownViaIC
{class Program
    {staticvoid Main(string[] args)
        {//Connect to the Remote Machines Management Scope
            ConnectionOptions options =  new ConnectionOptions();
            ManagementScope scope = new ManagementScope(@"\\localhost\root\virtualization"); scope.Connect();//Get the msvm_computersystem for the given VM (Vista)         
            ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope,new ObjectQuery("SELECT * FROM Msvm_ComputerSystem WHERE ElementName = 'Vista'"));//Select the first object in the Searcher collection
            IEnumerator enumr = searcher.Get().GetEnumerator();
            enumr.MoveNext();
            ManagementObject msvm_computersystem = (ManagementObject)(enumr.Current);//Use the association to get the msvm_shutdowncomponent for the msvm_computersystem
            ManagementObjectCollection collection = msvm_computersystem.GetRelated("Msvm_ShutdownComponent");
            ManagementObjectCollection.ManagementObjectEnumerator enumerator = collection.GetEnumerator();
            enumerator.MoveNext();
            ManagementObject msvm_shutdowncomponent = (ManagementObject)enumerator.Current;//Get the InitiateShudown Parameters
            ManagementBaseObject inParams = msvm_shutdowncomponent.GetMethodParameters("InitiateShutdown");
            inParams["Force"] = true;
            inParams["Reason"] = "Need to Shutdown";//Invoke the Method
            ManagementBaseObject outParams = msvm_shutdowncomponent.InvokeMethod("InitiateShutdown", inParams, null);uint returnValue = (uint)outParams["ReturnValue"];//Zero indicates successif (returnValue != 0)
                Console.WriteLine("SHUTDOWN Failed");            
        }
    }
}

PowerShell like most scripting languages can do simple tasks well simply, but your power and control is limited… This is still the case with PowerShell the code to initiate this shutdown is dead simple in PowerShell and all of three lines, you have more ‘using’ lines than that in the C# code…  However when it comes to writing more complex solutions like a Windows service that monitors Hyper-V and implements some custom business logic C# is a great choice… (it’s what the Hyper-V UI is written in).

--Taylor Brown
--Hyper-V test team

Hyper-V WMI Using PowerShell Scripts – Part 5 (Creating Virtual Switchs/Networks)

$
0
0

I hope everyone had a great Memorial Day weekend – we had a four day weekend on the Hyper-V team which was excellent!  In this post I am going to show how to create a new virtual switch attached to an external network.  I’ll start with a complete script and then take it apart and explain what each part is doing.

$VirtualSwitchService = get-wmiobject -class "Msvm_VirtualSwitchManagementService" -namespace "root\virtualization"
$ReturnObject = $VirtualSwitchService.CreateSwitch([guid]::NewGuid().ToString(), "New External Switch", "1024","")

#Create New Virtual Switch
$CreatedSwitch = [WMI]$ReturnObject.CreatedVirtualSwitch

#Create Internal Switch Port
$ReturnObject = $VirtualSwitchService.CreateSwitchPort($CreatedSwitch, [guid]::NewGuid().ToString(), "InternalSwitchPort", "")
$InternalSwitchPort = [WMI]$ReturnObject.CreatedSwitchPort

#Create External Switch Port
$ReturnObject = $VirtualSwitchService.CreateSwitchPort($CreatedSwitch, [guid]::NewGuid().ToString(), "ExternalSwitchPort", "")
$ExternalSwitchPort = [WMI]$ReturnObject.CreatedSwitchPort

$ExternalNic = get-wmiobject -namespace "root\virtualization" -Query "Select * From Msvm_ExternalEthernetPort WHERE IsBound=False"

#Call SetupSwitch
$Job = $VirtualSwitchService.SetupSwitch($ExternalSwitchPort, $InternalSwitchPort, $ExternalNic, [guid]::NewGuid().ToString(), "InternalEthernetPort")
while (([WMI]$Job.Job.JobState -eq 2) -or ([WMI]$Job.Job.JobState -eq 3) -or ([WMI]$Job.Job.JobState -eq 4)) {Start-Sleep -m 100}
[WMI]$Job.Job

Before explaining the elements of the script, I think it’s important to explain a little about Hyper-V’s networking model.  Hyper-V’s networking model attempts to be a similar to a real network, there are virtual switches, virtual switch ports and network adapters.  When you create a new external virtual network you are actually creating a virtual switch, an internal and external switch port and a virtual network adapter on the host.

So let's look at the script above section by section.

Section 1 - Creating The Switch

$VirtualSwitchService = get-wmiobject -class "Msvm_VirtualSwitchManagementService" -namespace "root\virtualization"
$ReturnObject = $VirtualSwitchService.CreateSwitch([guid]::NewGuid().ToString(), "DemoExternal", "1024","")

Create New Virtual Switch
$CreatedSwitch = [WMI]$ReturnObject.CreatedVirtualSwitch

This section get's the Msvm_VirtualSwtichManagmentService, this is similar to other management service classes like msvm_imagemanagmentsevice.  The second line creates the switch, the first parameter to this function is the switch name, typically a guid is a good unique name, the second parameter is the friendly name (what you will see in the UI), the third parameter is the number of learnable addresses in the switch, the last parameter the AzMan scope name (I'll talk more about those in a later post).  The third line retrieves the WMI object for the created switch.

Section 2 - Creating Switch Ports

#Create Internal Switch Port
$ReturnObject = $VirtualSwitchService.CreateSwitchPort($CreatedSwitch, [guid]::NewGuid().ToString(), "InternalSwitchPort", "")
$InternalSwitchPort = [WMI]$ReturnObject.CreatedSwitchPort

#Create External Switch Port
$ReturnObject = $VirtualSwitchService.CreateSwitchPort($CreatedSwitch, [guid]::NewGuid().ToString(), "ExternalSwitchPort", "")
$ExternalSwitchPort = [WMI]$ReturnObject.CreatedSwitchPort

This section creates the internal and external switch ports, think of these as the ports on a physical switch that you would attach to your PC or Modem.  In both cases we are calling the CreateSwitchPort method.  The first parameter is switch we created in the previous section, the second parameter is the switch port name again we using a guid, the third the friendly name this name does not have to be unique and can be anything you want, and the final parameter again is the AzMan scope.  We again retrieve the created switch port's as WMI objects.

Section 3 - Retrieving External Ethernet Connection

$ExternalNic = get-wmiobject -namespace "root\virtualization" -Query "Select * From Msvm_ExternalEthernetPort WHERE IsBound=False"

This section retrieves the external Ethernet port think of this as the port on the modem or the actual network adapter on the physical machine.  This query should return only one adapter, in the query above I select all adapters on the machine that are not already bound to a switch (hence the IsBound=False) so if I had two network adapters that not bound this query would need to be more specific.  You'll need to figure out what your criteria will be try running "get-wmiobject -namespace "root\virtualization" -Query "Select * From Msvm_ExternalEthernetPort" this will return all of the information available to query against.

Section 4 - Bringing It All Together

$Job = $VirtualSwitchService.SetupSwitch($ExternalSwitchPort, $InternalSwitchPort, $ExternalNic, [guid]::NewGuid().ToString(), "InternalEthernetPort")


while (([WMI]$Job.Job.JobState -eq 2) -or ([WMI]$Job.Job.JobState -eq 3) -or ([WMI]$Job.Job.JobState -eq 4)) {Start-Sleep -m 100}
[WMI]$Job.Job

This final section bring's it all together.  The SetupSwitch method takes the WMI objects for the switch, switch ports, external Ethernet port as well as a name and friendly name and binds all the switch port's together.  Up to this point if you looked in the Hyper-V Network Manger you would see your switch but it would be a private switch; after this it will be an external switch.  The last two lines just wait for the returned WMI object to complete and then prints out the object.

That's it!  You now have an external network.

- Taylor Brown
- Hyper-V Test Team

image

Hyper-V WMI – Cloning Virtual Machines Using Import/Export

$
0
0

I have officially given up on the “Hyper-V WMI Using PowerShell Scripts” serious, not because of lack of interest but because or extreme interest implying that I would need to do Part 5, 6, 7, 99…  Counting past 5 is hard so from now on I will just title the posts for what they are doing.  Today’s post is going to be an end-to-end script to create 10 clones of a given VM.

Here’s a quick tour of the script…

This script takes 4 parameters:
     MasterVM – this is the name of the VM that will be cloned
     Path – this is the base path where the clones will reside
     NewName – this is what the cloned VM’s will be named
     HyperVHost – this is the name of the host that the script will execute against

The function ProcessWMIJob takes the return of a WMI method call and then processes the job waiting for the job to complete  and throwing an exception if the job failed.

The main part of the script retrieves the Msvm_VirtualSystemManagmentService class and the MasterVM’s Msvm_ComputerSystem.  It then loops 10 times, first changing the name of the VM and then exporting the VM and finally re-importing the VM.  After it completes the 10 interactions it restores the name of original name of the MasterVM.

 

param
(
    [
string]$MasterVM=$(Throw"MasterVM required"),
    [
string]$Path=$(Throw"Path required"),
    [
string]$NewName="VMCopy",
    [
string]$HyperVHost="localhost"
)


functionProcessWMIJob
{
    param
    (
        [
System.Management.ManagementBaseObject]$Result
    )

    if ($Result.ReturnValue-eq4096)
    {
        $Job= [WMI]$Result.Job

        while ($Job.JobState-eq4)
        {
            Write-Progress-Id2-ParentId1$Job.Caption-Status"Executing"-PercentComplete$Job.PercentComplete
            Start-Sleep1
            $Job.PSBase.Get()
        }
        if ($Job.JobState-ne7)
        {
            Write-Error$Job.ErrorDescription
            Throw$Job.ErrorDescription
        }
    }
    elseif ($Result.ReturnValue-ne0)
    {
        Throw$Result.ReturnValue
    }
    Write-Progress$Job.Caption-Status"Completed"-PercentComplete100-Id2-ParentId1
}

#Main Script Body
$VMManagementService=Get-WmiObject-Namespaceroot\virtualization-ClassMsvm_VirtualSystemManagementService-ComputerName$HyperVHost
$SourceVm=Get-WmiObject-Namespaceroot\virtualization-Query"Select * From Msvm_ComputerSystem Where ElementName='$MasterVM'"-ComputerName$HyperVHost
$a=0


while ($a-lt10) {
    write-progress-Id1"Cloning Vm's"-Status"Executing"-percentcomplete (($a/10)*100)
    $tempVMName="$NewName - $a"
    $VMSettingData=Get-WmiObject-Namespaceroot\virtualization-Query"Associators of {$SourceVm} Where ResultClass=Msvm_VirtualSystemSettingData AssocClass=Msvm_SettingsDefineState"-ComputerName$HyperVHost
    $VMSettingData.ElementName=$tempVMName

    $Result=$VMManagementService.ModifyVirtualSystem($SourceVm,$VMSettingData.PSBase.GetText(1))
    ProcessWMIJob$Result

    $Result=$VMManagementService.ExportVirtualSystem($SourceVm,$TRUE,"$Path")
    ProcessWMIJob$Result

    $Result=$VMManagementService.ImportVirtualSystem("$Path\$tempVMName",$TRUE)
    ProcessWMIJob$Result

    $a++
}


write-progress-Id1-Completed$TRUE-Activity"Cloning Vm's"
$VMSettingData=Get-WmiObject-Namespaceroot\virtualization-Query"Associators of {$SourceVm} Where ResultClass=Msvm_VirtualSystemSettingData AssocClass=Msvm_SettingsDefineState"-ComputerName$HyperVHost
$VMSettingData.ElementName=$MasterVM

$Result=$VMManagementService.ModifyVirtualSystem($SourceVm,$VMSettingData.PSBase.GetText(1))
ProcessWMIJob$Result

- Taylor Brown
- Hyper-V Test Team

image


Hyper-V WMI – Configuring Automatic Startup/Shutdown/Recovery Action’s For Virtual Machines

$
0
0

Hyper-V virtual machines have configuration options that control what happens when the parent/host server shuts down, start’s up, or if a virtual machine’s worker process terminates unexpectedly.  The first two conditions (parent/host shutdown, startup) are pretty self explanatory but what would cause a worker process to terminate?  There are a couple reasons, one would be if someone terminates the process, another would be if the process detects an security attack coming from the virtual machine, others reasons could be if there was bad hardware or a programming error (i.e bug) in either Hyper-V or another component in the system…

The default Automatic Startup Action is to start the virtual machine if it was running when the server was shutdown.  Another option is to always startup the virtual machine irrespective of the state of the virtual machine when the server was shutdown. The last option is none – this translates to leave the virtual machine off or saved when the server starts up.

The default Automatic Shutdown Action is to save any running virtual machines.  There are two other options, first is to turn off any running virtual machines and second is to shutdown any running virtual machines using the shutdown integration component.  The shutdown is forced – so any open/running programs will be terminated.  If the shutdown request fails the vm will be turned off – this can happen for many reasons primarily because the IC’s aren’t installed or if the guest is in safe mode/booting up.

The default Automatic Recovery Action is to restart the virtual machine, the other options are to revert to the last snapshot if one exists or none – which again equates to leaving the virtual machine off.

There is one additional option that I wanted to discuss briefly is Automatic Startup Action Delay, this is the amount of time to wait after the server reboot before taking the automatic startup action.  The default is zero – meaning take the action immediately.  This option could be very helpful for some servers – if you have lower and higher priority virtual machines you might want to delay the startup of your low priority virtual machines.

 

So here’s some code:

$VirtualSystemManagemntService=get-wmiobject-class"Msvm_VirtualSystemManagementService"-namespace"root\virtualization"

foreach ($VminGet-WmiObject-Namespaceroot\virtualization-Query"Select * from Msvm_ComputerSystem Where Description='Microsoft Virtual Machine'")
{
   $SettingData=Get-WmiObject-Namespaceroot\virtualization-Query"Associators of {$Vm} Where ResultClass=Msvm_VirtualSystemGlobalSettingData AssocClass=Msvm_ElementSettingData"
   $SettingData.AutomaticStartupAction=0#None=0, Restart if Previously Running=1, Always Startup=2
   $SettingData.AutomaticShutdownAction=0#Turn Off=0, Save State=1, ShutDown=2
   $SettingData.AutomaticRecoveryAction=0#None=0, Restart=1, Revert to Snapshot=2
   $SettingData.AutomaticStartupActionDelay= [System.Management.ManagementDateTimeconverter]::ToDmtfTimeInterval((New-TimeSpan-Minutes10))

   $VirtualSystemManagemntService.ModifyVirtualSystem($Vm,$SettingData.PSBase.GetText(1))
}

 

ENJOY!

Taylor Brown
Hyper-V Integration Test Lead
http://blogs.msdn.com/taylorb

clip_image001

Hyper-V WMI: Creating/Applying/Deleting Virtual Machine Snapshots

$
0
0
After I finished writting this I relized it got a bit long... - I guess I had a lot to talk about!  Hope you enjoy it (or at least find it mildly useful)

imageHyper-V implements a feature known as snapshots, this should not be confused with a SAN snapshot or a VSS snapshot these snapshots are quite different.  A Hyper-V snapshot allows you to save off the current state of a virtual machine even while the virtual machine is running or paused.  You can then you can revert back to this state at a latter point…  You can create tree’s of snapshots (see screen shot), think about application testing when you might need an XP RTM image, XP SP1, XP SP2, XP SP1 that was upgraded to SP2 and then rolled back to SP1 etc…  With a snapshot tree you can create all of these interesting combinations without having to reinstall a physical or virtual machine 20 times… and when the next service pack comes out you can just apply the interesting base snapshots create a new snapshot and install the service pack – Major Time Saver!

The way a snapshot works is that Hyper-V creates a copy of the virtual machine configuration (network connections, disk configuration, cpu count, ram count etc…) Hyper-V then creates a special diffrencing VHD file known as an AVHD for every virtual hard disk connected to the VM to prevent the current VHD from being changed.  If the virtual machine is running a full copy of the guest memory is also saved – unlike a saved state the virtual machine continues to run while this is occurring.  There are a few things that should be noted, since Hyper-V effectively uses a diffrencing VHD to branch the hard disk state VM’s that are using passthough disks or cd’s can not be snapshoted.  Along the same lines just like diffrencing VHD files have a disk read and write performance penalty over a fixed or even dynamically expanding VHD snapshots to incur this cost.  Another thing to note is that the AVHD file and saved memory file by default is located in the same location as the virtual machine configuration, this can be changed either by creating the virtual machine in a non-default location or more comely in the Virtual Machine Settings’s UI under Management (Snapshot File Location).

Snapshot’s are excellent for test and development they are a huge time saver.  They are also great for staging up a server you get the ability to undo when you accidentally type the wrong machine name or password… Just remember to merge your snapshots before putting the server into production, to merge a snapshot you just deleted the snapshot tree with the virtual machine off, it will then start a background merge which you can monitor from the Hyper-V management UI.  When the merge is completed you will have a flat VHD that you can then put into production with no-performance impact.  Now let’s see some code!

Taking a Snapshot
$VMManagementService=Get-WmiObject-Namespaceroot\virtualization-ClassMsvm_VirtualSystemManagementService
$SourceVm=Get-WmiObject-Namespaceroot\virtualization-Query"Select * From Msvm_ComputerSystem Where ElementName='VmToSnapshot'"

$result=$VMManagementService.CreateVirtualSystemSnapshot($SourceVm)
#ProcessWMIJob($result)
Applying a Snapshot
$VMManagementService=Get-WmiObject-Namespaceroot\virtualization-ClassMsvm_VirtualSystemManagementService
$SourceVm=Get-WmiObject-Namespaceroot\virtualization-Query"Select * From Msvm_ComputerSystem Where ElementName='VmToSnapshot'"
$Snapshot=Get-WmiObject-Namespaceroot\virtualization-Query"Associators Of {$SourceVm} Where AssocClass=Msvm_ElementSettingData ResultClass=Msvm_VirtualSystemSettingData"

$result=$VMManagementService.ApplyVirtualSystemSnapshot($SourceVm,$Snapshot)
#ProcessWMIJob($result)
Deleting a Snapshot
$VMManagementService=Get-WmiObject-Namespaceroot\virtualization-ClassMsvm_VirtualSystemManagementService
$SourceVm=Get-WmiObject-Namespaceroot\virtualization-Query"Select * From Msvm_ComputerSystem Where ElementName='VmToSnapshot'"
$Snapshot=Get-WmiObject-Namespaceroot\virtualization-Query"Associators Of {$SourceVm} Where AssocClass=Msvm_ElementSettingData ResultClass=Msvm_VirtualSystemSettingData"

$result=$VMManagementService.RemoveVirtualSystemSnapshot($Snapshot)
#ProcessWMIJob($result)
Enumerating Snapshots
$SourceVm=Get-WmiObject-Namespaceroot\virtualization-Query"Select * From Msvm_ComputerSystem Where ElementName='VmToSnapshot'"
Get-WmiObject-Namespaceroot\virtualization-Query"Associators Of {$SourceVm} Where AssocClass=Msvm_ElementSettingData ResultClass=Msvm_VirtualSystemSettingData"|Format-List-PropertyElementName,InstanceID
Enumerating Snapshots – With a bit more information…
$SourceVm=Get-WmiObject-Namespaceroot\virtualization-Query"Select * From Msvm_ComputerSystem Where ElementName='VmToSnapshot'"
$Snapshots=Get-WmiObject-Namespaceroot\virtualization-Query"Associators Of {$SourceVm} Where AssocClass=Msvm_ElementSettingData ResultClass=Msvm_VirtualSystemSettingData"

$script:list=@()
foreach ($Snapshotin$Snapshots)
{
   
$SnapObj=New-Object-TypeNameSystem.Object
   
$SnapObj|Add-Member-MemberTypeNoteProperty-NameSnapshotName-Value$Snapshot.ElementName
   
$SnapObj|Add-Member-MemberTypeNoteProperty-NameSnapshotID-Value$Snapshot.InstanceID
   
$SnapObj|Add-Member-MemberTypeNoteProperty-NameSnapshotParentName-Value ([WMI]$Snapshot.Parent).ElementName
   
$script:list+=$SnapObj
}
$script:list
ProcessWMIJob Function
Put this block at the top of your script and uncomment the ProcessWMIJob call if you want the function call to wait for completion and provide error messages…
functionProcessWMIJob

   
param
    ( 
        [
System.Management.ManagementBaseObject]$Result
    ) 

   
if ($Result.ReturnValue-eq4096)
    { 
       
$Job= [WMI]$Result.Job

       
while ($Job.JobState-eq4)
        { 
           
Write-Progress$Job.Caption"% Complete"-PercentComplete$Job.PercentComplete
           
Start-Sleep-seconds1
           
$Job.PSBase.Get()
        } 
       
if ($Job.JobState-ne7)
        { 
           
Write-Error$Job.ErrorDescription
           
Throw$Job.ErrorDescription
        } 
       
Write-Progress$Job.Caption"Completed"-Completed$TRUE
    } 
   
elseif ($Result.ReturnValue-ne0)
    { 
       
Write-Error"Hyper-V WMI Job Failed!"
       
Throw$Result.ReturnValue
    } 

ENJOY!

Taylor Brown
Hyper-V Integration Test Lead
http://blogs.msdn.com/taylorb

clip_image001


Hyper-V WMI: Rich Error Messages for Non-Zero ReturnValue (no more 32773, 32768, 32700…)

$
0
0

Since I did my last post on snapshots I have gotten several comments and few e-mails asking how to map ReturnValues to actual human readable strings.  I guess not every one just knows that 32773 is Invalid Parameter…  Well after many hours of asking and playing I have the answer – or at least a good start so here it is:

The real magic is this in ProcessWMIJob… it now operates on the pipeline and can take two new parameters one for the WmiClassPath and a second for the MethodName…  It uses those to retrieve the error strings for the specific class and function from WMI…  To use this just put it at the top of your scripts or in your environment and party on…

filterProcessWMIJob

   
param
    ( 
        [
string]$WmiClassPath=$null,
        [
string]$MethodName=$null
    )
    
   
$errorCode=0

   
if ($_.ReturnValue-eq4096)
    { 
       
$Job= [WMI]$_.Job

       
while ($Job.JobState-eq4)
        { 
           
Write-Progress$Job.Caption"% Complete"-PercentComplete$Job.PercentComplete
           
Start-Sleep-seconds1
           
$Job.PSBase.Get()
        } 
       
if ($Job.JobState-ne7)
        { 
           
if ($Job.ErrorDescription-ne"")
            {
               
Write-Error$Job.ErrorDescription
               
Throw$Job.ErrorDescription
            }
           
else
            {
               
$errorCode=$Job.ErrorCode
            }
        } 
       
Write-Progress$Job.Caption"Completed"-Completed$TRUE
    }
   
elseif($_.ReturnValue-ne0)
    {
       
$errorCode=$_.ReturnValue
    }
    
   
if ($errorCode-ne0)
    { 
       
Write-Error"Hyper-V WMI Job Failed!"
       
if ($WmiClassPath-and$MethodName)
        {
           
$psWmiClass= [WmiClass]$WmiClassPath
           
$psWmiClass.PSBase.Options.UseAmendedQualifiers=$TRUE
           
$MethodQualifiers=$psWmiClass.PSBase.Methods[$MethodName].Qualifiers
           
$indexOfError= [System.Array]::IndexOf($MethodQualifiers["ValueMap"].Value, [string]$errorCode)
           
if ($indexOfError-ne"-1")
            {
               
Throw"ReturnCode: ",$errorCode," ErrorMessage: '",$MethodQualifiers["Values"].Value[$indexOfError],"' - when calling $MethodName"
            }
           
else
            {
               
Throw"ReturnCode: ",$errorCode," ErrorMessage: 'MessageNotFound' - when calling $MethodName"
            }
        }
       
else
        {
           
Throw"ReturnCode: ",$errorCode,"When calling $MethodName - for rich error messages provide classpath and method name."
        }
    } 
   
return$_
}

Example:

$VHDService=get-wmiobject-class"Msvm_ImageManagementService"-namespace"root\virtualization"
$VHDService.CreateDynamicVirtualHardDisk("C:\Users\Public\Documents\Hyper-V\Virtual hard disks\MyVHD.vhd",20GB) |ProcessWMIJob$VHDService"CreateDynamicVirtualHardDisk"

Revised 7/6 To Add Support For WMI Jobs that have blank Error Descriptions.
Revised 7/28 To Return Created Object on Success and To Add Sample Code...

Taylor Brown
Hyper-V Integration Test Lead
http://blogs.msdn.com/taylorb

clip_image001

Hyper-V WMI: KVP Exchange aka Data Exchange (Adding New Items From Parent/Host)

$
0
0

Update 12/5/12

A lot has changed since 2008 and many things have stayed the same…  I wanted to provide an update to some of the most commonly viewed posts and this was one of them.

For updated information on this topic please refer to my latest post Customizing The Key Value Pair (KVP) Integration Component.

 

Original Post

I have gotten a ton of questions about the KVP Exchange or Data Exchange Integration Component…  So what is it and how do I use it?  The KVP Integration component allows the guest and host to query and provide information to each via pairs of Key’s and Value’s. The KVP integration component provides some basic Key’s and Value’s for you, I talked about the host accessible ones in a previous post Hyper-V WMI Using PowerShell Scripts – Part 3 (KVP's - Guest OS Version) these include things like the fully qualified name, OS version, Processor Architecture etc…  There are also some guest accessible values that provide some information on the parent (host) such as HostName, PhysicalHostName, PhysicalHostNameFullyQualified, and VirtualMachineName.  These values are located in registry under “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters”.  The other thing you can do via the KVP is write registry key’s from the parent (host) and read guest provided registry key’s from the parent (host).  Today I am going to show how to write key’s from the parent into the guest.

Add-KVP.ps1 Script

The AddKvpItems method returns a WMI Job Object see Hyper-V WMI- Rich Error Messages for Non-Zero ReturnValue (no more 32773, 32768, 32700…) for very helpful method to provide rich error messages.

$ComputerName="localhost"

$VMManagementService=Get-WmiObject-class"Msvm_VirtualSystemManagementService"-namespace"root\virtualization"-ComputerName$ComputerName
$Vm=Get-WmiObject-Namespaceroot\virtualization-ComputerName$ComputerName-Query"Select * From Msvm_ComputerSystem Where ElementName='Vista'"
$Kvp=Get-WmiObject-Namespaceroot\virtualization-ComputerName$ComputerName-Query"Associators of {$Vm} Where AssocClass=Msvm_SystemDevice ResultClass=Msvm_KvpExchangeComponent"

$Msvm_KvpExchangeDataItemPath="\\$ComputerName\root\virtualization:Msvm_KvpExchangeDataItem"
$Msvm_KvpExchangeDateItem= ([WmiClass]$Msvm_KvpExchangeDataItemPath).CreateInstance()
$Msvm_KvpExchangeDateItem.Name="Test4"
$Msvm_KvpExchangeDateItem.Data="Testing"
$Msvm_KvpExchangeDateItem.Source=0

$VMManagementService.AddKvpItems($Vm,$Msvm_KvpExchangeDateItem.PSBase.GetText(1))

 

 

 

And as you can see I have a new registry entry… (btw 64bit Vista SHWEEET!)

 

 

 

 

clip_image001

 

 

Taylor Brown
Hyper-V Integration Test Lead
http://blogs.msdn.com/taylorb

clip_image001

Hyper-V WMI: KVP Exchange aka Data Exchange (Adding New Items From Guest)

$
0
0

Update 12/5/12

A lot has changed since 2008 and many things have stayed the same…  I wanted to provide an update to some of the most commonly viewed posts and this was one of them.

For updated information on this topic please refer to my latest post Customizing The Key Value Pair (KVP) Integration Component.

 

Original Post

Yesterday’s post (Hyper-V WMI: KVP Exchange aka Data Exchange (Adding New Items From Parent/Host)) showed how to add registry key’s into the guest so that the guest could receive information from the host.  Today’s post will show how to add a registry key in the guest so that the host can retrieve it…

Step 1 – Add a registry key to the guest…

Use your faviorite registy editing tool such a reg.exe or powershell.

Examples:
Reg.exe: reg add "HKLM\SOFTWARE\Microsoft\Virtual Machine\Guest" /v test /t REG_SZ /d testing
Powershell: New-ItemProperty -path "HKLM:\SOFTWARE\Microsoft\Virtual Machine\Guest" -name test2 -value testing

Step 2 – Query the value from the host…

This might look very similar to Hyper-V WMI Using PowerShell Scripts – Part 3 (KVP's - Guest OS Version) it is…(just the last line changes :-))

filterImport-CimXml
{
   
$CimXml= [Xml]$_
   
$CimObj=New-Object-TypeNameSystem.Object
   
foreach ($CimPropertyin$CimXml.SelectNodes("/INSTANCE/PROPERTY"))
    {
       
$CimObj|Add-Member-MemberTypeNoteProperty-Name$CimProperty.NAME-Value$CimProperty.VALUE
    }
   
$CimObj
}

$Vm=Get-WmiObject-Namespaceroot\virtualization-Query"Select * From Msvm_ComputerSystem Where ElementName='vista'"
$Kvp=Get-WmiObject-Namespaceroot\virtualization-Query"Associators of {$Vm} Where AssocClass=Msvm_SystemDevice ResultClass=Msvm_KvpExchangeComponent"
$Kvp.GuestExchangeItems|Import-CimXml

Output:

Caption     :
Data        : testing
Description :
ElementName :
Name        : test
Source      : 1

Caption     :
Data        : testing
Description :
ElementName :
Name        : test2
Source      : 1

 

Taylor Brown
Hyper-V Integration Test Lead
http://blogs.msdn.com/taylorb

clip_image001

Hyper-V WMI: KVP Exchange aka Data Exchange (Retrieving and Modifying Parent/Host KVP’s)

$
0
0

On Sunday I showed how to add registry keys to the guest from the host (Hyper-V WMI: KVP Exchange aka Data Exchange (Adding New Items From Parent/Host)) and on Monday I showed how to read registry key’s written by the guest from the host (Hyper-V WMI- KVP Exchange aka Data Exchange (Adding New Items From Guest)).  Today I am going to show how to retrieve previously added host keys and modify there values…

Retrieving Previously Added Key’s

filterImport-CimXml
{
   
$CimXml= [Xml]$_
   
$CimObj=New-Object-TypeNameSystem.Object
   
foreach ($CimPropertyin$CimXml.SelectNodes("/INSTANCE/PROPERTY"))
    {
       
$CimObj|Add-Member-MemberTypeNoteProperty-Name$CimProperty.NAME-Value$CimProperty.VALUE
    }
   
$CimObj
}

$Vm=Get-WmiObject-Namespaceroot\virtualization -Query"Select * From Msvm_ComputerSystem Where ElementName='vista'"
$Kvp=Get-WmiObject-Namespaceroot\virtualization-Query"Associators of {$Vm} Where AssocClass=Msvm_SystemDevice ResultClass=Msvm_KvpExchangeComponent"
$GuestKvp=Get-WmiObject-Namespaceroot\virtualization-Query"Associators of {$Kvp} Where AssocClass=Msvm_ElementSettingData ResultClass=Msvm_KvpExchangeComponentSettingData"
$GuestKvp.HostExchangeItems|Import-CimXml

 

Modifying Previously Added Key’s

This is almost identical to the script to add a KVP except in this case you need to provide a Name of an existing KVP and call the ModifyKvpItems method…
Note: If you are using my ProcessWMIObject function and getting a blank error message you should update to the latest version posted 7/6.

$ComputerName="localhost"

$VMManagementService=Get-WmiObject-class"Msvm_VirtualSystemManagementService"-namespace"root\virtualization"-ComputerName$ComputerName
$Vm=Get-WmiObject-Namespaceroot\virtualization-ComputerName$ComputerName-Query"Select * From Msvm_ComputerSystem Where ElementName='Vista'"
$Kvp=Get-WmiObject-Namespaceroot\virtualization-ComputerName$ComputerName-Query"Associators of {$Vm} Where AssocClass=Msvm_SystemDevice ResultClass=Msvm_KvpExchangeComponent"

$Msvm_KvpExchangeDataItemPath="\\$ComputerName\root\virtualization:Msvm_KvpExchangeDataItem"
$Msvm_KvpExchangeDateItem= ([WmiClass]$Msvm_KvpExchangeDataItemPath).CreateInstance()
$Msvm_KvpExchangeDateItem.Name=<PreviousKeyName>
$Msvm_KvpExchangeDateItem.Data="Foo"
$Msvm_KvpExchangeDateItem.Source=0

$VMManagementService.ModifyKvpItems($Vm,$Msvm_KvpExchangeDateItem.PSBase.GetText(1))

 

Taylor Brown
Hyper-V Integration Test Lead
http://blogs.msdn.com/taylorb

clip_image001

Hyper-V WMI: What VHD’s/Physical Disks Are Associated With a Virtual Machine?

$
0
0

I  got a great question based on yesterday’s post (by the way my e-mail was blocking a lot of external messages that’s fixed now so I apologize to anyone I missed a mail from).  The person was asking how they could figure out what physical disk a virtual machine is using when configured for passthough on the host…  Well here’s the magic – I took it a little further and got the path’s for any attached VHD’s…  Enjoy!

 

$HyperVParent="localhost"
$HyperVGuest="My Virtual Machine"

$VMManagementService=Get-WmiObject-class"Msvm_VirtualSystemManagementService"-namespace"root\virtualization"-ComputerName$HyperVParent
$Vm=Get-WmiObject-Namespace"root\virtualization"-ComputerName$HyperVParent-Query"Select * From Msvm_ComputerSystem Where ElementName='$HyperVGuest'"
$VMSettingData=Get-WmiObject-Namespace"root\virtualization"-Query"Associators of {$Vm} Where ResultClass=Msvm_VirtualSystemSettingData AssocClass=Msvm_SettingsDefineState"-ComputerName$HyperVParent

#
#Getting the Path's for Attached VHD's
$VirtualDiskResource=Get-WmiObject-Namespace"root\virtualization"`
   
-Query"Associators of {$VMSettingData} Where ResultClass=Msvm_ResourceAllocationSettingData AssocClass=Msvm_VirtualSystemSettingDataComponent"`
   
-ComputerName$HyperVParent|Where-Object { $_.ResourceSubType-match"Microsoft Virtual Hard Disk" }
    
ForEach-Object-InputObject$VirtualDiskResource-Process {
   
Write-Host"Virtual Hard Disk At: $_.Connection[0]"
}

#
#Getting the Disk Attachments for Passthrough Disks
$PhysicalDiskResource=Get-WmiObject-Namespace"root\virtualization"`
   
-Query"Associators of {$VMSettingData} Where ResultClass=Msvm_ResourceAllocationSettingData AssocClass=Msvm_VirtualSystemSettingDataComponent"`
   
-ComputerName$HyperVParent|Where-Object { $_.ResourceSubType-match"Microsoft Physical Disk Drive" }
    
ForEach-Object-InputObject$PhysicalDiskResource-Process {
   
Write-Host"Passthrough Disk At: " ([WMI]$_.HostResource[0]).ElementName
   
Write-Host"Passthrough Disk Drive Number: " ([WMI]$_.HostResource[0]).DriveNumber
}

 

Taylor Brown
Hyper-V Integration Test Lead
http://blogs.msdn.com/taylorb

clip_image001

Open Source PowerShell Editor -- PowerGUI

$
0
0

imageMany of you know I have been a fan of PowerShellPlus for quite a while, but I was turned on to a new editor the other day that’s pretty slick – PowerGUI.  Winner of this years Windows IT Pro Magazine’s Best of Tech Ed IT Pro Breakthrough Product Award this editor/GUI is not to shabby…  The editor and debugger are fast and the auto compleate works pretty good – the only thing it’s missing as a copy as html (how do you think I post those samples!).  The other cool thing PowerGUI sports is a nice library plugin model – when you install it you can chose to download and install many of the Quest libraries such as Active Directory management but there’s about 50 libraries listed on the PowerGUI site (none for Hyper-V yet hint hint).image

 

 

 

 

 

 

 

 

 

 

 

 

 

Taylor Brown
Hyper-V Integration Test Lead
http://blogs.msdn.com/taylorb

clip_image001

PDC Teaser – Attaching a VHD to A Virtual Machine

$
0
0

PDC is just around the corner now – I am giving the dry run of my talk tomorrow morning, so of course I am working on my demo’s today…  Just to give you a bit of a teaser here’s one of the scripts that I am using in one of my demo’s…

This script will take a VHD and attach it to the second port of the first IDE controller, just change the address numbers and you can change where it get’s attached.


Note that I am using the ProcessWMIJob function from Hyper-V WMI: Rich Error Messages for Non-Zero ReturnValue (no more 32773, 32768, 32700…)

$vhdToMount="c:\test.vhd"
$HyperVGuest="ScriptTest"

$VMManagementService=Get-WmiObject-class"Msvm_VirtualSystemManagementService"-namespace"root\virtualization"
$Vm=Get-WmiObject-Namespace"root\virtualization"-Query"Select * From Msvm_ComputerSystem Where ElementName='$HyperVGuest'"
$VMSettingData=Get-WmiObject-Namespace"root\virtualization"-Query"Associators of {$Vm} Where ResultClass=Msvm_VirtualSystemSettingData AssocClass=Msvm_SettingsDefineState"
$VmScsiController= (Get-WmiObject-Namespace"root\virtualization"-Query"Associators of {$VMSettingData} Where ResultClass=Msvm_ResourceAllocationSettingData AssocClass=Msvm_VirtualSystemSettingDataComponent" | `
                       
where-object {$_.ResourceSubType -eq"Microsoft Emulated IDE Controller"-and$_.Address -eq0})
                        
$DiskAllocationSetting=Get-WmiObject-Namespace"root\virtualization"-Query"SELECT * FROM Msvm_AllocationCapabilities WHERE ResourceSubType = 'Microsoft Synthetic Disk Drive'"
$DefaultDiskDrive= (Get-WmiObject-Namespace"root\virtualization"-Query"Associators of {$DiskAllocationSetting} Where ResultClass=Msvm_ResourceAllocationSettingData AssocClass=Msvm_SettingsDefineCapabilities" | `
                       
where-object {$_.InstanceID -like"*Default"})
$DefaultDiskDrive.Parent =$VmScsiController.__Path
$DefaultDiskDrive.Address =1
$NewDiskDrive= ($VMManagementService.AddVirtualSystemResources($Vm.__Path, $DefaultDiskDrive.PSBase.GetText(1)) | ProcessWMIJob $VMManagementService"AddVirtualSystemResources").NewResources

$DiskAllocationSetting=Get-WmiObject-Namespace"root\virtualization"-Query"SELECT * FROM Msvm_AllocationCapabilities WHERE ResourceSubType = 'Microsoft Virtual Hard Disk'"
$DefaultHardDisk= (Get-WmiObject-Namespace"root\virtualization"-Query"Associators of {$DiskAllocationSetting} Where ResultClass=Msvm_ResourceAllocationSettingData AssocClass=Msvm_SettingsDefineCapabilities" | `
                       
where-object {$_.InstanceID -like"*Default"})
                        
$DefaultHardDisk.Parent =$NewDiskDrive
$DefaultHardDisk.Connection =$vhdToMount

$VMManagementService.AddVirtualSystemResources($Vm.__Path, $DefaultHardDisk.PSBase.GetText(1)) | ProcessWMIJob $VMManagementService"AddVirtualSystemResources"

 

Taylor Brown
Hyper-V Integration Test Lead
http://blogs.msdn.com/taylorb

clip_image001


Hyper-V PowerGUI PowerPack – Now That’s Power….

$
0
0

I loved PowerGUI ever since I found it a month ago or so… Well Kirk and the PowerGUI guys have done it again… They now have a pretty comprehensive PowerShell wrapper for Hyper-V… Pretty Cool!

http://poshoholic.com/2008/10/22/powergui-now-with-100-more-hyper-v/
As of today, PowerGUI users can download a free Hyper-V PowerPack for PowerGUI!  This PowerPack has been a huge undertaking, to put it mildly, and I’m absolutely thrilled with the end result (and so happy that I’ve finally finished the first version…whew)!  Here’s a list of some of the key features that this PowerPack provides:

  1. Bulk management of multiple VMs, Virtual Networks, Virtual Hard Drives, Snapshots, etc. within one Hyper-V servers and across multiple Hyper-V servers.
  2. Support for remote management of Hyper-V servers using alternate credentials.
  3. Integrated management of standard Windows features like Processes, Services, Event Logs, etc.
  4. Automatic credential caching (in memory, not to disk) allowing you to enter a password for a Hyper-V server you are managing only once per PowerGUI session.
  5. Discovery of Hyper-V servers through Active Directory.
  6. Over 30 rich user-defined functions that wrap the Hyper-V WMI interfaces and provide a cmdlet-like experience when scripting with Hyper-V while outputting rich, custom objects complete with properties and methods to script to your heart’s content.  Many of these functions support CSV input through Import-Csv, so there are a lot of opportunities for provisioning already available.
  7. 101 links and actions allowing you to manage just about everything you would want to manage in Hyper-V, including configuration of security via AzMan Scopes, Snapshot refresh, and many, many more.

Download: http://www.powergui.org/entry.jspa?externalID=2142&categoryID=21

Taylor Brown
Hyper-V Integration Test Lead
http://blogs.msdn.com/taylorb

clip_image001

    Hyper-V: Background Merging of AVHD’s… When’s it done?

    $
    0
    0

    image

    I think it might be best to start at ground zero with this topic and explain what a snapshot really is and how it work’s (if you already know skip a head…).  Hyper-V introduced a new feature called a snapshot – snapshots allow you to capture and save the point in time state of a running or saved virtual machine and then go back to that state at a latter point in time.  For example you can have a Windows XP RTM virtual machine running take a snapshot, install SP1, take a snapshot and install SP2 and then latter revert back to the SP1 snapshot and either discard the SP2 installation or keep it around so you can apply that state latter.  Snapshot’s are pretty handing in this regard – you can create pretty extensive tree’s of snapshots and you can rapidly apply specific states to virtual machines.  Under the covers snapshots primarily use a technology that was implemented back in the pre-Microsoft days of Virtual PC called differencing VHD’s.  What a differencing VHD effectively does is point back to a parent VHD for it’s data but any updates made to the VHD reside in the new differencing VHD and subsequent requests for that same data will be overridden by the child differencing VHD.  These parent child relationships can get many levels deep and a parent can have many children – however if a parent is ever modified it’s children's state is now invalid since the child was unaware of the changes.  So back to snapshots – when a snapshot is taken we create a new differencing disk to point the virtual machine to and we call it an AVHD or automatic VHD since it was created automatically by requesting the snapshot – at the same time we will save off the virtual machines running state if it’s running including it’s memory state and it’s device state (network adapter IP etc…).  When you revert back to a previous snapshot you reload the memory and device state and the VM is pointed at a new AVHD from the parent of that time.  And that’s snapshots in a nut shell…

    OK now back to topic at hand – when you delete a snapshot the next time the virtual machine is off or saved we will merge the AVHD created by the snapshot back into it’s respective parent…  We do this automatically and in the background – so lets say you wanted to know when it’s was done programmatically…  It’s not too hard just run the following query to see if any merges are going on presently - PS C:\> Get-WmiObject -Namespace "root\virtualization" -Query "select * from Msvm_ConcreteJob" | Where {$_.ElementName - eq 'Merge in Progress'}.  Below you can see the full output of that query when a merge is occurring.  Hope this helps!

     

    PS C:\> Get-WmiObject -Namespace "root\virtualization" -Query "select * from Msvm_ConcreteJob" | Where {$_.ElementName -eq 'Merge in Progress'}

    __GENUS                 : 2
    __CLASS                 : Msvm_ConcreteJob
    __SUPERCLASS            : CIM_ConcreteJob
    __DYNASTY               : CIM_ManagedElement
    __RELPATH               : Msvm_ConcreteJob.InstanceID="E3675DEB-A13C-440D-AEAD-B6CEB5ADF1D7"
    __PROPERTY_COUNT        : 36
    __DERIVATION            : {CIM_ConcreteJob, CIM_Job, CIM_LogicalElement, CIM_ManagedSystemElement...}
    __SERVER                : TAYLORB
    __NAMESPACE             : root\virtualization
    __PATH                  : \\TAYLORB\root\virtualization:Msvm_ConcreteJob.InstanceID="E3675DEB-A13C-440D-AEAD-B6CEB5ADF1D7"
    Cancellable             : True
    Caption                 : Merge in Progress
    DeleteOnCompletion      : False
    Description             : Merge in Progress
    ElapsedTime             : 00000000000000.000000:000
    ElementName             : Merge in Progress
    ErrorCode               : 0
    ErrorDescription        :
    ErrorSummaryDescription :
    HealthState             : 0
    InstallDate             : 16010101000000.000000-000
    InstanceID              : E3675DEB-A13C-440D-AEAD-B6CEB5ADF1D7
    JobRunTimes             : 1
    JobState                : 4
    JobStatus               :
    LocalOrUtcTime          : 2
    Name                    : Merge in Progress
    Notify                  :
    OperationalStatus       : {0, 0, 0}
    OtherRecoveryAction     :
    Owner                   :
    PercentComplete         : 13                          <----Percent Complete
    Priority                : 0
    RecoveryAction          : 0
    RunDay                  : 0
    RunDayOfWeek            : 0
    RunMonth                : 0
    RunStartInterval        : 00000000000000.000000:000
    ScheduledStartTime      : 16010101000000.000000-000
    StartTime               : 16010101000000.000000-000
    Status                  :
    StatusDescriptions      : {, , }
    TimeBeforeRemoval       : 00000000000500.000000:000
    TimeOfLastStateChange   : 20090309234922.000000-000
    TimeSubmitted           : 16010101000000.000000-000
    UntilTime               : 16010101000000.000000-000

    Taylor Brown
    Hyper-V Integration Test Lead
    http://blogs.msdn.com/taylorb

    clip_image001

    Attaching Passthough Disks Via WMI (SCSI or IDE)

    $
    0
    0

    So you want to use passthough disks with Hyper-V cool – but how do you script attaching them?  Well here’s your answer…  But first you need to decide if you are going to attach them to the virtual IDE controller or the virtual SCSI controller.  The IDE controller is ideal if you plan to boot from the passthough disk or if your guest doesn’t support the virtual SCSI adapter (Linux), the SCSI controller is ideal if you want to add/remove storage from the virtual machine while it’s running (feature of Hyper-V R2) or if you have more than 4 disks you want to add.  Attaching to SCSI or IDE is pretty similar – there are really only 1 difference I bolded it on both scripts below you just have to select the correct controller.  Other than that you can either use the physical disk number for disk manager (not too bad) or if you provide a LUN ID when you create the storage (in the case of a SAN) you can use that which can be a bit more deterministic.  Either way enjoy!

     

    Attaching Passthrough Disk To IDE Controller

    $HyperVGuest="Passthough Demo"

    $VMManagementService=Get-WmiObject-class"Msvm_VirtualSystemManagementService"-namespace"root\virtualization"
    $Vm=Get-WmiObject-Namespace"root\virtualization"-Query"Select * From Msvm_ComputerSystem Where ElementName='$HyperVGuest'"

    $VMSettingData=Get-WmiObject-Namespace"root\virtualization"-Query"Associators of {$Vm} Where ResultClass=Msvm_VirtualSystemSettingData AssocClass=Msvm_SettingsDefineState"


    $VmIdeController= (Get-WmiObject-Namespace"root\virtualization"-Query"Associators of {$VMSettingData} Where ResultClass=Msvm_ResourceAllocationSettingData AssocClass=Msvm_VirtualSystemSettingDataComponent" |`
                           
    where-object {$_.ResourceSubType -eq"Microsoft Emulated IDE Controller"-and$_.Address -eq0
    }) 
     
    $DiskAllocationSetting=Get-WmiObject-Namespace"root\virtualization"-Query"SELECT * FROM Msvm_AllocationCapabilities WHERE ResourceSubType = 'Microsoft Physical Disk Drive'"
    $DefaultHardDisk= (Get-WmiObject-Namespace"root\virtualization"-Query"Associators of {$DiskAllocationSetting} Where ResultClass=Msvm_ResourceAllocationSettingData AssocClass=Msvm_SettingsDefineCapabilities" | `
                           
    where-object {$_.InstanceID -like"*Default"})

                           
    $Disk=Get-WmiObject-Namespace"root\virtualization"-Query"select * from Msvm_DiskDrive Where DriveNumber=2"
    #$Disk = Get-WmiObject -Namespace "root\virtualization" -Query "select * from Msvm_DiskDrive Where ElementName Like '%Lun 200%'"

    $DefaultHardDisk.Parent =$VmIdeController.__Path
    $DefaultHardDisk.Address =0
    $DefaultHardDisk.HostResource =$Disk.__PATH

    $VMManagementService.AddVirtualSystemResources($VM, $DefaultHardDisk.PSBase.GetText(1)) | ProcessWMIJob $VMManagementService"AddVirtualSystemResources"

    Attaching Passthrough Disk To SCSI Controller

    $HyperVGuest="Passthough Demo"

    $VMManagementService=Get-WmiObject-class"Msvm_VirtualSystemManagementService"-namespace"root\virtualization"
    $Vm=Get-WmiObject-Namespace"root\virtualization"-Query"Select * From Msvm_ComputerSystem Where ElementName='$HyperVGuest'"

    $VMSettingData=Get-WmiObject-Namespace"root\virtualization"-Query"Associators of {$Vm} Where ResultClass=Msvm_VirtualSystemSettingData AssocClass=Msvm_SettingsDefineState"


    $VmScsiController= (Get-WmiObject-Namespace"root\virtualization"-Query"Associators of {$VMSettingData} Where ResultClass=Msvm_ResourceAllocationSettingData AssocClass=Msvm_VirtualSystemSettingDataComponent" | `
                             where-object {$_.ElementName -eq"SCSI Controller"})

    $DiskAllocationSetting=Get-WmiObject-Namespace"root\virtualization"-Query"SELECT * FROM Msvm_AllocationCapabilities WHERE ResourceSubType = 'Microsoft Physical Disk Drive'"

    $DefaultHardDisk= (Get-WmiObject-Namespace"root\virtualization"-Query"Associators of {$DiskAllocationSetting} Where ResultClass=Msvm_ResourceAllocationSettingData AssocClass=Msvm_SettingsDefineCapabilities" | `
                            where-object {$_.InstanceID -like"*Default"})                   

    $Disk=Get-WmiObject-Namespace"root\virtualization"-Query"select * from Msvm_DiskDrive Where DriveNumber=2"

    #$Disk = Get-WmiObject -Namespace "root\virtualization" -Query "select * from Msvm_DiskDrive Where ElementName Like '%Lun 200%'"

    $DefaultHardDisk.Parent =$VmScsiController.__Path

    $DefaultHardDisk.Address =0
    $DefaultHardDisk.HostResource =$Disk.__PATH

    $VMManagementService.AddVirtualSystemResources($VM, $DefaultHardDisk.PSBase.GetText(1)) | ProcessWMIJob $VMManagementService"AddVirtualSystemResources"

    Taylor Brown
    Hyper-V Integration Test Lead
    http://blogs.msdn.com/taylorb

    clip_image001

    Scripts From TechEd 2012… Part 1 (Keeping PowerShell Window On Top)

    $
    0
    0

    I just finished my speaking session at TechEd 2012, once the recording is available I will post a link…  I’ve already had an overwhelming number of requests for the scripts that I used during the session.  I’m going to do a few posts over the next few days, as I can steal 10 min from all the TechEd activities.

     

    The first script and the one that every seemed the most interested in keeps a PowerShell Window on top i.e. the top most window.  The way I did it was a bit evil – well very non PowerShell but it works.  I use PInvoke…

     

    $signature = @’
    [DllImport("user32.dll")]
    public static extern bool SetWindowPos(
        IntPtr hWnd,
        IntPtr hWndInsertAfter,
        int X,
        int Y,
        int cx,
        int cy,
        uint uFlags);
    ‘@
     
    $type = Add-Type -MemberDefinition $signature -Name SetWindowPosition -Namespace SetWindowPos -Using System.Text -PassThru

    $handle = (Get-Process -id $Global:PID).MainWindowHandle
    $alwaysOnTop = New-Object -TypeName System.IntPtr -ArgumentList (-1)
    $type::SetWindowPos($handle, $alwaysOnTop, 0, 0, 0, 0, 0x0003)

     

    So there you go – look for more of the scripts latter tonight or tomorrow…

     

    -taylorb

    Removing a VHD From A VM Using The Hyper-V WMI V2 Namespace

    $
    0
    0

    What good would Attaching a VHD To A VM Using The Hyper-V WMI V2 Namespace be if you couldn’t remove one two… Here’s how you do it.

     

    Removing a virtual hard disk

    $vmName = "Test"
    $vhdPath = "d:\vms\Test.vhdx"
    
    #Retrieve the Hyper-V Management Service, ComputerSystem class for the VM and the VM’s SettingData class. 
    $Msvm_VirtualSystemManagementService = Get-WmiObject -Namespace root\virtualization\v2 `
          -Class Msvm_VirtualSystemManagementService
    
    $Msvm_ComputerSystem = Get-WmiObject -Namespace root\virtualization\v2 `
          -Class Msvm_ComputerSystem -Filter "ElementName='$vmName'"
    
    $Msvm_VirtualSystemSettingData = ($Msvm_ComputerSystem.GetRelated("Msvm_VirtualSystemSettingData", `
         "Msvm_SettingsDefineState", `
          $null, `
          $null, `
         "SettingData", `
         "ManagedElement", `
          $false, $null) | % {$_})
    
    #Find the VirtualDisk with the path specified
    $virtualHardDisk = $Msvm_VirtualSystemSettingData.GetRelated("Msvm_StorageAllocationSettingData") | Where-Object {
        ($_.HostResource -contains $vhdPath)}
    
    #Save the associated Disk Drive
    $SyntheticDiskDrive = [WMI]$virtualHardDisk.Parent
    
    #Call the RemoveResourceSettings function with the path to virtual hard disk
    $Msvm_VirtualSystemManagementService.RemoveResourceSettings($virtualHardDisk)
    
    #Call the RemoveResourceSettings function with the path to disk drive
    $Msvm_VirtualSystemManagementService.RemoveResourceSettings($SyntheticDiskDrive)
    
    

    -Taylor Brown

    -Program Manager, Hyper-V

    Viewing all 29 articles
    Browse latest View live


    <script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>