Friday, October 23, 2009

Hyper-V Automation through scripts (Final Script)

Ok, so far we have created, modified, and added resources (memory, processor, disks, and network) to virtual machines.  Now, we want to take that information and build a complete virtual machine.

# Set up variables
$VHD = "f:\VHDs\win2k8.vhd"
$GuestVM = "Win2k8"
$Namespace = "root\virtualization"
$Computer = "HyperV"
$VHDSize = "10GB"
$VMSwitchName = "Hyper-V External Switch"
$VMSwitchPortName = "MyPort"
$VMNICAddress = "00155D9290FF"

$VMSvc = Get-WmiObject -class "Msvm_VirtualSystemManagementService" -namespace $Namespace -ComputerName $Computer
$VM = Get-WmiObject -Namespace $Namespace -ComputerName $Computer -Query "Select * From Msvm_ComputerSystem Where ElementName='$GuestVM'"
$VMSettingData = Get-WmiObject -Namespace $Namespace -Query "Associators of {$VM} Where ResultClass=Msvm_VirtualSystemSettingData AssocClass=Msvm_SettingsDefineState"

# Give the new virtual machine a name
$VMGlobalSettingClass = [WMIClass]"\\$Computer\root\virtualization:Msvm_VirtualSystemGlobalSettingData"

$NewVMGS = $VMGlobalSettingClass.psbase.CreateInstance()

while ($NewVMGS.psbase.Properties -eq $null) {}

$NewVMGS.psbase.Properties.Item("ElementName").value = $GuestVM

# Create  a virtual disk
$VMDiskSvc = Get-WmiObject -Class "Msvm_ImageManagementService" -Namespace "root\virtualization"

$DiskCreate = $VMDiskSvc.CreateFixedVirtualHardDisk($VHD, 10GB)
$DiskJob = [WMI]$DiskCreate.job

while (($DiskJob.JobState -eq "2") -or ($DiskJob.JobState -eq "3") -or ($DiskJob.JobState -eq "4")) {Start-Sleep -m 100 $DiskJob = [WMI]$DiskCreate.job}

#Create memory resource
$VMMem = (Get-WmiObject -Namespace $Namespace -Query "Associators of {$VMSettingData} Where ResultClass = Msvm_VirtualSystemSettingDataComponent" | where-object -FilterScript {$_.ResourceSubType -eq "Microsoft Virtual Machine Memory"})

$VMMem.VirtualQuantity = [string]2048
$VMMem.Reservation = [string]2048
$VMMem.Limit = [string]2048

# Create processor resource
$VMProc = (Get-WmiObject -Namespace $Namespace -Query "Associators of {$VMSettingData} Where ResultClass = Msvm_ProcessorSettingData" | where-object -FilterScript {$_.ResourceSubType -eq "Microsoft Processor"})

$VMProc.VirtualQuantity = [string]1
$VMProc.Reservation = [string]0
$VMProc.Limit = [string]100000
$VMProc.Weight = [string]100

# Create network interface
$DefaultNet = Get-WmiObject -Namespace $Namespace -Class Msvm_SyntheticEthernetPortSettingData | Where-Object -FilterScript {$_.InstanceID -like "*Default*"}

$GUID1 = [GUID]::NewGUID().ToString()
$GUID2 = [GUID]::NewGUID().ToString()

$VMSwitchQuery = Get-WmiObject -Class "Msvm_VirtualSwitchManagementService" -Namespace $Namespace

# $VMSvc = Get-WmiObject -Class "Msvm_VirtualSystemManagementService" -namespace $Namespace -ComputerName $Computer

$VMSwitch = Get-WmiObject -Namespace $Namespace -Query "Select * From Msvm_VirtualSwitch Where ElementName = '$VMSwitchName'"

$ReturnObject = $VMSwitchQuery.CreateSwitchPort($VMSwitch, [guid]::NewGuid().ToString(), $VMSwitchPortName, "")
$NewSwitchPort1 = $ReturnObject.CreatedSwitchPort

$ReturnObject = $VMSwitchQuery.CreateSwitchPort($VMSwitch, [guid]::NewGUID().ToString(), $VMSwitchPortName, "")
$NewSwitchPort2 = $ReturnObject.CreatedSwitchPort

$StaticNet = $DefaultNet.psbase.Clone()
$StaticNet.VirtualSystemIdentifiers = "{GUID1}"
$StaticNet.StaticMacAddress = $true
$StaticNet.Address = $VMNICAddress
$StaticNet.Connection = $NewSwitchPort1

$DynNet = $DefaultNet.psbase.Clone()
$DynNet.VirtualSystemIdentifiers = "{GUID2}"
$DynNet.Connection = $NewSwitchPort2

#Add the network interface resources to Resource Allocation Settings
$VMRASD = @()

$VMRASD += $StaticNet.psbase.gettext(1)
$VMRASD += $DynNet.psbase.gettext(1)
$VMRASD += $VMMem.psbase.gettext(1)
$VMRASD += $VMProc.psbase.gettext(1)

# Time to create the virtual machine
$VMSvc.DefineVirtualSystem($NewVMGS.psbase.GetText(1), $VMRASD)

# Add our disk to the virtual machine
# $VM = Get-WmiObject -Namespace $Namespace -ComputerName $Computer -Query "Select * From Msvm_ComputerSystem Where ElementName = '$GuestVM'"

# $VMSettingData = Get-WmiObject -Namespace $Namespace -Query "Associators of {$VM} Where ResultClass = Msvm_VirtualSystemSettingData AssocClass = Msvm_SettingsDefineState"

$VMIDECtrl = (Get-WmiObject -Namespace $Namespace -Query "Associators of {$VMSettingData} Where ResultClass = Msvm_ResourceAllocationSettingData AssocClass = Msvm_VirtualSystemSettingDataComponent" | where-object -FilterScript {$_.ResourceSubType -eq "Microsoft Emulated IDE Controller" -and $_.Address -eq 0})

$DiskAllocationSetting = Get-WmiObject -Namespace $Namespace -Query "Select * From Msvm_AllocationCapabilities Where ResourceSubType = 'Microsoft Synthetic Disk Drive'"

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

$DefaultDiskDrive.Parent = $VMIDECtrl._Path

$DefaultDiskDrive.Address = 0

$NewDiskDrive = ($VMSvc.AddVirtualSystemResources($VM._Path, $DefaultDiskDrive.PSBase.GetText(1))).NewResources

$DiskAllocationSetting = Get-WmiObject -Namespace $Namespace -Query "Select * From Msvm_AllocationCapabilities Where ResourceSubType = 'Microsoft Virtual Hard Disk'"

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

$DefaultHardDisk.Parent = $NewDiskDrive
$DefaultHardDisk.Connection = $VHD

$VMSvc.AddVirtualSystemResources($VM._Path, $DefaultHardDisk.PSBase.GetText(1))

#Now, we add a DVD
$DVDAllocationSetting = Get-WmiObject -Namespace $Namespace -Query "Select * From Msvm_AllocationCapabilities Where ResourceSubType = 'Microsoft Synthetic DVD Drive'"

$DefaultDVDDrive = (Get-WmiObject -Namespace $Namespace -Query "Associators of {$DVDAllocationSetting} Where ResultClass = Msvm_ResourceAllocationSettingData AssocClass = Msvm_SettingsDefineCapabilities" | where-object -FilterScript {$_.InstanceID -like "*Default"})

$DefaultDVDDrive.Parent = $VMIDECtrl._Path

$DefaultDVDDrive.Address = 1

$NewDVDDrive = $DefaultDVDDrive.psbase.Clone()

$VMSvc.AddVirtualSystemResources($VM._Path, $NewDVDDrive.psbase.GetText(1))

In this code, I am using a data array to contain all of the resources that will be used to create the virtual machine.

$VMRASD = @()

$VMRASD += $StaticNet.psbase.gettext(1)
$VMRASD += $DynNet.psbase.gettext(1)

You will notice that the hard disk and DVD drive are not included in this array.  This is because they are added to a virtual IDE port.  These ports do not exist until after the virtual machine is created, so we add them after it is.

That wraps up this session for automating Hyper-V virtual machine creation through scripts.  As always, any comments or questions, let me know.

AAAAHHHHHH!

Just when I think I have decided on the right eBook reader for me, another one comes out with bigger and better features that made me revisit my earlier research.

First, I looked through several readers, but it really came down to Sony's and Amazon's readers.  These fell into my <$300 requirement and size, screen clarity, etc.  You know, all the things that make reading enjoyable.  In the end, I decided that I would lay down for the Kindle from Amazon.  Having Amazon lower the price on the non-DX model didn't hurt either.

Now comes the dilemma.  Barnes and Noble looks to be readying a release of their reader that they have unfortunately named 'Nook'.  A name is a name, so no big deal.  This appears to boast a color touchscreen, LendMe technology, a million books in the catalog, a replaceable battery, and it runs on Android.  These are a few of the features, but you can read more about the Nook at the Barnes & Noble site.

So, with me getting ready to purchase a reader, I needed to review what was important and how each product met the requirements.....again.  So, here goes.....

For me the color touchscreen is cool, but not a functional deal-maker.  There was not enough information that I could find on how it handles fingerprints and everyday use.  The LendMe technology is pretty cool in being able to let a friend borrow one of your ebooks for 2 weeks I believe.  I also think this carried over to the other readers from Barnes & Noble (iPhone/iPod, Blackberry, Mac, PC).  The replaceable battery is a nice option, but with a life expectancy of 2-3 years, I will probably upgrade to something else by then.  And, Android, is well, it's Android. I could care less about the underlying OS, as long as it does what I need it to.

This brings me to the one million books catalog.  The book count includes the myriad of books available through Google Books.  Not very beneficial to me.  Also, the Barnes & Noble ebook catalog has absolutely zero computer books.  For me, being an IT guy with tons of books on varying IT subjects, I was hoping to have at least of glimpse that there was a future in having them become available at some point.

Comparing this to the Amazon Kindle.....Amazon has a very large library of books available in the Kindle format.  These include a large selection of computer related books.  Many other categories and selections of books are available through Amazon for the Kindle.  This large library selection alone is really enough for me to settle on the Kindle, but I will point out a few other items.

First, like the Kindle, the Nook gets access to a wireless network for delivery of books.  The problem here is that the Nook uses the crappy AT&T cellular (3G, if you're lucky) network.  No guarantees that the book will be delivered because someone forgot to feed the mouse that runs their cell network.  Look at the challenges AT&T has with iPhones and pretty much any other phone on the network.  The Kindle uses the Sprint network for its' connectivity.  Sprint is not perfect either, but at least they know where the problems are at.  For me, it is about knowing the limitations versus assuming everything is 100%.

The Kindle is a tested product with a lot of users.  Many reviewers state that they wish it could do this or do that, but none are looking to exchange it for something else because it complements their reading style so well, which is the reason I am sticking with my decision to purchase the Amazon Kindle.

Thursday, October 22, 2009

Hyper-V Automation through scripts (Network)

Last time I looked at scripting memory resource creating.  Today, I want to look at the final individual component, network resources.  These network resources are virtual network interfaces that are connected to a virtual switch.  A virtual network interface can be connected to a virtual machine, but will not become active until it is attached to a virtual switch.

Let’s dig into the code to perform this network provisioning.

# Set up variables$VHD = "f:\VHDs\win2k8.vhd"

$GuestVM = "Win2k8"

$Namespace = "root\virtualization"

$Computer = "Hyper-V2k8"

# I am assuming the virtual switch and port already exist# created through Hyper-V Manager or through another script$VMSwitchName = "Hyper-V External Switch"$VMSwitchPortName = "VMPort"# Hyper-V uses GUIDs to identify components. Friendly names are only a benefit for admins$VMNICGUID1 = [GUID]::NewGUID().ToString()$VMNICGUID2 = [GUID]::NewGUID().ToString()

# Get instance of the default network interface$DefaultNet = Get-WmiObject -Namespace $Namespace -Class Msvm_SyntheticEthernetPortSettingData | where-object -FilterScript {$_.InstanceID -like "*Default*"}

# Get instance of Msvm_ComputerSystem class$VM = Get-WmiObject -Namespace $Namespace -ComputerName $Computer -Query "Select * From

Msvm_ComputerSystem Where ElementName='$GuestVM'"


# Get instance of Msvm_VirtualSwitchManagementService class$VMSwitchQuery = Get-WmiObject -Class "Msvm_VirtualSwitchManagementService" -Namespace $Namespace

# Get instance of Msvm_VirtualSystemManagementService class$VSMSvc = Get-WmiObject -Class "Msvm_VirtualSystemManagementService" -Namespace $Namespace

-ComputerName $Computer

# Get instance of target virtual switch$VMSwitch = Get-WmiObject -Namespace $Namespace -Query "Select * From Msvm_VirtualSwitch Where ElementName = '$VMSwitchName'

# Create the switch ports$ReturnObject = $VMSwitchQuery.CreateSwitchPort ($VMSwitch, [guid]::NewGuid().ToString(), $VMSwitchPortName, "
")$NewSwitchPort1 = $ReturnObject.CreatedSwitchPort$ReturnObject = $VMSwitchQuery.CreateSwitchPort ($VMSwitch, [guid]::NewGuid().ToString(), $VMSwitchPortName, "")$NewSwitchPort2 = $ReturnObject.CreatedSwitchPort

#Set up the virtual interfaces# I am showing two interfaces, a static and a dynamic addressed model$StatNet = $DefaultNet.psbase.Clone()$StatNet.VirtualSystemIdentifiers = "
{VMNICGUID1}"$StatNet.StaticMacAddress = $true$StatNet.Address = "00155d9290ff"$StatNet.Connection = $NewSwitchPort1

$DynNet = $DefaultNet.psbase.Clone()$DynNet.VirtualSystemIdentifiers = "
{VMNICGUID2}"$DynNet.Connection = $NewSwitchPort2

#set properties and target virtual machine$VSMSvc.AddVirtualSystemResources ($VM._Path, $StatNet.PSBase.GetText(1))$VSMSvc.AddVirtualSystemResources ($VM._Path, $DynNet.PsBase.GetText(1))

That creates our network resources.  Next time, I will take everything and put together a single script that builds a complete virtual machine.

Monday, October 19, 2009

Hyper-V Automation through scripts (Memory)

Last time I looked at building onto our WMI automation script with processor creation.  Today, I want to cover how to add memory resources into the script.  Once again, I will take advantage of the existing patterns for creating this script.

# Set up variables$VHD = "f:\VHDs\win2k8.vhd"

$GuestVM = "Win2k8"

$Namespace = "root\virtualization"

$Computer = "Hyper-V2k8"

# Get instance of Msvm_VirtualSystemManagementService class$VSMSvc = Get-WmiObject -Class "Msvm_VirtualSystemManagementService" -Namespace $Namespace

-ComputerName $Computer

# Get instance of Msvm_ComputerSystem class$VM = Get-WmiObject -Namespace $Namespace -ComputerName $Computer -Query "Select * From

Msvm_ComputerSystem Where ElementName='$GuestVM'"


#Associating Msvm_VirtualSystemSettingData class with $VM$VMVSSD = Get-WmiObject -Namespace $Namespace -Query "Associators of {$VM} Where

ResultClass=Msvm_VirtualSystemSettingData AssocClass=Msvm_SettingsDefineState"


# Define instance of Virtual IDE controller through an association$VMMEM = (Get-WmiObject -Namespace $Namespace -Query "Associators of ($VMVSSD) Where

ResultClass=Msvm_MemorySettingData AssocClass=Msvm_VirtualSystemSettingDataComponent"


| where-object -FilterScript {$_.ResourceSubType -eq "Microsoft Virtual Machine Memory"})

# Define memory resource attributes# set amount of memory (in megabytes)$VMMem.VirtualQuantity = [string]2048# set other attributes that are viewable in Hyper-V manager$VMMem.Reservation = [string]2048$VMMem.Limit = [string]2048

$VSMSvc.ModifyVirtualSystemResources($VM._Path, $VMMem.PSBase.GetText(1))

There you go. Memory has been defined and created for the virtual machine.  Next time, I will add a network resource via WMI.

Friday, October 16, 2009

Hyper-V Automation through scripts (Processor)

Last time I covered automatic Hyper-V through WMI for virtual disks.  Now, I want to cover how to automate the creation of processor resources.  One thing you will notice is that the pattern used to create virtual disks through WMI will be very similar for creating the rest of our resources.  As we figure out how to manipulate settings of virtual machine components, it becomes easier to build a complete script

# Set up variables$VHD = "f:\VHDs\win2k8.vhd"

$GuestVM = "Win2k8"

$Namespace = "root\virtualization"

$Computer = "Hyper-V2k8"

# Get instance of Msvm_VirtualSystemManagementService class$VSMSvc = Get-WmiObject -Class "Msvm_VirtualSystemManagementService" -Namespace $Namespace

-ComputerName $Computer

# Get instance of Msvm_ComputerSystem class$VM = Get-WmiObject -Namespace $Namespace -ComputerName $Computer -Query "Select * From

Msvm_ComputerSystem Where ElementName='$GuestVM'"


#Associating Msvm_VirtualSystemSettingData class with $VM$VMVSSD = Get-WmiObject -Namespace $Namespace -Query "Associators of {$VM} Where

ResultClass=Msvm_VirtualSystemSettingData AssocClass=Msvm_SettingsDefineState"


# Define instance of Virtual processor through an association$VMProc = (Get-WmiObject -Namespace $Namespace -Query "Associators of ($VMVSSD) Where

ResultClass=Msvm_ProcessorSettingData AssocClass=Msvm_VirtualSystemSettingDataComponent"


| where-object -FilterScript {$_.ResourceSubType -eq "Microsoft Processor"})

# Define Processor resource attributes# set number of processors$VMProc.VirtualQuantity = [string]1# set other attributes that are viewable in Hyper-V manager$VMProc.Reservation = [string]0$VMProc.Limit = [string]100000$VMProc.Weight = [string]100$VSMSvc.ModifyVirtualSystemResources($VM._Path, $VMProc.PSBase.GetText(1))

There you are. Adding a virtual processor through WMI using our already established pattern for defining resources.  Next time I will cover adding memory resources.

Thursday, October 15, 2009

I have built my fair share of VMs using both Hyper-V Manager and Virtual Machine Manager 2008 (VMM), but as an engineer, I wanted a way to build multiple VMs without the repetitive clicking involved in doing so within the graphical tools.  Fortunately, Microsoft enabled Hyper-V to be managed through WMI scripting.  With VMM, Microsoft has extended the scripting capability into PowerShell.  For this entry, I will focus on WMI,since I always look to understand what shortcut code is doing behind the scenes.  Much of the PowerShell scripting to accomplish these tasks are shorter than their WMI counterparts, but hide the details that I want to see and understand.

For those that don’t know, WMI is the method used to manage pretty much anything Microsoft has developed that runs under the Windows Operating System, so it is fitting that we can use it to manage Hyper-V as well.  Microsoft has made available several classes in WMI that can be used to manage Hyper-V.  A full listing can be found here.

I will not get into scripting the Hyper-V host server build, but will focus on scripting the virtual machine builds on the host.  See, I am building up VMs all the time and needed a method for lighting them up quickly. Building a host or multiple host servers is nice, but not really what I would use in my scenario.

In Hyper-V, there are four primary components that  make up a virtual machine.  These are virtual disk resources, processor resources, memory resources, and network resources. I will be covering each of these parts separately with a final script that takes everything and merges them into one script that will build a virtual machine for you.

The first thing we need to do before we can play with virtual disks is to create them.  Generally, this is pretty simple with a couple of lines.

$VirtDiskSvc = Get-WmiObject -Class "Msvm_ImageManagementService" -Namespace "root\virtualization" 

$VirtDiskSvc.CreateFixedVirtualHardDisk("f:\VHDs\win2k8.vhd", 20GB)

This gets a handle to the class in the first line and then creates a disk using the CreateFixedVirtualHardDisk method using a size of 20GB and path of f:\VHDs\win2k8.vhd.
If you would like to create a dynamic disk file, just keep the first line, but replace the second line.
$VirtDiskSvc.CreateDynamicVirtualHardDisk("f:\VHDs\win2k8.vhd", 20GB)

This creates a dynamic disk using the specified path and size.  The difference between these two methods is in Fixed, the entire 20GB disk is created.  In dynamic, just the minimal size is created and the virtual disk will autogrow up to the 20GB maximum size.
Finally, Hyper-V supports differencing, which uses a base disk and writes any changes to a differencing disk.  There are a couple of additional lines that need to be run to support this.
$VirtDiskPath = "f:\VHDs\win2k8-diff.vhd"

$VirtDiskParent = "f:\VHDs\win2k8.vhd"

$VirtDiskSvc = Get-WmiObject -Class "Msvm_ImageManagementService" -Namespace "root\virtualization"

$VirtDiskSvc.CreateDifferencingVirtualHardDisk($VirtDiskPath, $VirtDiskParent)

Building on this, let’s create a complete script.

# Set up variables$VHD = "f:\VHDs\win2k8.vhd"

$GuestVM = "Win2k8"

$Namespace = "root\virtualization"

$Computer = "Hyper-V2k8"

# Get instance of Msvm_VirtualSystemManagementService class$VSMSvc = Get-WmiObject -Class "Msvm_VirtualSystemManagementService" -Namespace $Namespace -ComputerName $Computer

# Get instance of Msvm_ComputerSystem class$VM = Get-WmiObject -Namespace $Namespace -ComputerName $Computer -Query "Select * From Msvm_ComputerSystem Where ElementName='$GuestVM'"

#Associating Msvm_VirtualSystemSettingData class with $VM$VMVSSD = Get-WmiObject -Namespace $Namespace -Query "Associators of {$VM} Where ResultClass=Msvm_VirtualSystemSettingData AssocClass=Msvm_SettingsDefineState"

# Define instance of Virtual IDE controller through an association$VMIDECtrl = (Get-WmiObject -Namespace $Namespace -Query "Associators of ($VMVSSD) Where ResultClass=Msvm_ResourceAllocationSettingData AssocClass=Msvm_VirtualSystemSettingDataComponent"  | where-object -FilterScript {$_.ResourceSubType -eq "Microsoft Emulated IDE Controller" -and $_.Address -eq 0})

# Define capabilities of the disk resource$DiskAllocSet = Get-WmiObject -Namespace $Namespace -Query "SELECT * From Msvm_AllocationCapabilities

WHERE ResourceSubType = 'Microsoft Synthetic Disk Drive'"

# Define minimum, maximum, default, and incremental value for disk resource allocation$DefaultDiskDrive = (Get-WmiObject -Namespace $Namespace -Query "Associators of {$DiskAllocSet} Where ResultClass=Msvm_ResourceAllocationSettingData AssocClass=Msvm_SettingsDefineCapabilities" | where-object -FilterScript {$_.InstanceID -like "*&Default"})

# Define controller and address$DefaultDiskDrive.Parent = $VMIDECtrl._Path$DefaultDiskDrive.Address = 1

# Define new disk drive through AddVirtualSystemResources method of the Msvm_VirtualSystemManagementService class$NewDiskDrive = ($VSMSvc.AddVirtualSystemResource($VM._Path, $DefaultDiskDrive.PSBase.GetText(1))).NewResources

#Get Microsoft Virtual Hard Disk resource subtype$DiskAllocSet = Get-WmiObject -Namespace $Namespace -Query "SELECT * FROM Msvm_AllocationCapabilities WHERE ResourceSubType = 'Microsoft Virtual Hard Disk'"

# Get Microsoft Virtual Hard Disk instance and store in variable$DefaultHardDisk (Get-WmiObject -Namespace $Namespace -Query "Associators of {$DiskAllocSet} Where ResultClass=Msvm_ResourceAllocationSettingData AssocClass=Msvm_SettingsDefineCapabilities" | where-object -FilterScript {$_.InstanceID -like "*Default"})

# Define properties for our $DefaultHardDisk$DefaultHardDisk.Parent = $NewDiskDrive$DefaultHardDisk.Connected = $VHD

# Add $DefaultHardDisk to virtual machine$VSMSvc.AddVirtualSystemResources($VM._Path, $DefaultHardDisk.PSBase.GetText(1))

That should take care of create a virtual disk through WMI.  Next time, I will take a look at creating processor resources through WMI for Hyper-V.

Wednesday, October 07, 2009

ESX vs Windows Time Sync

Not sure if this is a common issue or if I just hit a perfect storm with an ESX host and a Windows guest OS. Here is how it played out……

We had an application that checks the time and date stamps between its host server and the database server that it writes to.  This is done to ensure accurate records in the database and all that fun stuff.  In any case, when the time difference falls outside of the pre-determined tolerance level, the application service shuts itself down, thereby disabling the application.  So far so good. This is what is should do.

When this started happening, I looked at how the clocks were set up. The Windows guest OS was configured to sync time and data information from a domain controller.(Ok, that’s good).  VMWare Tools in the guest OS had the time sync option unchecked. (Ok, that’s good too).  We know that the VMWare Time Sync option and the Windows Time Service do not recognize each other and in some cases can cause overcorrection of time.  Not the case here, but just a fact we are aware of.

Visually, everything looked good, so where did that leave me? I knew something was causing a discrepancy in the time, so I disabled the Windows Time Service and stopped it, then enabled the Time Sync option in VMWare tools.  As soon as I did that, the clock moved forward 13 minutes.  Hmm, that was the amount of time shown in our application logs as a difference in time between our application and the SQL database.  Interesting.

Talking with the VMWare engineer, they updated the ESX host clock to sync from the domain.  I re-enabled Windows Time Service and removed the Time Sync option from VMWare Tools set the guest OS back to its original state. The guest OS was rebooted, since it always gets the clock update at that time.  This time, it came up without our application service shutting down.  A couple other reboots confirmed the setting was good once again.

Lesson learned:

Apparently, in ESX server, even though a guest OS clock (Windows, for sure) is configured to sync with a domain clock source, it is apparently tunneled through ESX.  When this happens, the guest OS application thinks it is 10:00, but the time is being presented as 10:13.  At this point, I am not sure if it is presented this way going to the SQL server or if it is being translated coming back to the guest OS.  I have a hunch it is the latter, since the application is what complains about the time difference.

If anyone else has seen something similar, let me know.  This is really the first time I have run into this and other guests seem to run just fine with the same configuration.

Windows 7 Keyboard Shortcuts

Now that we are a couple of weeks away from the official retail launch date of Windows 7, I thought I would list out some of my favorite and most used keyboard shortcuts in this new operating system from Microsoft.  For me, the most used are grouped into 3 categories; General Windows 7, Display Shortcuts, and Display Magnifier Shortcuts.

General Windows 7

Windows logo key + Tab

Cycle through open programs on the taskbar using Aero Flip 3-D

For those not familiar with Aero Flip 3-D, this was introduced with Windows Vista, and functions much like the Alt + Tab feature, but performs it visually.  Eye candy, but nice.

Ctrl + Windows Logo key (+ Tab)

Hit the tab key once while holding the other two and then use the arrow keys to move the Aero Flip 3-D, then hit Windows Logo key to release.

Windows Logo key + Pause

Display the System Properties dialog box

Windows Logo key + D

Display the Desktop

Windows Logo key + M

Minimize all windows

Windows Logo key + Shift+M

Restore minimized windows

Windows Logo key + E

Open Computer Explorer

Windows Logo Key + R

Open Run dialog box

Display Shortcuts

Windows Logo Key + Spacebar

Look at the desktop without minimizing/closing application

Windows Logo key + Shift + (Left Arrow or Right Arrow)

Moves active window from one screen to another in multi-monitor configurations

Windows Logo key + PChoose a display presentation mode

Shift+Click taskbar item

Opens a new instance of the item

Display Magnifier Shortcuts

Windows Logo key + (+ or – key)

Screen Zoom in or out

Ctrl + Alt + F

Switch to Full Screen

Ctrl + Alt + L

Switch to Lens mode

Ctrl + Alt + D

Switch to Docked mode

Ctrl + Alt + I

Invert colors

Ctrl + Alt + arrow keys

Pan in the direction of the arrow key

Windows logo key + Esc

Exit Magnifier