Comment An explanation why get-harddisk is so slow - 03/24/09

It just so happened that today I was browsing the VMware blog for the Windows VI Toolkit, and came across a post the described in a fair amount of detail why get-harddisk was slow for me.

Looks like the culprit is that I typically use get-view to pull my information out of the API, and as such I had to pass a VM name into get-harddisk, which results in some extremely slow object name translation voodoo.

This:

get-harddisk -vm (get-vm -name s092464).name

was over a minute slower than this:

get-harddisk -vm (get-vm -name s092464).

So imagine that times 1200.

That said, I think my script will still stay with the method I wrote about last week, simply because get-view suits my data needs better, plus it’s WAY faster:

get-vm -name s092464 = 2 minutes

get-view -viewtype virtualmachine -filter @{“Name” = “s092464″} = 5 seconds

2 Comments get-vm is retarded slow - 03/20/09

I have been working a lot with the Windows VI Toolkit lately, it is a very straight forward way of working with your Virtual Infrastructure programmatically.

One of the things I have noticed is that there are a few cmdlets, that are exceedingly slow.  These cmdlets aren’t so bad to use if you are working with a single VM, but if you start doing some scripting against hundreds or thousands of machines, whoa boy – I mean hit enter, go make a cup of coffee, drink it, drop the kids off at the pool, and you’ll still have time to spare.

Thus far the worst cmdlets I’ve come across are get-vm and get-harddisk.  get-vmhost, and get-cluster are pretty pokey as well, but fortunately even in a large environment, there aren’t that many hosts and there are even fewer clusters so they don’t annoy me with their pokeyness much.  Yet.

Here’s an example of how slow these cmdlets are, I have a script that I wrote that looks at my VI, and grabs every single VM that fits a certain naming pattern, which business rules dictate are VDI instances.  Next, I take the VM collection, and pull some interesting data: name, memory allocation, guestOS, IP, VLAN (portgroup), and VMDK size.  I knew from the get go that get-vm was slow, so I was using get-view.  get-view doesn’t return quite as friendly an object, but if you are willing to explore, it has everything you need.

So my collection of ~1200 VMs, comes back, and I do a little dance with it, then I get the portgroup:

$tempvm.vlan = (Get-View -Id $vm.network).name fairly speedy return

Then I get the VMDK size:

get-harddisk -VM $vm.name | foreach-object -process {$tempvm.diskGB += $_.CapacityKB}
    $tempvm.diskGB = [math]::round(($tempvm.diskGB / 1048576),0)
    if ($tempvm.diskGB -eq 0)
    {
        $tempvm.diskGB = “N-A”
    }

Let’s jsut say you can go take a nice nap, but it returns the total size of the VMDKs attached to the system.

I then scheduled this script to run via AutoSys, and it happily generated a CSV of all my VDI instances, and the info I wanted – in 35 hours!

I was a bit perturbed by the run time, but figured it was a batch job, and I could adjust the start times, and I’d just live with it.

Not any longer!  Today I had an epiphany of sorts while exploring the get-view object returned for a VM – it was if the skies had parted, God spoke to me, while a chorus of Angels sang.  Or I could have seen a Narwhal, I’m not really sure, but it was that cool.

The epiphony caused me to modify two lines of code – the temp.vlan line, and the get-harddisk line – replacing them with:

foreach ($device in ($myvm.config.hardware.device)) {if ($device.backing.devicename -like “VLAN*”) {$tempvm.vlan=$device.backing.devicename}}

and

foreach ($device in ($vm.config.hardware.device)) {if ($device.backing.filename -like “*vmdk”){$tempvm.diskGB += $device.capacityinKB}}

After the changes, I force started my job and waited eagerly for it to complete – 2 minutes and 15 seconds later.  Same result, only 35 hours less of waiting.

 

And if you don’t believe me, here is the run log from AutoSys

Original Code:

[FORCE_STARTJOB] Fri Mar 13 11:50:24 2009    
Starting Fri Mar 13 11:50:25 2009    
Running Fri Mar 13 11:50:28 2009    
Success Sat Mar 14 23:21:53 2009    

Revised Code:

Starting Fri Mar 20 14:25:13 2009    
Running Fri Mar 20 14:25:16 2009    
Success Fri Mar 20 14:27:25 2009    

Comment Powershell script against VC – in batch! - 03/17/09

Not long ago, I posted a powershell script, that would set a standard memory and CPU reservation across an entire virtual center instance.

As cool as that is, let’s make it even cooler, let’s do it as a scheduled task and so you don’t have to enter credentials!

The first thing you need to do is create a text file that contains an encrypted password.

read-host -assecurestring | convertfrom-securestring | out-file C:\securestring.txt

This will store the password you type into a text file, that is only decryptable by the user that ran the script.

Next we make a little modification of the script I posted earlier (the modfied script is below, with updated parts in italics)

add-pssnapin VMware.VimAutomation.Core -erroraction Silentlycontinue
$vcServer=”virtualcenter”
$user=”Cooluser”
$credentialFile=”C:\securestring.txt”
$pass = cat $credentialFile | convertto-securestring
$credentials = new-object -typename System.Management.Automation.PSCredential -argumentlist $user,$pass
$vcConnection=connect-viserver -server $vcServer -credential $credentials -warningaction Silentlycontinue
$vms=get-view -viewtype VirtualMachine -server $vcConnection

$vms | % {$spec = new-object VMware.Vim.VirtualMachineConfigSpec;
        $spec.memoryAllocation = New-Object VMware.Vim.ResourceAllocationInfo;
        $spec.memoryAllocation.Shares = New-Object VMware.Vim.SharesInfo;
        $spec.memoryAllocation.Shares.Level = “normal”;
        $spec.memoryAllocation.Limit = -1;
        $spec.memoryAllocation.Reservation = 512;
        $spec.cpuAllocation = New-Object VMware.Vim.ResourceAllocationInfo;
        $spec.cpuAllocation.reservation = 0
        $spec.cpuallocation.Shares = New-Object VMware.Vim.SharesInfo;
        $spec.cpuAllocation.Shares.Level = “normal”;
        $spec.cpuAllocation.Limit= -1;
        Get-View($_.ReconfigVM_Task($spec))}
       
disconnect-viserver -Confirm:$false

The best part of this script is, if you do run it interactively, it won’t display a certificate warning message, and it will disconnect your VC session – kind of like “Be kind, rewind”

2 Comments Setting a standard resource reservation across your VI - 03/2/09

Me, I’m a big fan of standards.  Standard processes, standard this, standard that – standards are a great way to make your life easier when dealing with hundreds or thousands of objects.

Inside of my Virtual Infrastructure, I’m a huge fan of ignoring the micro level of things, and paying attention to things at a macro level.  One of the ways I do that, is by ensuring that every virtual machine is configured with identical reservations – regardless of how much resources they are allocated.  If a given virtual machine (or group of virtual machines) requires a guaranteed amount of resources, I create a resource pool and toss them in there.

Not only does this prevent a “rouge” VM from stealing resources it may not need at a moment in time, it calls out the big hitters and puts them out in the open.

Our virtual machine creation process defines all new virtual machines with our standard reservation, but over the course of weeks and months, these drift.  Machines change, an admin “tests” something and forget’s to change it back, or we might even change the standard.  Here is a script that will locate all virtual machines in your infratructure, and update them to whatever makes you happy.

add-pssnapin VMware.VimAutomation.Core -erroraction Silentlycontinue
$vcServer=”virtualcenter”
$credentials = get-credential
$vcConnection=connect-viserver -server $vcServer -credential $credentials
$vms=get-view -viewtype VirtualMachine -server $vcConnection

$vms | % {$spec = new-object VMware.Vim.VirtualMachineConfigSpec;
        $spec.memoryAllocation = New-Object VMware.Vim.ResourceAllocationInfo;
        $spec.memoryAllocation.Shares = New-Object VMware.Vim.SharesInfo;
        $spec.memoryAllocation.Shares.Level = “normal”;
        $spec.memoryAllocation.Limit = -1;
        $spec.memoryAllocation.Reservation = 512;
        $spec.cpuAllocation = New-Object VMware.Vim.ResourceAllocationInfo;
        $spec.cpuAllocation.reservation = 0
        $spec.cpuallocation.Shares = New-Object VMware.Vim.SharesInfo;
        $spec.cpuAllocation.Shares.Level = “normal”;
        $spec.cpuAllocation.Limit= -1;
        Get-View($_.ReconfigVM_Task($spec))}

|

Bear