Archive

Archive for the ‘Scripting’ Category

Installing VMware SDK with Visual Studio 2010 / Visual Studio 2010 Express – workaround

March 31, 2011 Leave a comment

This is just a quick workaround to get the installation done – nothing else (really a reminder to myself)

I have a project to provision VMs from a customised front-end,
I have created a C# tool – that integrates with SCCM as well as our various asset management tools and some scripting environments, to allow for a ‘1 button deployment’

Of course . . to be a true one button deployment, I’d like to be able to actually create a VM when using the same ‘Big Red Button’

Anyway, my development environment happens to be Visual Studio 2010 – so yes simple . . let’s get going, surely we just follow the setup guide provided at :

http://www.vmware.com/support/developer/vc-sdk/visdk400pubs/sdk40setupguide.pdf – page 19

Well, that would work, except that the SDK kit has not yet gotten the relevant batch files for a Visual Studio 2010 installation.

The solution to get the installation working was to get a copy of the amended cmd from the VMWare communities:
http://communities.vmware.com/servlet/JiveServlet/download/1225636-21465/genvimstubs2.cmd
and copy it to your .\sdk\samples\DotNet directory

Next, go to : Start Menu\Programs\Microsoft Visual Studio 2010\Visual Studio Tools and select Visual Studio Command Prompt (2010)

Now, make sure that you have the environmental variable VCINSTALLDIR set to point to your Visual Studio installation path (type ‘set’ to see your environmental variables)
I had to set it like this:

SET VSINSTALLDIR="c:\Program Files (x86)\Microsoft Visual Studio 10.0"

Finally, I had to run the installer.]
In my case, the SDK was at d:\VMWare\SDK\samples, so I ran:

D:\VMWare\SDK\samples\DotNet>genvimstubs2.cmd d:\VMWare\SDK\wsdl\vim25 Vim25Api stage Vim25Objects.cs . Vim25Service2005

Installation looks like this:

D:\VMWare\SDK\samples\DotNet>genvimstubs2.cmd d:\VMWare\SDK\wsdl\vim25 Vim25Api
stage Vim25Objects.cs . Vim25Service2005
Checking and Creating stage
The system cannot find the file specified.
Microsoft (R) Web Services Description Language Utility
[Microsoft (R) .NET Framework, Version
2.0.50727.1432]
Copyright (C) Microsoft Corporation. All rights reserved.
Writing file ‘stage\Vim25Objects.cs’.
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.4926
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.

Microsoft (R) Xml Serialization support utility
[Microsoft (R) .NET Framework, Version
2.0.50727.1432]
Copyright (C) Microsoft Corporation. All rights reserved.
Serialization Assembly Name: Vim25Service2005.XmlSerializers, Version=0.0.0.0, C
ulture=neutral, PublicKeyToken=null.
Generated serialization assembly for assembly D:\VMWare\SDK\samples\DotNet\vim25
service2005.dll –> ‘.\Vim25Service2005.XmlSerializers.dll’.
Optimizing generated stubs…
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.4926
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.

Stub generation Done.
ECHO is off.

From here you can continue using the instructions in the getting started guide above.

Categories: Scripting, VMWare Tags: ,

Using regular expressions to parse files in PowerShell

March 28, 2011 Leave a comment

How often do you find yourself needing to identify a string in a file somewhere.

For example, you have a log file, or a config file and you know it contains an IP address, but you do not want to manually trawl through this file (or even worse . . these files)

Regular expressions are pretty handy, as you can use them to identify (and edit) strings of text pretty simply. thik of it as a Replace function on steroids.

Here are some examples:
http://www.regular-expressions.info/quickstart.html

Anyway, back to our original question – we’d like to find an IP address in a file.

The first thing of course is to get hold of the text in our file – we’ll drop it into an array, so we can do a line by line comparison..

$var = @(Get-Content .\Access*.log)

Next, we need to create a Regex string pattern, which we will use as reference when we query out text – there are plenty examples available on the web (e.g. http://www.regular-expressions.info/examples.html) – but we just need one to find IP addresses:

$regex = [regex] "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"

Lastly, we simply need to return a list of elements in our array, where the array matches the REGEX search string – again simple:

$regex.matches($var) | Select-Object -unique -property "Value"

so the full bit of code:

$var = @()
$var = Get-Content .\Access*.log
$regex = [regex] "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
$regex.matches($var) | `Select-Object -unique -property "Value"

Value

Finding VMs with disks on multiple different datastores – Script of the Day

March 23, 2011 Leave a comment

I was looking at a VM on one of our hosts and noticed the rather odd configuration showed that the VM had 2 disks provisioned (not unusual), and that the 2 disks had been presented on different storage (very unusual for non clustered VMs in our environment)

I figured, the easiest way to identify all of the VMs that are using VMDKs on multiple different datastores was PowerCli.

The result – just a one liner.

PS:7 >get-vm | ?{$_.DatastoreIdList.count -gt 1}

Name                 PowerState Num CPUs Memory (MB)
----                 ---------- -------- -----------
labserver001     PoweredOn  1        8192
labserver 17a         PoweredOn  2        1280
labserver21        PoweredOn  1        8192
labserver17b         PoweredOn  2        1152

Function: Get-Documentation

March 18, 2011 Leave a comment

Righto – As mentioned here in Get-Screenshot we can easily capture our working screen. Now more than just the novelty of having a .png file filling up a random folder…. think this concept through to automatically documenting a script / build / app install.

Function Get-Documentation ($cmd,$filename="screenshot",$fold="C:\wiki\Get-Documentation",[switch]$PAUSE,[switch]$CLS,[switch]$DISPLAY)
{
	# note use of script block $cmd =  {gf get-screenshot -de}
	# syntax Get-Documentation -cmd {gf get-screenshot -de} -PAUSE -CLS -DISPLAY

	if ($CLS) {clear}
	"`nRunning command ""$cmd""`n" | Write-Host -ForegroundColor Green
	. $cmd

	sleep 1
	if ($PAUSE) {pause}
	if ($display) {get-screenshot $filename -fold $fold  -DISPLAY} else {get-screenshot $filename -fold $fold}
}

Talking through the various param options:
$cmd………………..is the script block to execute
$filename……………name of the file, with a default of “screenshot”, but will also have datestamp appended
$fold…………………folder, default is “C:\wiki\Documentation”
[switch]$PAUSE……wait for user input before continuing
[switch]$CLS……….clear the powershell window before executing the script block
[switch]$DISPLAY….invoke the screengrab (for review purposes)

sample output from running command:
Get-Documentation {gf get-screenshot -de} SampleScreenShot -PAUSE -CLS -DISPLAY
get-screenshot

tbc.

Categories: Powershell

Function: Get-Screenshot

March 17, 2011 1 comment

Function: Get-Screenshot

Just as I was leaving for the day… From across the room came a granade:

I wish there was a way to grab a screenshot from the command line

Somewhere in the back of my mind I have a vague memory of catching this in a mail / post, and true enough, techtalkz.com had the sample I was after. I messed with it a few minutes, and refined it adding my usual variables. Then stripping out the taskbar (thanks to Shay Levi) and getting the screen size dynamically (thanks Keith Hill). The result is the Function below.

Function Get-Screenshot ($filename="PrintScreen",$ext="png",$fold="C:\temp",[switch]$DISPLAY,[switch]$FULL)
{
	$date = Get-Date -Format yyyyMMdd_HHmm
	if (!(Test-Path $fold)) {md $fold}
	$repfile = "$fold\$filename`_$date.$ext"
	
	if ($FULL) 
	{
		$screen = gwmi Win32_DesktopMonitor
		[int32]$height = $screen[0].screenHeight
		[int32]$width = $screen[0].screenWidth
	} else {
		$workarea = [System.Reflection.Assembly]::LoadWithPartialName('PresentationFramework')
		[int32]$height = [System.Windows.SystemParameters]::FullPrimaryScreenHeight
		[int32]$width = [System.Windows.SystemParameters]::FullPrimaryScreenWidth
	}
			
	[reflection.assembly]::LoadWithPartialName("System.Drawing") > $null
	$Bitmap = New-Object System.Drawing.Bitmap $width,$height
	$Size = New-object System.Drawing.Size $width,$height
	$FromImage = [System.Drawing.Graphics]::FromImage($Bitmap)
	$FromImage.copyfromscreen(0,0,0,0, $Size,([System.Drawing.CopyPixelOperation]::SourceCopy))
	$Bitmap.Save($repfile,([system.drawing.imaging.imageformat]::png)); # the acceptable values: png, jpeg, bmp, gif...
	
	if ($DISPLAY) {
		Invoke-Item $repfile
	} else {
		return "PrintScreen saved to: $repfile"
	}
}

Notes:

  • The $DISPLAY switch is a simple way to flag the output to screen
  • The mix of WMI and .NET is here to show that both can be used
  • There’s a few ideas spawned off from here, tbc

    Categories: Powershell

    Identifying SAN disk usage using WMI – Powershell – Script of the Day

    March 11, 2011 Leave a comment

    So I was commissioned with identifying the amount of actual disk space used by a bunch of Microsoft Servers that were attached to various SANs on our network. Unfortunately, despite us having a rather expensive vendoir supplied product for doing this reporting, the vendor product(s) is/are dependent on agents running on the servers to actually report back what the performance stats look like.

    I fugured that the information must be accessible via WMI so I set about trying to identify something that identified disks as being remote / SAN attached.

    I had a crack using several different WMI classes, thinking that I may need to tie the results from a hardware based query to identify physical disks, against the results of something like the win32_logicaldisk class – but was drawing a blank.

    to identify similarities / differences betwen hosts I decided to just spit our the results of the Disk / Volume classes for a handful of hosts

    I tried the following classes:
    win32_logicaldisk
    win32_DiskDrive
    Win32_Volume

    After interrogating a few hosts (some SAN attached, some not . I noticed a similarity in the device IDs returned in the following class win32_Volume.

    you see all of our servers are set to have local disk for the C: and CDROM for the Z: (so I had a control group)
    Executing the following however . . against a LONG list of server seemed to always return C: and Z: with device IDs in the format:

    \\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-806e6f6e6963}\

    Now I have looked around for an explanation as to why all the Local Disks and Local CD Roms appear with tat number at the end, but I can find no confirmation – but I figured I’d simply create a PowerShell script using this snippet of info to generate the report I require.

    First of all, the wmi query that I would need :
    gwmi -ComputerName <servername> -class win32_volume | select deviceid, driveletter

    Now all I need to do is contruct a method to repeat the above and churn out a nice Excel style report to show disk utilisation . .

    Here is the result

    
    
    Function get-sandisks ([string]$InputFilename,[string]$OutputFilename)
    {
    $servers = gc $InputFilename
    
    $MyObj = @()
    # Cycle through the servers in the file
    foreach ($server in $servers)
    {Write-Host $server -ForegroundColor Green
    # first test if we can ping the server (quicker than trying WMI straight away)
    If (Test-Connection $server -Count 1)
    {
    if (Get-WmiObject -ComputerName $server Win32_LogicalDisk -ea 0)
    {$disks = gwmi -ComputerName $server -class win32_volume | ?{$_.driveletter} #| ?{$_.deviceid -notmatch "806e6f6e6963"} #| select deviceid, driveletter
    If ($disks)
    {foreach ($disk in $disks)
    {
    $rep = "" | select "Server Name", "Drive Letter", "Disk Space", "Used Space", "Free Space", "DeviceID", "Type"
    $Rep."Server Name" = $server
    $Rep."Drive Letter" = $disk."driveletter"
    $Rep."Disk Space" = $disk | %{$_.Capacity}
    $Rep."Free Space" = $disk | %{$_.Freespace}
    $Rep."Used Space" = $Rep."Disk Space" - $Rep."Free Space"
    If ($disk.deviceid -notmatch "806e6f6e6963"){$rep.Type = "SAN"}
    Else
    {$Rep.Type = "Local"}
    $Rep."DeviceID" = $disk | %{$_.deviceID}
    Write-Host $rep
    $MyObj += $Rep
    $rep = $null
    }
    }
    }
    Else
    {
    $rep = "" | select "Server Name", "Drive Letter", "Disk Space", "Used Space", "Free Space", "DeviceID", "Type"
    $Rep."Server Name" = $server
    $Rep."Drive Letter" = "WMI"
    Write-Host $rep "WMI" -ForegroundColor Yellow
    $MyObj += $Rep
    $rep = $null
    }
    }
    Else
    {              $rep = "" | select "Server Name", "Drive Letter", "Disk Space", "Used Space", "Free Space", "DeviceID", "Type"
    $Rep."Server Name" = $server
    $Rep."Drive Letter" = "PING"
    Write-Host $rep "PING" -ForegroundColor Yellow
    $MyObj += $Rep
    $rep = $null
    }
    }
    $MyObj | sort | Export-Csv -Path $OutputFilename -NoTypeInformation
    }
    
    

    While I appreciate that this is  not 100% accurate, I simply wanted to report on space that is in use by the SAN and is no local disk, so the result is fit for my purpose.

    Copying data to a VM datastore using PowerCli – Script of the Day

    March 8, 2011 Leave a comment

    Ever needed to copy data from your local machine to a VMware datastore . .and not felt like messing around with winSCP / FastSCP, the Datastore browser etc?

    PowerCli / PowerShell lets you create a new PSProvider item for your datastore, which in turn lets you copy data using the normal Copy-Item syntax. (though using Copy-DatastoreItem instead)

    So, if you have a Datastore in your ESX environment called ‘Datatstore1’ and you want to copy an iso from your C:\ISO directory, it would be as simple as

    PS: >new-PSDrive -location (get-datastore 7523_local) -name myds -PSProvider VimDatastore -Root '\'
    Name           Used (GB)     Free (GB) Provider      Root                                               CurrentLocation
    ----           ---------     --------- --------      ----                                               ---------------
    myds                                   VimDatastore  \lonlab001@443\Prod\7523_local
    PS: >Copy-DatastoreItem -item C:\ISO\install.iso -Destination myds:\ISOS\Myiso.iso -force
    
    

    Also, as the drive is now a normal PSProvider path, normal commands like get-childitem work like they do on a local drive

    PS: >gci myds:
       Datastore path: [7523_local]
    
                LastWriteTime            Type       Length Name
                -------------            ----       ------ ----
         21/04/2010     07:40          Folder              esxconsole-4bcdbd...
         08/03/2011     16:31          Folder              ISOS
    
    

    Genius,

    Of course this gives you full access to all of the datat on your datastores directly form a PowerCli session, so you can run any sort of reports / inventories etc that you may need. Happy days . .

    Categories: Powershell, Scripting, VMWare