31 January 2011

Enable SIOC On All Datastores

After reading what Duncan at Yellow-Bricks.com had to say about enabling SIOC (Storage I/O Control) on all datastores here and here, we were inspired to write a script to avoid having to do it by hand on the 370 datastores in our environment. Of course, LucD already has a SIOC script but it was written before VMware fixed the StorageResourceManager bug in PowerCLI 4.1.1 that he had to use a workaround for. LucD's script allows you to both query and set values--we just wanted one that enabled SIOC on all datastores that supported it as quickly as possible. In addition, we wanted to schedule it (this script is not schedule-ready) to run on a regular basis so that it can enable SIOC on newly created datastores without admins having to worry about it.

This is what we ended up with:
## Script function: Enable SIOC (Storage I/O Control) on all datastores that support it and do not already have it enabled.
## Author: vNugglets.com

## Set up specification to enable SIOC
$spec = New-Object VMware.Vim.StorageIORMConfigSpec
$spec.Enabled = $True

## Create an array of datastore view objects that are SIOC capable and that do not already have it enabled
$arrSIOCableDatastores = @(Get-View -ViewType Datastore -Property Capability.StorageIORMSupported,IormConfiguration,Name -Filter @{"Capability.StorageIORMSupported" = "True"; "IormConfiguration.Enabled" = "[^(True)]"})

## Loop through each SIOC-ready datastore view (if any), then on the first run grab the "view" of the StorageResourceManager (this is needed to use the ConfigureDatastoreIORM_Task method to enable/disable SIOC) and finally, enable SIOC on the datastore
$arrSIOCableDatastores | ForEach-Object -Begin {$viewStorageRM = Get-View -Id "StorageResourceManager-StorageResourceManager"} {
$viewStorageRM.ConfigureDatastoreIORM_Task($_.MoRef, $spec)

Of course, if you want to disable SIOC on all of your datastores you need to only modify two pieces of code:

Line 7: Simply change $True to $False.
Line 10: Remove the caret (^) on the second part of the filter so it finds datastores that already have SIOC enabled.

Depending on what you are looking for, you may choose LucD's script over this one, or maybe you'll use both since his contains two functions and gives you more granular control on which datastores to enable/disable SIOC.

19 January 2011

Re-Registering VMs Removed from Inventory

The cache module on the array controller failed on a host, and ESXi was wasted. The host stopped responding in vCenter, but did not fail hard enough to trigger HA. Most of the VMs on it were still up and their OSes were responsive to ping requests. Eventually we had to remove the host from vCenter. At that point, all VMs registered on it also are removed from inventory.

I grabbed the info for the guests that were in "disconnected" state _BEFORE_ removing the affected host from vCenter, then removed the host, then re-registered VMs and started them as such:
## Script function:  re-register VMs after host removal from vCenter
## Author: vNugglets.com
## Jan 2011

## cluster in which troubled host resides
$strAffectedCluster = "myCluster"

## get array BEFORE removing bad host from vCenter!!! Else, will not be able to get this info in this manner, since disconnected VMs are removed from inventory at that time, too

## get an array of VM .Net View objects where their OverallStatus is "gray"; optimized for low memory consumption
$arrVMsToHandle = Get-View -ViewType VirtualMachine -SearchRoot (Get-Cluster $strAffectedCluster | Get-View).MoRef -Property Name,Parent,LayoutEx.File,Summary.OverallStatus -Filter @{"Summary.OverallStatus" = "gray"}

## get the hosts in the cluster, to be used for re-registering VMs
$arrHostsInAffectedCluster = Get-Cluster $strAffectedCluster | Get-VMHost

## for each set of VM name, parent folder ID, and .VMX file path, add VM to inventory via New-VM cmdlet; add to random host within the cluster
$arrVMsToHandle | Select Name, Parent, @{n="vmxFilePath"; e={($_.layoutex.File | ? {$_.name -like "*.vmx"}).name}} | %{
New-VM -VMFilePath $_.vmxFilePath -VMHost ($arrHostsInAffectedCluster | Get-Random) -Location (Get-VIObjectByVIView $_.Parent) -RunAsync
} ## end ForEach-Object

## start all of the VMs (may cause a boot storm if huge number of VMs -- split up by groups of x VMs as necessary)
$arrVMsToHandle | %{Start-VM $_.Name -RunAsync}

You could also have put the "Start-VM" call inside of the "ForEach-Object" loop (say, before line 19), but that makes the process more linear than quick. This would require the removal of the "-RunAsync" from the "New-VM" call on line 18.

This could come in handy for you someday. Enjoy!