Scripting Hyper-V with WMI and PowerShell
Part 1 – Introduction + Querying State
Introduction
When it comes to scripting Hyper-V there are really 2 methods:
1. Using the virtualization WMI provider that ships with Hyper-V.
2. Using the cmdlets provided by System Centre Virtual Machine Manager 2008
So which option should you use? Well if you want an easy life, the answer is absolutely Option 2. Use SCVMM 2008, and scripting Hyper-V is like a pleasurable dream. The cmdlets are task orientated, provide a rich set of features and really do work very well. So why is this a guide to Option 1 – Using the virtualization WMI provider? Well, sometimes Hyper-V will be used without an accompanying System Centre deployment, and if that’s the case, using WMI is your only scripting option.
I`ll be honest, using the WMI provider to script Hyper-V is unintuitive, complicated and feels quite clunky. So the question has to be asked “Why is the Hyper-V WMI provider so difficult to use?” The answer is Industry Standards. The virtualization WMI provider fully complies with the standards outlined by the Distributed Management Task Force (DMTF). Whilst standards are great for creating consistency among different vendors, there are often comprises with the simplicity of individual solutions. Contrastingly the SCVMM cmdlets are a bespoke solution designed by Microsoft to be simple, intuitive and powerful, but do not adhere to any industry standards.
So, with the expectation that the Hyper-V WMI journey will be a challenging one, let’s get on with it.
WMI Basics
As mentioned we will be using the virtualization WMI provider, and before going any further I would strongly recommend that you spend some time understanding WMI to a reasonable depth. If you can answer the following questions, you’re probably familiar enough with WMI to get the most out of this tutorial:
1. What is namespace?
2. What is a class?
3. How do you create a WMI Object in PowerShell?
Basic WMI information is out of scope for this tutorial, so if you can’t answer the above questions, before continuing I would suggest the following pre-reading/viewing:
1. Brief WMI Intro on Technet Edge - http://edge.technet.com/Media/Powershell-tips-and-tricks-from-the-field-with-Ben-Pearce
2. Windows, PowerShell and WMI – Tech Ed 2008 Session http://www.microsoft.com/emea/spotlight/sessionh.aspx?videoid=996
3. Microsoft Windows PowerShell Step by Step Book- http://www.microsoft.com/MSPress/books/10329.aspx
Hyper-V + WMI
There are 2 key points you need to understand to start using the Hyper-V WMI provider.
1. All Hyper-V classes live in the “Virtualization” namespace. Therefore whenever you want to instantiate an object you need to specify this namespace. The following sample lists all the classes available in this namespace:
|
Get-WMIObject –namespace “root\virtualization” -list |
2. PowerShell must be elevated and running as an administrator. If you run PowerShell in a non-administrative context you will not be able to connect to any guests, and will only be able to affect the host. In Server 2008 you need to right-click the PowerShell icon, then click “Run As Administrator” to achieve this, even if logged on as an administrator.
VMStateQuery
Often, I find the best way to learn something is with a worked example. Attached to this post is VMStateQuery.ps1, which is an example PowerShell script which can be used to determine the state of guests deployed to a Hyper-V host. The script can be used to return the state of all guests on a host, or the state of 1 particular guest.
Usage
This returns a list of all guests and their state, sorted alphabetically.
|
.\VMStateQuery.ps1 -vhost myremotehost -sortbystate |
This returns a list of all the guests on MyRemoteHost, and sorts the guests by state.
|
.\VMStateQuery.ps1 –vhost myremotehost –vguest MyGuest1 |
This returns the state of the guest MyGuest1, running on the host MyRemoteHost.
Explanation
Let’s dig into some interesting parts of this script.
The only time we use WMI in this example is in this 1 line:
|
$vms = Get-WMIObject -Class Msvm_ComputerSystem -Namespace "root\virtualization" -ComputerName $vhost |
This line connects using WMI and retrieves all instances of MSVM_ComputerSystem on the computer specified by $VHost. This line returns an array of all guests and the host, each one represented by an object. In order to find out what we can with this object type we can do two things. Firstly, use Get-Member to obtain all properties and methods, or use this MSDN link, which details each property and method.
Having looked at the properties of this object we can see 2 properties that will be particularly useful when trying to query a guest’s state: elementname and enabledstate. ElementName is the name of the guest that you see in the Hyper-V MMC console, and enabledstate is a number that represents the state of the machine.
This bit of code filters our array of guests, and returns any that match the following
|
$vms = $vms | where-object {$_.elementname -eq $vguest} |
We simply use where-object to filter, such that only guests whose elementname equals $vguest are retained.
We use the enabledstate property to identify the state of the machine. However, the state of the machine is a number which might not make too much sense. Therefore I’ve created a function called ConvertStateToFriendly which simply uses a switch statement to return a friendly word for the state. The call to this function is nested as an expression that can be used by the format-table cmdlet to display the information nicely. Here’s the code:
|
$statefriendly = @{Expression={convertStateToFriendly $_.enabledstate};Label="State";width=25}
$vms | format-table Elementname, $statefriendly |
This code looks a little bid nasty, but is simply a way of creating custom tables. More details on how this mechanism works can be found here.
One final part I want to explain is this line:
|
$vms = $vms | where-object{$_.caption -ne "Hosting Computer System"} |
When you get all instances of MSVM_ComputerSystem, one of the returned objects represents the host system. In this script I am not really interested in the state of the host, just the state of the guests. Therefore the above line simply looks at the caption property of the objects, and drops the object with the name “Hosting Computer System”.
All the rest of the script is generic PowerShell code, used for parameters, error checking and other useful bits and pieces.
Hyper-V WMI Resources
The two best resources for Hyper-V WMI scripting that I have come across so far are the MSDN page, and James O’Neil’s Hyper-V management library on CodePlex. The MSDN page is the definitive source on the WMI provider and is here:
http://msdn.microsoft.com/en-us/library/cc136992(VS.85).aspx
The Code Plex project which James uploaded is a pretty comprehensive library on managing Hyper-V and WMI. It’s an excellent source, but be warned it is pretty hardcore and very code efficient in places, which can sometimes be quite tricky to understand (maybe that’s just me J)
http://www.codeplex.com/PSHyperv
My colleague Richard Macdonald has written a very similar script, but using C# instead of PowerShell. Check out his blog here for the code.
Well that’s it for part 1. Stay tuned for Part 2 –Hyper-V Data Gathering.
Enjoy
BenP
Hi All
I got kidnapped by the Tech Net Edge guys whilst I was at Tech Ed the other week, and intereviewed about the PowerShell and WMI session that I was presenting there. If you'd like to see the interview in full it's here:
http://edge.technet.com/Media/Powershell-tips-and-tricks-from-the-field-with-Ben-Pearce/
You might need to use "the force" whilst watching the demos, as sadly some of the commands I was using were slightly off the screen.
Have fun
BenP
Hi All
Sometimes you just want a new Domain created quickly for a bit of testing. Given that Windows 2008 ships with server core, a light footprint version of the OS, it’s ideal for being the domain controller. As I am fairly inexperienced with Server Core I had to search all over the place to find information on how to go from a vanilla server core build, to a dc running a brand new domain. I figured out a set of commands that achieve this, so thought I would share them with the world.
Rename Host
Netdom renamecomputer <OldName> /NewName:<NewName>
Set IP
netsh int ip set address "Local Area Connection" static 192.168.0.210 255.255.255.0 192.168.0.1 1
Set DNS
Netsh interface ipv4 add dnsserver name=”<idxname>” address=<IP Address> index = 1
Install DNS Role
start /w ocsetup DNS-Server-Core-Role
Create New Domain
dcpromo /unattend:c:\unattend.txt
Unattend.txt Contents
[DCINSTALL]
AutoConfigDNS=Yes
DomainNetBiosName=benpdom
NewDomainDNSName=benpdom.com
ReplicaOrNewDomain=Domain
NewDomain=Forest
ForestLevel=3
DomainLevel=3
SafeModeAdminPassword=Password1234
RebootOnSuccess=Yes
Another cool Server Core reference can be found on Mark’s blog here:
http://blogs.technet.com/mempson/archive/2008/03/19/server-core-quick-reference-guide.aspx
Hope this helps
Cheers
BenP
Finally, here is the last demo.
Demo 5 – Administering Failover Clustering
I have already written a detailed post, and a similar script on this subject, here. However, I promised all the demos would be on my blog, so attached is the exact script I used at Tech Ed 2008.
Enjoy!
BenP
So here is Demo 4 – Administering Hyper-V
I am planning to put more posts on my blog, looking at this subject in more depth, so stay tuned for more in depth demos. This was is what I demo’d at Tech Ed 2008. Notice the namespace that is used:
|
Gwmi –namespace “root\virtualization” –list
Gwmi –namespace “root\virtualization” –class msvm_computersystem | get-member
Gwmi –namespace “root\virtualization” –class msvm_computersystem | format-table elementname, enabledstate
|
Thanks
BenP
Ola
Demo 3 – How Do I Know Which Classes to Use
In this demo I firstly used WMI Browser, which provides a GUI that can be used to visually display WMI information. That can be downloaded from here:
I then browsed for classes in PowerShell. I have already documented this on my blog and it can be found here:
Phew, that was a short post.
Enjoy!
BenP
Bonjour Bonjour
It’s time for Demo 2 – Administering Servers in Bulk. I’ve attached the 4 scripts that I used.
Demo 2 – Administering Servers in Bulk
BulkServers1.ps1 – This script reads in a text file, containing 1 server per line. It simply then writes the server names back to the console
BulkServers2.ps1 – This script extends the first script and simply gets the hostname, operating system and service pack level for each server listed in the input file.
BulkServers3.ps1 – This script gets a little bit more complex and in fact is rather exciting. It again reads an input file and for each server, gets operating system information, bios information, writes this to a CSV file and then opens the csv file in your default CSV file handler.
BulkServers4.ps1 – The piece de resistance! This script is very similar to the above script, except that rather than read an input file with server names, it connects to the Domain Controller container in the Active Directory, and gets information from all computers in that container.
Please note, there is no error checking in these scripts, and are purely working illustrations. I would flesh these scripts out a bit more before I used them in anything other than a test infrastructure.
All done, stay tuned for Demo 3 – How Do I Know Which Classes to Use
That is all.
BenP
Hello Again
Well I’ve delivered my session “Windows, PowerShell and WMI: Unveiling Microsoft’s Best Kept Secret”, and as promised here are the scripts for the Demo’s I used during my session:
Demo 1 – Administering Windows
All these demos are simple command lines that I just typed straight in PowerShell, no need for any fancy scripts.
Basics
The following lines of code show help on how to use the Get-WMIObject cmdlet in PowerShell, how to list all classes in the cimv2 namespace and finally how to use some basic parameters.
|
Get-Help -name Get-WMIObject
Get-Help -name Get-WMIObject –det
get-wmiobject -namespace "root\cimv2" –list
Gwmi -namespace "root\cimv2" –list
Gwmi -namespace "root\cimv2" -class Win32_LogicalDisk
Gwmi -class Win32_LogicalDisk
Gwmi Win32_LogicalDisk
Gwmi Win32_LogicalDisk –computername localhost
$cred = get-credentials
Gwmi Win32_LogicalDisk –credential $cred |
Disks
These lines of code show how to get disk information from a system, identify all the properties and methods of the disk objects that can be used, then uses some properties.
|
Gwmi Win32_LogicalDisk | Get-Member
$disks = gwmi Win32_LogicalDisk –computername localhost
$disks[0].freespace
$disks[0].freespace/1gb
$disks[0].filesystem |
Hotfixes
These lines connect to a system and list all the Hotfixes that have been installed.
|
$hotfixes = gwmi Win32_QuickFixEngineering –computername localhost
$hotfixes | get-member
$hotfixes | format-table Hotfixid |
OperatingSystem
These lines enumerate basic operating system information: the OS version, service pack level and OS architecture type.
|
$os = gwmi win32_OperatingSystem -computername Serverxxx
$os | get-member
$os | format-list caption, CSDVersion,OSArchitecture |
Network Adapter
The following lines modify the IP Address and Subnet Mask of a network adapter using the EnableStatic method.
|
$nics = Gwmi win32_NetworkAdapterConfiguration
$nic = $nics | where{$_.description –like “*XXXXXXXXXXXX*”}
$IPAddress = x.x.x.x
$subnetmask = x.x.x.x
$nic.EnableStatic($IPAddress, $SubnetMask) |
Well that’s the first demo stay tuned for Demo 2 – Administering Servers in Bulk.
Enjoy!
BenP
Ladies and Gents
Many months ago I posted a script on how to search a namespace for different classes. The post is here
A common question I then get asked is “How do I know what WMI namespaces are installed on a system?” The answer is not immediately obvious so I thought I’d share it with you all.
|
Get-WMIObject -class __Namespace -namespace root | Format-Table name
|
I get the following output from my Vista RTM machine.
|
name
----
subscription
DEFAULT
MicrosoftDfs
CIMV2
Cli
Nap
SECURITY
SmsDm
RSOP
ccm
WMI
directory
Policy
ServiceModel
SecurityCenter
MSAPPS12
Microsoft
Aspnet |
So by searching the host for a list of namespaces, and then searching each namespace for the classes available you can find some really useful stuff.
Hope this helps
BenP
Hi All
Some of you may of heard about this already, but it's recently been announced that PowerShell will be in the Microsoft Common Engineering Criteria for 2009.
What is the Common Engineering Criteria?
The Common Engineering Criteria is a set of criteria that each Microsoft server product should adhere to. The criteria was set up in 2005 and has been updated each year with a new set of requirements. The word on the street is that in 2009, PowerShell support will be added to this list, meaning that from 2009 all server products that are released should have full PowerShell support. Wahoo!
For more details on the Common Engineering Criteria check out the homepage: http://www.microsoft.com/windowsserversystem/cer/allcriteria.mspx
For a checklist of the current criteria, and a report on which products implement them, check out this link: http://www.microsoft.com/windowsserversystem/cer/report.mspx
So to all those that haven't learnt PowerShell yet ... it is time. PowerShell is not going away!
Cheers all
BenP
Hi All
I had the pleasure of presenting a joint session at the PowerShell UK User Group this week. I presented a joint session with Jeremy Peck from HP on an Introduction to SCVMM and scripting it with PowerShell. I have attached my slide deck from the first half of the session. In order to see Jeremy's deck with PowerShell examples, and the other sessions that were presented at the event please see the links on the Get-PSUGUK homepage (if they are not there yet Richard Siddaway should have them up soon)
http://www.culminisconnections.com/sites/get-psuguk/default.aspx
Enjoy
BenP
Hello Everybody
Sorry for the huge delay in posting anything, I promise I will never leave it so long again.
I got asked a question the other day. Can I use Get-EventLog to access all the new logs that are in Vista?
Which logs am I referring to you may ask. Well, there are loads of new logs that can provide a massive set of troubleshooting information. Here's a screen shot from my Vista laptop that shows some of the logs:
So the question is can I query the Backup, Bits-Client, DiskDiagnostic and all the other logs using the Get-Eventlog cmdlet.
In short no. You can however still use PowerShell, but you need to use a command line tool that ships in Vista, wevtutil.exe. You can find out all the logs that can be accessed using Get-Eventlog with the -list parameter.
PS C:\Users\benp> Get-EventLog -list
Max(K) Retain OverflowAction Entries Name
------ ------ -------------- ------- ----
15,168 0 OverwriteAsNeeded 1,381 Application
15,168 0 OverwriteAsNeeded 0 DFS Replication
20,480 0 OverwriteAsNeeded 0 Hardware Events
512 7 OverwriteOlder 0 Internet Explorer
512 7 OverwriteOlder 0 Key Management Service
8,192 0 OverwriteAsNeeded 0 Media Center
16,384 0 OverwriteAsNeeded 0 Microsoft Office Diagnostics
16,384 0 OverwriteAsNeeded 29 Microsoft Office Sessions
15,168 0 OverwriteAsNeeded 4,109 System
15,360 0 OverwriteAsNeeded 40 Windows PowerShell
All of the above logs are part of the standard Windows Event Log. However, all of the the other logs in the screenshot use Windows Eventing 6.0. Get-EventLog does not hook into Windows Eventing 6.0.
So how can I get at these logs using PowerShell? Check out the sample below:
PS C:\Users\benp> wevtutil.exe qe Microsoft-Windows-UAC/Operational /c:2 /f:text
Event[0]:
Log Name: Microsoft-Windows-UAC/Operational
Source: Microsoft-Windows-UAC
Date: 2007-10-30T11:14:00.524
Event ID: 1
Task: N/A
Level: Error
Opcode: Info
Keyword: N/A
User: S-1-5-21-1721234763-462695806-1538865281-2692397
User Name: testdom\benp
Computer: vista.test.microsoft.com
Description:
The process failed to handle ERROR_ELEVATION_REQUIRED during the creation of a child process.
This sample connects to the UAC Operational log and displays the newest 2 items as text. (There is only 1 event listed, because I only have 1 entry in the log).
So yes I can access these logs using PowerShell, but no I can't use the Get-EventLog cmdlet to do it. Check out the following link for detailed syntax for using wevtutil.exe
http://technet2.microsoft.com/windowsserver2008/en/library/d4c791e0-7e59-45c5-aa55-0223b77a48221033.mspx?mfr=true
Thanks to Narayanan Lakshmanan for answering the many questions I had about this.
That is all
BenP
Hello
I hate writing up scripts. Writing the scripts themselves is great, it’s just explaining them after which is really boring J
Here is the second demo script I used last week, Create-ChildVM.ps1. This script is invaluable if you need to quickly deploy machines in a test lab. I say test lab rather than production because this script uses differencing disks, which do not perform as well as fixed disk. They are great to use when you have disk space constraints, but on a beefy production system I would use fixed disks. A differencing disk has a read-only parent disk which can be used to store the operating system. Then any changes made to the disk are actually stored in the differencing disk. In this example my parent disk is a Windows 2003 SP2 sysprepped disk. The child then holds any differences. Multiple children can point to the same parent and parent disks can be chained together.
This script takes no parameters, and provides a menu system. The VM is created in seconds and the machine is up running in a matter of minutes.
I won’t explain the whole script, but just shout if you have any questions. There is no error checking in this script. Version 2 will have some error checking built in – I promise J
Thanks go to Steven Adler who's code I plagiarised for some (most) of the sections.
Cheers
BenP
Hello Everyone
As promised, attached is the first fo the demo scripts that I used at the “Scripting Virtual Server with PowerShell” session I ran. I`m not going to go through the whole script but here is an over view and bit more detail on a few key sections.
Script Synopsis
CAP-ISO.ps1 stands for CreateAndPresent-ISO.ps1. This script can be used to create an ISO file comprising of a given set of files. This iso is then presented to a guest VM. I find this particularly useful to run on my laptop with Virtual Server installed. Essentially this is a quick way of getting files from a host to a guest without having to worry about the network setup.
Interesting Bits
I should probably give this section a more descriptive title, but you get the idea. Here’s some of the more interesting sections of the script.
Firstly, this script just wraps around an existing command line tool to create the ISO. This tool is called OSCDIMG.EXE and ships with the Windows Automated Installation Kit (WAIK). You will need to download the tool, and modify the script to point to its install location. The WAIK can be downloaded here: http://www.microsoft.com/downloads/details.aspx?familyid=C7D4BC6D-15F3-4284-9123-679830D629F2&displaylang=en
Let’s look at some code. I don’t want to duplicate what Virtual PC Guy, Ben Armstrong has already written so for a basic guide to scripting Virtual Server with PowerShell go here: http://blogs.msdn.com/virtual_pc_guy/archive/2006/06/13/630165.aspx
So, as Ben Armstrong discussed, you must first have the dll somewhere on the system, and then must reference it from the script. You also need to be running as admin (and elevated if in Vista). Here is how to reference the dll.
|
$result = [System.Reflection.Assembly]::LoadFrom(“$profdir\VSWrapperForPSH.dll”) |
$profdir is a variable I have created in my profile that points the variable to my profile directory.
I then create a Virtual Server Com Instance like this:
|
$vs = new-object -com VirtualServer.Application -Strict |
The next essential part is to set the security on the object. I do this using a function called setsecurity which can be called anytime. Here’s the function and an example call to it:
|
function setsecurity($Object)
{
$result = [Microsoft.VirtualServer.Interop.PowerShell]::SetSecurity($Object)
}
$result = SetSecurity $VS |
I then have to call this function every time I create a new Virtual Server based object. Whether it’s a VM object, DVD Drive, Hard Disk or any other object I have to set the security once I have created the object.
Have a look through the script and if you have any questions, just post them in the comment section.
For more information on scripting Virtual Server with PowerShell check out Ben Armstrong’s most excellent book, Professional Microsoft Virtual Server 2005, Wrox Publishing. Check out Ben’s blog for more information on the book:
http://mumblingtomyself.spaces.live.com/blog/cns!64FFB030F5637A64!128.entry
Enjoy!
BenP
Bonjour Bonjour
Last night I was kindly invited to speak at the PowerShell UK User Group meeting. The subject I delivered was "Scripting Virtual Server with PowerShell". I was asked if I could post my slide deck, so here it is in both pptx and ppt format (I got burned for using just the new office format before :) )
The slide deck is not very verbose, so might not make the most sense if you didn't attend the session, but could still be useful. I will publish the demo scripts that I used somtime next week. I just need to clean them up a little bit before I show them to the world.
Enjoy
Ben