Quantcast
Channel: MSDN Blogs
Viewing all articles
Browse latest Browse all 29128

Creating a Virtual Machine with WMI v2

$
0
0

Most people use the built in Hyper-V PowerShell cmdlets to control Hyper-V these days.  That said, there are people out there who program directly to our WMI APIs.  In Windows Server 2012 we introduced a new WMI namespace– and recently I have been getting a number of questions about how to convert code that talks to our old WMI namespace to the new one.

With that in mind – I am going through blog posts that I have done on programming our WMI APIs and publishing updated versions that use the new namespace.

Today I am going to look at creating a virtual machine.  The sample script for doing this with the WMI v1 namespace is here: http://blogs.msdn.com/b/virtual_pc_guy/archive/2008/05/28/scripting-vm-creation-with-hyper-v.aspx. And here is how you do the same thing in the WMI v2 namespace:

# Prompt for the Hyper-V Server to use$HyperVServer= Read-Host "Specify the Hyper-V Server to create the virtual machine on"# Get name for new VM$VMName= Read-Host "Specify the name for the new virtual machine"# Create new MSVM_VirtualSystemSettingData object$wmiClassString="\\"+$HyperVServer+"\root\virtualization\v2:Msvm_VirtualSystemSettingData"$wmiClass= [WMIClass]$wmiClassString$newVSSD=$wmiClass.CreateInstance()# wait for the new object to be populatedwhile ($newVSSD.Properties -eq$null) {}# Set the VM name$newVSSD.Properties.Item("ElementName").value =$VMName# Get the VirtualSystemManagementService object$VMMS= gwmi MSVM_VirtualSystemManagementService -namespace "root\virtualization\v2"-computername $HyperVServer# Create the VM$result=$VMMS.DefineSystem($newVSSD.GetText(1))#Return success if the return value is "0"if ($Result.ReturnValue -eq0)
   {write-host "Virtual machine created."} #If the return value is not "0" or "4096" then the operation failedElseIf ($Result.ReturnValue -ne4096)
   {write-host "Failed to create virtual machine"}Else
   {#Get the job object$job=[WMI]$Result.job#Provide updates if the jobstate is "3" (starting) or "4" (running)while ($job.JobState -eq3-or$job.JobState -eq4)
      {write-host $job.PercentComplete
       start-sleep 1#Refresh the job object$job=[WMI]$Result.job}#A jobstate of "7" means successif ($job.JobState -eq7)
       {write-host "Virtual machine created."}Else
       {write-host "Failed to create virtual machine"
        write-host "ErrorCode:"$job.ErrorCode
        write-host "ErrorDescription"$job.ErrorDescription}
   }

These two scripts look very similar.  But there are some key differences:

  • The script uses the "root\virtualization\v2” namespace instead of the “root\virtualization”
    • It surprises me the number of people that email me with questions about WMI code who do not know which WMI namespace they are using.  A simple search of your code for “root\virtualization” will give you the answer quickly.
  • The script uses the DefineSystem method instead of DefineVirtualSystem method to actually create the virtual machine
    • This is a simple name change to better align with the latest DMTF standard.  The functionality of this API is the same.
  • A number of “psbase” objects have been removed from the script
    • This is actually nothing to do with the new WMI namespace, but is instead because I am writing this script in a more recent version of PowerShell.  PowerShell v2 required that you use .psbase to access the properties of a WMI object.  PowerShell v3 does not.
  • The script creates a new MSVM_VirtualSystemSettingData instead of creating a new MSVM_VirtualSystemGlobalSettingData

The reason for this last change is quite interesting (to me – anyway) as it is the result of a philosophical change in the underlying platform. 

When we started designing virtual machine management and virtual machine snapshot management in Hyper-V we had a simple premise: virtual machine snapshots should just be read-only virtual machine instances.  This meant that at a WMI level we wanted to use the same object (VirtualSystemSettingData) to describe a virtual machine or a virtual machine snapshot.  Applying a virtual machine snapshot would then just update the “active” VirtualSystemSettingData. 

However, we encountered an issue with this approach. 

When you apply a virtual machine snapshot you do not actually want to copy the whole VirtualSystemSettingData over to the active virtual machine – for example: you do not want to change the virtual machine name when you apply a snapshot, but you do want the snapshot to have a different name.  We solved this problem by creating the VirtualSystemGlobalSettingData object.  This was a class that would store any virtual machine settings that we did not want to change when you applied a snapshot.

The problem with this approach is that it required someone who was coding against the Hyper-V WMI API to be aware of which properties were global and which were local. 

With the WMI v2 namespace we did something more intelligent – we put all the settings on the VirtualSystemSettingData and when you apply a snapshot we just do not apply the fields that we do not want to overwrite.  This means that for developers:

  • All settings belonging to a virtual machine are now in one place, not two.
  • When you create a new virtual machine you now create a VirtualSystemSettingData object, not a VirtualSystemGlobalSettingData object

Cheers,
Ben


    Viewing all articles
    Browse latest Browse all 29128

    Trending Articles



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