VMGuru.com - Home of the Virtualization Gurus

Our Books REALLY are Available Now!

Don’t become overwhelmed by your VMware Infrastructure project. Use the books that tens of thousands of others have used to design, plan, and implement their virtual infrastructures.Download Now!

Scripting
Using PowerShell to Track Block Change Sizes Over Time PDF Print
Written by Scott Herold   
Friday, 09 April 2010 12:31

Updated to fix a minor bug on April 16, 2010

I took it as a personal challenge this week to leverage PowerShell, PowerCLI and the vSphere API to track the amount of data that changes in a VM over a regular interval window.  It turns out VMware does make it quite simple to query what blocks in a VMDK file have changed and what the length of data is as long as you know how to structure the API call.

The following script can be run as a scheduled task in Windows on a regular interval such as every 15 or 60 minutes, or even just once a day (depending on how granular you want your data) against a single VM.  This is perfect for profiling the amount of data a particular VM will need to send (uncompressed) over a network connection for backup or replication purposes. 

There are a few quick things to note about this script:

  1. It requires vSphere and CBT to be enabled for the selected virtual machine.  This also means the VM Hardware version must be set to 7.  There is an optional flag of "-enableCBT $true" that can be set as a script parameter to enable CBT for the specified VM.  This executes an additional function in the script to turn CBT on.  If CBT is already enabled, the function simply exits cleanly, no harm, no foul.
  2. I don't recommend running this script against a VM if there is potential overlap with other regular processes such as backup or replication that add snapshots to virtual machines.  I don't have advanced snapshot debugging in here and simply don't know how all scenarios of snapshots being added/removed from multiple programs against a single VM will play out.
  3. I have it limited so a single instance of the script can be run against a single VM only.  I started off with this being a simple proof-of-concept script, and haven't built in proper multi-VM intelligence yet.  If there is enough demand, I'll definitely consider it.

You should create a standalone directory somewhere on an available hard drive of a Windows system.  Create a new PS1 file using the built in script editor in Virtualization EcoShell. Copy and paste the following code block and save the file as "CBT_Tracker.ps1" in the newly created directory:

#(c)2010 Scott Herold - VMGuru.com
#Quest Software
Param (
    [string] $vmName,
    [string] $vimHost,
    [string] $vimUser,
    [string] $vimPass,
    [Boolean] $enableCBT = $false

)
#Use the optional $enableCBT paramater at input to enable CBT on
#a compatible virtual machine (HW Version 7). In order for CBT flags to take
#effect, a Snapshot must be added and removed.
function Add-CBTFlag {
    if ($vmv.Config.ChangeTrackingEnabled){
        "CBT is already enabled on $vm"
        return
    }
    $vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
    $vmConfigSpec.changeTrackingEnabled = $true
    $vmv.ReconfigVM($vmConfigSpec)
    sleep 3
    $vm | New-Snapshot -Name "Enable CBT"
    sleep 5
    $vm | Get-Snapshot -Name "Enable CBT" | Remove-Snapshot -Confirm:$false
    "Enabled CBT for $vm"
}

#Add a snapshot specific to the purposes of this script
function Add-CBTSnap {
    $newSnap = $vm | New-Snapshot -Name "CBT Change Tracker"
    return $newSnap
}

#Remove the snapshot created for the purpose of this script
function Remove-CBTSnap {
    param (
        $vmSnap
    )
    $vmSnap | Remove-Snapshot -Confirm:$false
}

#Captures the ChangeID of the snapshot, which is required for comparisson
#tracking purposes.  The current run of the script will always compare
#current state against the previously logged ChangeID for differences.
function Get-ChangeID {
    param (
        $vmSnap
    )
    $vmSnapv.Config.Hardware.Device | where {($_.GetType()).Name -eq "VirtualDisk"} | ForEach-Object {
        $vzCBT = New-Object PSObject
        $vzCBT.PSObject.TypeNames.Clear()
        $vzCBT.PSObject.TypeNames.Insert(0,"vzCBTTracker")
        $vzCBT `
            | Add-Member -MemberType NoteProperty -Name VMName -Value $vm.Name -PassThru `
            | Add-Member -MemberType NoteProperty -Name DeviceID -Value $_.Key -PassThru `
            | Add-Member -MemberType NoteProperty -Name ChangeID -Value $_.Backing.Get_ChangeID()
        [array] $vzCBTColl += $vzCBT
    }
    return $vzCBTColl
}

#Writes the historic ChangeID and VMDK device information to a tracking file
#This file is read on each iteration of the script to capture the previos
#iterations ChangeID inforation.
function Write-TrackerLog {
    $output = $null
    $cid | ForEach-Object {
        $output += $_.VMName + "," + $_.DeviceID + "," + $_.ChangeID + "`n"
    }
    $output | Out-File "$vm-CBTTracker.cfg"
}

#Reads previous state information of the VM from the Tracker.cfg file
#Captures the list of changed blocks for the specified VM for each VMDK file
#calculates the total size in bytes of changed block data across all VMDK
#files associated with the VM.
function Get-ChangedBlockSize {
    $chSize = 0
    Get-Content "$vm-CBTTracker.cfg" | ForEach-Object {
        if ($_ -ne "") {
            $TrackerRef = $_.split(",")
            $changes = $vmv.QueryChangedDiskAreas($vmSnapv.MoRef,$TrackerRef[1],0,$TrackerRef[2])
            $changes.ChangedArea | ForEach-Object {
                $chSize += $_.Length
            }
        }
    }
    $chSize = $chSize/1024/1024
    return $chSize
}

#Writes the actual iterations change data out to a CSV file
function Write-TrackerCSV {
    $longDate = Get-Date
    $shortDate = $longDate.toShortDateString() + " - " + $longdate.toShortTimeString()
    Add-Content "$vm-CBTTracker.csv" "$vm,$shortDate,$amtChanged"
}

#Loads VMware's PowerCLI PowerShell Cmdlets if necessary
[void](Get-PSSnapin VMWare.VimAutomation.Core -ErrorVariable getVmwareSnapinErr 2> $null)
if ($getVmwareSnapinErr.Count -gt 0) {    Add-PSSnapin VMware.VimAutomation.Core }

#Establish a connection to the VI Server based on input parameters
Connect-VIServer $vimHost -User $vimUser -Password $vimPass

#Load some VM variables
$vm = Get-VM $vmName
$vmv = $vm | Get-View

#We can only run against a single VM at this point in time.  This makes sure
#the object being passed is a single VirtualMachineImpl object, and not a
#collection.
if (($vm.GetType()).Name -ne "VirtualMachineImpl"){
    "Script can only run against a single VM at a time"
    return
}

#Checks to make sure VM Hardware version is 7.  Terminates if not.
if ($vmv.Config.Version -ne "vmx-07"){
    "The Virtual Machine $vm must be VM Hardware Version 7 to support CBT"
    return
}

#If the "-enableCBT $true" flag is set as an input parameter, enables CBT
#for specified VM if necessary
if ($enableCBT){
    Add-CBTFlag
}

#If all other checks fail, this is a final failsafe to ensure CBT is enabled
#on the VM before continuing the script.
if ($vmv.Config.ChangeTrackingEnabled -eq $false){
    "CBT is not enabled on $vm.  Script cannot proceed."
    return
}

#Load up snapshot variables
$vmSnap = Add-CBTSnap
$vmSnapv = $vmSnap | Get-View
$amtChanged = 0

#Checks to see if the script has previous written out a CBTTracker.cfg file. This
#would indicate file deletion, or first script run.  If cfg file doesn't exist,
#initializes CSV headings.  If this is an iterative run, Gets the amount of
#data that has changed since previous iteration.  Writes to CSV file.
if (Test-Path "$vm-CBTTracker.cfg") {
    $amtChanged = Get-ChangedBlockSize
    Write-TrackerCSV
}
else {
    Add-Content "$vm-CBTTracker.csv" "VMName,Time,ChangedMB"
}

#Capsture the current ChangeID to use against next iteration, Remove Snapshot
#Write cfg data.
$cid = Get-ChangeID ($vmSnap)
Remove-CBTSnap ($vmSnap)
Write-TrackerLog
 

With the script file created, use notepad or other simple text editor to create a new CMD file called "CBT_Tracker.cmd".  This is what you will execute within Windows Task Scheduler.  Paste the following line in the CMD file and edit with the proper parameters for your environment.  Make sure you copy exactly, including the quotes.

powershell -command "& '.\CBT_Tracker.ps1' -VMName VMName -vimHost vCenter.domain.com -vimuser domain\user -vimpass Passw0rd"

You can now fire up Windows Task Scheduler and point to the CMD file.  After the script runs for the first time, you will see 2 new files per VM that you set this to run against.  $VMName-CBT_Tracker.cfg is used for tracking previous snapshot history for reference in the current script iteration.  $VMName-CBT_Tracker.csv is the actual data file that contains the VMName, Timestamp, and Amount of data changed.

The CSV/Excel combination will let you do some creative things with the data output.

 

 
Fun with PowerShell - Calculate Permutations PDF Print
Written by Scott Herold   
Saturday, 13 June 2009 22:17

I got sidetracked on Twitter tonight with a conversation between @jasonboche and @vmdoug, and since my wife is out of town visiting family I figured what better way to spend a Saturday night than to write a quick PowerShell script that can calculate the number of unique permutations based on 2 criteria.

First is the total number of available elements.  in this case, we were looking at the number of available URL combinations on bit.ly before they would "run out".  Without spending any more than 15 seconds investigating, I determined that bit.ly uses only alphanumeric keys, but is case sensitive.  That means we have 26 uppercase letters, 26 lowercase letters, and 10 integers (0-9).  That gives us 62 total elements.

The second criteria is the number of total elements used in the combination.  In this case, bit.ly still uses 5 character URL strings.

The math behind this is something that I actually still remembered from high school oh so many years ago and is P = n!/(n-r)! where P is the number of Permutations, n is the total number of available elements, and r is the number of elements used in the combination.

Borrowing a function from stackoverflow.com (The nested loop calculation was pissing me off so I had to cheat), I was able to put together the following PowerShell script that can rather quickly do basic permutation calculations.

function factorial( [int] $f ) 
{ 
$result = 1
if ( $f -gt 1){
$result = $f * ( factorial ( $f - 1 ) )  
}
$result
}
 
function permutation( [int] $n, [int] $r )
{
(factorial $n) / (factorial ($n - $r) )
}
[int] $n = Read-Host "Total number of available elements:"
[int] $r = Read-Host "Total number of elements in combination:"
 
if ($n -ge 1 -and ($n - $r) -ge 0) {
permutation $n $r
}
else{
Write-Host "Invalid input parameters"
} 

 

So, when all is said and done, by using this script we can determine that when using 62 total elements in 5 element combinations, bit.ly currently has 776,520,240 URL combinations available.  if they were to change to a 6 character URL, the number jumps to 44,261,653,680, in addition to the 776,520,240 combinations from their 5 character URLs.  I think its safe to say that as long as the bit.ly database can handle the load, we don't need to worry about them running out of URLs any time soon.

 
Resolving Improper Memory Limits on your Virtual Machines PDF Print
Written by Scott Herold   
Monday, 11 May 2009 12:14

Last week I posted an article that talked about what happens on an ESX Server when a virtual machine has a memory limit set lower than the amount of memory assigned to that virtual machine.  Sound confusing?  If so, head over and read the original blog post.

The short version is that the situation is simply not good, and has major performance implications across the ESX Host, and potentially across the whole infrastructure.  Today, I want to show how you can simply identify and resolve this significant VMware Infrastructure issue using some simple PowerShell commands.

 
Conception of a Turtle - Part 2 PDF Print
Written by Scott Herold   
Friday, 17 April 2009 12:21

This is the second part of my blog post in which I give people a little insight into the "Behind the Scenes" of bringing Virtualization EcoShell to life.  Why did I do it, Why did I choose PowerGUI, etc.  My goal is to give people just a little appreciation into the amount of effort it takes to bring new ideas to market (and to do it for free!).

 
Conception of a Turtle - Part 1 PDF Print
Written by Scott Herold   
Thursday, 16 April 2009 18:47

As many people have hopefully noticed, yesterday marked the release of Virtualization EcoShell from Vizioncore.  Virtualization EcoShell is a freeware desktop toolkit for VMware administrators based off Windows PowerShell technology.  When get out to customer sites or am at trade shows I am often asked “Where did this idea come from?”, or “Wow, what into getting this available?”  For this blog series, I figured I’d give everyone some insight into what went into taking Virtualization EcoShell from conception to delivery.  The trick will be doing so in a way that doesn’t put everyone to sleep.  I’ve decided to split this post into two parts that I will release over two days.  In exchange for making you guys come back both days, I’ll post another chapter a week early right after I post Part 2 tomorrow.

 
<< Start < Prev 1 2 3 4 Next > End >>

Page 1 of 4

Syndication

feed-image RSS Feed

Buy on Amazon