Monday, January 30, 2012

Getting convert VHD jobs per VM from SCVMM 2012

I have been running some tests recently and one of the things that was brought into question is if a disk conversion job is taking longer to run as the number of VMs increases in the environment.

Now, you might think this is relatively easy.  Just issue a query with Get-SCJob and filter.

Well, I did begin that way, thinking I would get just what I wanted.

Get-SCJob | where { $_.Name -eq "convert virtual hard disk" } | where { $_.Status -eq "Completed" }

But I never got the right number of VHD conversion jobs returned back.  This obviously needed more complex scripting.

So, I tried using Get-SCVirtualDiskDrive   That cmdlet requires a VM object to be tossed in, I can’t just get a list of all the VHD like I could through a CIM call to a hypervisor.

Now I have to go to the VM level.  I have to query for the VMs, then find each virtual disk, then get the most recent job object on that virtual disk.

$scVMs = Get-SCVirtualMachine | where {$_.Name -match "Xd1K"}

In a long hand way that looks like this:

Foreach ($scVM in $scVMs){
    $vmVhd = Get-SCVirtualDiskDrive -VM $scVM | where {$_.MostRecentTask -match "convert"} 
    $vhdJob = $vmVhd.MostRecentTask
    $vhdConvertJobs += [Microsoft.SystemCenter.VirtualMachineManager.Task]$vhdJob
}

Take notice of that object cast; [Microsoft.SystemCenter.VirtualMachineManager.Task].  If you don’t do this you get an error that the Task cannot be converted to int32.  Don’t ask me why PowerShell is trying to convert the Task object into an integer, but that is what the default is trying to do.

In a nice tight shorthand way it looks like this:

Foreach ($scVM in $scVMs){
    $vhdConvertJobs += [Microsoft.SystemCenter.VirtualMachineManager.Task]( Get-SCVirtualDiskDrive -VM $scVM | where {$_.MostRecentTask -match "convert"} ).MostRecentTask
}

Next time, calculating the average time to execute the jobs, and making it useful to quickly check.

Friday, January 27, 2012

Traversing time with PowerShell

My first title for this was “the PowerShell time machine” because the article is about TimeSpan and managing time using TimeSpan.

Most folks are familiar with Get-Date.  Get-Date is all about ‘now’ – it is always now. 

Which is great, if you are running a script and want to know at some point in the script what the time is ‘now’, such as before entering a loop of some type.

Frequently I need to calculate the difference between then and now.  Or the difference between then and then.  This is where the TimeSpan comes into play.

My current project involves trudging through entries in a log file and finding a start time for a series of steps, and then the end time for the series of steps.  The whole point is that I need to know how long the series of steps took so that we can see if we made it any faster.

I don’t know about you but I have a hard time with determining the minutes in between 09:54:53 and 14:13:33.  That isn’t something I can look at and do in my head.

This is not the most elegant script and I know it can be improved.  However, this is where I began taking basic keyboard text entry and turning it into time.

If you run the script it asks you for the start time, entering HH, then MM, then SS.  Then the end time, again. HH, then MM, then SS.  Then it calculates the difference.


do {
    Clear-Host
   
    $startTime = New-TimeSpan -Hours (read-host -prompt "Enter Start hour HH") -Minutes (read-host -prompt "Enter Start minutes MM") -Seconds (read-host -prompt "Enter Start seconds SS")

    $endTime = New-TimeSpan -Hours (read-host -prompt "Enter End hour HH") -Minutes (read-host -prompt "Enter End minutes MM") -Seconds (read-host -prompt "Enter End seconds SS")

    $timeToExecute = $endTime - $startTime

    ""
    "   The task took: _" + $timeToExecute.TotalMinutes + "_ minutes"
    ""
   
    $quit = Read-Host -Prompt "press Enter to continue or 00 Enter to quit"
   
    Clear-Variable -Name startTime
    Clear-Variable -Name endTime

   
} until ($quit -eq "00")

Tuesday, January 17, 2012

psbase.gettext(1) I love you

I have had many cases to do things in PowerShell where I am manipulating CIM or WMI objects.
Getting CIM/WMI objects and querying information from them is never a big deal, however modifying an object and then trying to send it back to a method to cause some setting change has always been a pain.
When you get a CIM/WMI object with PowerShell, PowerShell treats it as an object, where in actuality it is XML.  It is a representation of am object.  It has a path and properties.
Over time I have treated this all kinds of ways to get it to format properly for the receiving CIM/WMI.
You can deal with it as InnerText, you can convert it to XML, you can deal with is as a complex string @” <stuff in there with intact formatting> ”@
When PowerShell sees the WMI as an object you can manipulate it in an easy object type of way.  But you can’t send it back to a WMI method.
When PowerShell sees the CIM as a string, you can manipulate it in a painful way, but you can easily send it back to a CIM method.
As a consumer who uses both Windows CIM (WMI) and Linux CIM (CIM) this is a royal pain.  Especially when PowerShell automatic object handling does not recognize the return properly (which I have had happen with CIM lots of times).  Now, I know that PowerShell 3 (in the Win8 Developer Preview) will make this all much better, but I am not there yet.
Lets just take a quick look at the object and return.
When you perform a query against WMI you get a single object or an array of objects back.  But PowerShell treats them like objects.  You can “.” the properties and methods.  This is powerful.
PS C:\Users\Public\Documents\> $vsmssd

__GENUS                    : 2
__CLASS                    : Msvm_VirtualSystemManagementServiceSettingData
__SUPERCLASS               : CIM_SettingData
__DYNASTY                  : CIM_ManagedElement
__RELPATH                  : Msvm_VirtualSystemManagementServiceSettingData.InstanceID="Microsoft:BJEDAR2"
__PROPERTY_COUNT           : 13
__DERIVATION               : {CIM_SettingData, CIM_ManagedElement}
__SERVER                   : BJEDAR2
__NAMESPACE                : root\virtualization
__PATH                     : \\BJEDAR2\root\virtualization:Msvm_VirtualSystemManagementServiceSettingData.InstanceID="Microsoft:BJEDAR2"
BiosLockString             :
Caption                    : Hyper-V Virtual System Management Service
DefaultExternalDataRoot    : C:\Users\Public\VMs\
DefaultVirtualHardDiskPath : C:\Users\Public\VMs\
Description                : Settings for the Virtual System Management Service
ElementName                : Hyper-V Virtual System Management Service
InstanceID                 : Microsoft:BJEDAR2
MaximumMacAddress          : 00155D748DFF
MinimumMacAddress          : 00155D680A00
NumaSpanningEnabled        : True
PrimaryOwnerContact        :
PrimaryOwnerName           : Administrators
ScopeOfResidence           :
But when I modify that object and send it back to the WMI provider I need to adhere to the CIM standard and I cannot just send back $vsmssd.   That is where this little, wonderful, psbase.gettext method comes into play.  Lets take this object and turn it back into its CIM text so that I can send it back to the WMI provider.
When I type that out to the screen I get something very different, not an object, but useful for sending the message.
PS C:\Users\Public\Documents\> $vsmssd.psbase.gettext(1)
<INSTANCE CLASSNAME="Msvm_VirtualSystemManagementServiceSettingData"><QUALIFIER NAME="dynamic" PROPAGATED="true" TYPE="boolean" TOSUBCLASS="false" TOINSTANCE="true"><VALUE>TRUE</VALU
E></QUALIFIER><PROPERTY NAME="__PATH" CLASSORIGIN="___SYSTEM" TYPE="string"><VALUE>\\BJEDAR2\root\virtualization:Msvm_VirtualSystemManagementServiceSettingData.InstanceID="Microsoft:
BJEDAR2"</VALUE></PROPERTY><PROPERTY NAME="__NAMESPACE" CLASSORIGIN="___SYSTEM" TYPE="string"><VALUE>root\virtualization</VALUE></PROPERTY><PROPERTY NAME="__SERVER" CLASSORIGIN="___S
YSTEM" TYPE="string"><VALUE>BJEDAR2</VALUE></PROPERTY><PROPERTY.ARRAY NAME="__DERIVATION" CLASSORIGIN="___SYSTEM" TYPE="string"><VALUE.ARRAY><VALUE>CIM_SettingData</VALUE><VALUE>CIM_
ManagedElement</VALUE></VALUE.ARRAY></PROPERTY.ARRAY><PROPERTY NAME="__PROPERTY_COUNT" CLASSORIGIN="___SYSTEM" TYPE="sint32"><VALUE>13</VALUE></PROPERTY><PROPERTY NAME="__RELPATH" CL
ASSORIGIN="___SYSTEM" TYPE="string"><VALUE>Msvm_VirtualSystemManagementServiceSettingData.InstanceID="Microsoft:BJEDAR2"</VALUE></PROPERTY><PROPERTY NAME="__DYNASTY" CLASSORIGIN="___
SYSTEM" TYPE="string"><VALUE>CIM_ManagedElement</VALUE></PROPERTY><PROPERTY NAME="__SUPERCLASS" CLASSORIGIN="___SYSTEM" TYPE="string"><VALUE>CIM_SettingData</VALUE></PROPERTY><PROPER
TY NAME="__CLASS" CLASSORIGIN="___SYSTEM" TYPE="string"><VALUE>Msvm_VirtualSystemManagementServiceSettingData</VALUE></PROPERTY><PROPERTY NAME="__GENUS" CLASSORIGIN="___SYSTEM" TYPE=
"sint32"><VALUE>2</VALUE></PROPERTY><PROPERTY NAME="BiosLockString" CLASSORIGIN="Msvm_VirtualSystemManagementServiceSettingData" TYPE="string"><QUALIFIER NAME="CIMTYPE" PROPAGATED="t
rue" TYPE="string" TOINSTANCE="true"><VALUE>string</VALUE></QUALIFIER></PROPERTY><PROPERTY NAME="Caption" CLASSORIGIN="CIM_ManagedElement" TYPE="string"><QUALIFIER NAME="CIMTYPE" PRO
PAGATED="true" TYPE="string" TOINSTANCE="true"><VALUE>string</VALUE></QUALIFIER><VALUE>Hyper-V Virtual System Management Service</VALUE></PROPERTY><PROPERTY NAME="DefaultExternalData
Root" CLASSORIGIN="Msvm_VirtualSystemManagementServiceSettingData" TYPE="string"><QUALIFIER NAME="CIMTYPE" PROPAGATED="true" TYPE="string" TOINSTANCE="true"><VALUE>string</VALUE></QU
ALIFIER><VALUE>C:\Users\Public\VMs\</VALUE></PROPERTY><PROPERTY NAME="DefaultVirtualHardDiskPath" CLASSORIGIN="Msvm_VirtualSystemManagementServiceSettingData" TYPE="string"><QUALIFIE
R NAME="CIMTYPE" PROPAGATED="true" TYPE="string" TOINSTANCE="true"><VALUE>string</VALUE></QUALIFIER><VALUE>C:\Users\Public\VMs\</VALUE></PROPERTY><PROPERTY NAME="Description" CLASSOR
IGIN="CIM_ManagedElement" TYPE="string"><QUALIFIER NAME="CIMTYPE" PROPAGATED="true" TYPE="string" TOINSTANCE="true"><VALUE>string</VALUE></QUALIFIER><VALUE>Settings for the Virtual S
ystem Management Service</VALUE></PROPERTY><PROPERTY NAME="ElementName" CLASSORIGIN="CIM_ManagedElement" TYPE="string"><QUALIFIER NAME="CIMTYPE" PROPAGATED="true" TYPE="string" TOINS
TANCE="true"><VALUE>string</VALUE></QUALIFIER><VALUE>Hyper-V Virtual System Management Service</VALUE></PROPERTY><PROPERTY NAME="InstanceID" CLASSORIGIN="CIM_SettingData" TYPE="strin
g"><QUALIFIER NAME="CIMTYPE" PROPAGATED="true" TYPE="string" TOINSTANCE="true"><VALUE>string</VALUE></QUALIFIER><QUALIFIER NAME="key" PROPAGATED="true" TYPE="boolean" OVERRIDABLE="fa
lse" TOINSTANCE="true"><VALUE>TRUE</VALUE></QUALIFIER><VALUE>Microsoft:BJEDAR2</VALUE></PROPERTY><PROPERTY NAME="MaximumMacAddress" CLASSORIGIN="Msvm_VirtualSystemManagementServiceSe
ttingData" TYPE="string"><QUALIFIER NAME="CIMTYPE" PROPAGATED="true" TYPE="string" TOINSTANCE="true"><VALUE>string</VALUE></QUALIFIER><VALUE>00155D748DFF</VALUE></PROPERTY><PROPERTY
NAME="MinimumMacAddress" CLASSORIGIN="Msvm_VirtualSystemManagementServiceSettingData" TYPE="string"><QUALIFIER NAME="CIMTYPE" PROPAGATED="true" TYPE="string" TOINSTANCE="true"><VALUE
>string</VALUE></QUALIFIER><VALUE>00155D680A00</VALUE></PROPERTY><PROPERTY NAME="NumaSpanningEnabled" CLASSORIGIN="Msvm_VirtualSystemManagementServiceSettingData" TYPE="boolean"><QUA
LIFIER NAME="CIMTYPE" PROPAGATED="true" TYPE="string" TOINSTANCE="true"><VALUE>boolean</VALUE></QUALIFIER><VALUE>TRUE</VALUE></PROPERTY><PROPERTY NAME="PrimaryOwnerContact" CLASSORIG
IN="Msvm_VirtualSystemManagementServiceSettingData" TYPE="string"><QUALIFIER NAME="CIMTYPE" PROPAGATED="true" TYPE="string" TOINSTANCE="true"><VALUE>string</VALUE></QUALIFIER><VALUE>
</VALUE></PROPERTY><PROPERTY NAME="PrimaryOwnerName" CLASSORIGIN="Msvm_VirtualSystemManagementServiceSettingData" TYPE="string"><QUALIFIER NAME="CIMTYPE" PROPAGATED="true" TYPE="stri
ng" TOINSTANCE="true"><VALUE>string</VALUE></QUALIFIER><VALUE>Administrators</VALUE></PROPERTY><PROPERTY NAME="ScopeOfResidence" CLASSORIGIN="Msvm_VirtualSystemManagementServiceSetti
ngData" TYPE="string"><QUALIFIER NAME="CIMTYPE" PROPAGATED="true" TYPE="string" TOINSTANCE="true"><VALUE>string</VALUE></QUALIFIER></PROPERTY></INSTANCE>
The actual object is the same thing, in spite of this last looking like a bunch of XML.
If you try to manipulate CIM from a Linux provider with PowerShell you will see lots of this type of output and dealing with it properly is the pain.
Just thought I would share.  Eventually I will get back to Linux CIM interfaces, but I hope I can wait until PowerShell 3 comes out, with handling for CIM, not just WMI.

Monday, December 19, 2011

Ubuntu Desktop 10.11 on Hyper-V piix4_smbus

So, I needed a small virtual machine that had the Hyper-V Integration Components working it (I need the clean shutdown action).

XP is just too large, but usually works well.  Linux, why not.  And the RedHat family just incorporated the latest of the Hyper-V Linux Integration Components.  Perfect.

Now, the flavor.  RedHat?  No, no license.  Fedora? Well, now that I think of it, I forgot this one before.  CentOS?  Great for a server.  Ubuntu.  Yep, I chose Ubuntu.

I created a VM and installed Ubuntu Server without a hitch.  Just be sure to use a Legacy Network Adapter during the install process.

I then created a VM and tried to install Ubuntu Desktop.  Big fail.
First of all, for the life of me I could not get the installer screen to popup.  I could not figure out what was going on.  After all, the server VM went straight to the language selection.

Well, at the bottom of the screen is this cryptic graphic of a keyboard, and equal sign, and what looks to be a person with arms and legs spread.  After a few reboots I interpreted this symbol to mean; “if you want to install, hit enter now”.
Hey, the language selection pops up!

Now, I select my language and hit enter.  Error message, drop to a prompt.  Fail two.

The error:  piix4_smbus 0000:07.3: SMBus base address uninitialized – upgrade BIOS or use force_addr=0xaddr

I only play a Linux guy on TV.  And a bit of searching showed me that this error is common on VirtualBox and the settings change suggested is not a safe thing to try.  Oh, and that I needed to re-compile my initrd.

This is a brand new build and freshly downloaded media.  Crazy talk!

Well, I looked around and figured out a workaround.
I managed to get the installer to load by selecting the “other options” at the installation selection menu (F6) and setting “acpi=off” (highlight it, enter or spacebar, ESC to close the options dialog).

Oh, and a nice feature, on the Windows 8 Developer Preview I actually had a mouse during the GUI installer of Ubuntu Desktop.

Now, enabling the Integration Components..

I did just a couple things.  Bring up a terminal using “Ctrl + Alt + t”
Then you need to do sudo –i to switch to root for the remainder of the session or type sudo at the beginning on each command.

Using nano (I never got any handle on vi and always have fallen back to nano) added 4 lines in /etc/initramfs-tools/modules  ( “nano /etc/initramfs-tools/modules” ) and add:
hv_vmbus
hv_storvsc
hv_blkvsc
hv_netvsc

Save that.  Then generate an updated initramfs with “update-initramfs –u” and reboot.

If you had rebooted prior to this you may have noticed a storage layer inaccessibility error that is now gone.

I then ran “apt-get update” and “apt-get upgrade” – two hours go by…Not necessary, but it does update all packages.

This entire time I have been using a Legacy Network Adapter with the Ubuntu Desktop VM.  After the update completed I shutdown the VM, removed the Legacy Network Adapter, added a (synthetic) Network Adapter and all was good.

Friday, December 16, 2011

Provisioning Server (PVS) Cache on device issues

I recently ran into some issues streaming VMs and taking advantage of the local storage on the hypervisors for the local cache.

Many of these issues were due to my lack of experience with the product, so I am making notes here for future use.

First, if you are not familiar with Provisioning Server or have not taken a look at it for a few revisions, go download the latest version.  There have been a lot of improvements since the last time I looked at it (a few years ago). 

Cache on Device Hard Drive is actually from the PVS feature to stream to bare metal.  In the VM world it allows me to use local storage that is relatively inexpensive (unless you use SSDs – but hey, just another possibility) and just fine when you don’t want to persist the cache disk.

Okay, enough of that, back to my cache disk issue notes.
Firstly, when you create your Template VM, be sure to create the local cache disk as its local drive.

Secondly, don’t forget to format this disk for your streamed OS.  So, for Windows, format it NTFS (I am just booting the VM that will be my template to WinPE and using DiskPart to avoid ACLs.)
Third, make that cache disk large enough.  This was my most perplexing puzzle and I fiddled for a couple days with this off and on.

When I booted the VM and login I would get this strange error message:  “Windows created a temporary paging file on your computer”

This issue is specific to using the Cache on Device setting when your vDisk is set to shared mode.  The root is that the default page file location cannot be written to as it is the shared vDisk image.  The ancillary detail is that the page file gets moved to the device cache disk which is some drive other than %system%.

So, I had my local cache, all formatted, as small as it thought it needed to be.  I booted my vDisk and the error.  I set the vDisk to private mode and fiddled around with paging file settings.  I went back to my template VM, booted in shared mode, no paging file. 

I searched and found all kinds of related errors; moving it off C:, using a SCSI attached VHD instead of IDE (I happen to be using XenServer so this was not it), ACLs on files within the VHD, also obscure errors where the programs are expecting specific folders to exist on the cache disk.  All of these are totally valid errors and entirely possible in their scenario, just not mine.

Very frustrating.  It was when I booted with the VM template in private mode with the cache disk attached and I attempted to move the page file that I got a useful error:  the destination is not large enough.

Duh!  My device cache disk (the virtual disk of the VM) was not large enough for the caching of temporary files AND the page file of the VM operating system.  So silly.

I went back and recreated my template VM, with a larger cache disk – taking into account any dynamic memory settings.

Once I made this larger VHD (formatted with Diskpart) and booted using private image mode with cache on device hard drive all was good.