Powershell and Adobe AMF3

Posted by vele1655 | Posted in Automation, Powershell | Posted on 31-01-2012

Tags:

0

One of the great things that I get to do as part of the vSpecialist group at EMC on a day to day basis to work on larger solutions and sometimes making things function in ways that they weren’t designed.  The posts I throw out there are really bandaids and educational with the hope that there is enough demand for what was shown that we can get product groups to adopt the functionality into a formal software release.  The following is a link to some Powershell work I did for Adobe AMF messaging (explained below) and basically exposes a “hidden API” for an application.  I mean this because with a bit of reverse engineering and AMF you can simulate the exact calls a Flash/Flex client is making.  I will be following this up with a real example of automating a VMware application that didn’t quite have automation as a first thought. 

It’s a first, I have my first post to Github! 

https://github.com/clintonskitson/Powershell-Adobe-AMF

These scripts are about 1,000 lines of code to accomplish AMF remoting calls with Powershell.  I have to say it was definitely the most challenging thing I have ever done and really provided some good insight into Powershell and true user-friendliness and what that does to negatively move it away from a WYSIWYG environment.  The work done involves endianess, bitwise operations, bytestreams, and all kinds of cool stuff that I really hadn’t needed to be deep with before.  I had some good working models to go from so a lot of the work was transposing between 3 or so different languages into PS.

For those of you that don’t know what Adobe AMF is, here is a bit of a primer.  When building a web based application that is Flex or Flash based there are many options for populating content into a client.  Let’s break this out a bit to understand where AMF fits. 

If I create a Flex interface that contains something like a table that needs to be populated with data from a database I might have an ODBC call to the database to do this.  Another example might be where I am pulling more static information that is unrelated to a database that might populate some of my look and feel which might leverage a JSP/PHP call.  In the situation where we are pulling data such as from a database another option could be to use Adobe AMF (Action Message Format) instead of ODBC.

http://ojitha.blogspot.com/2010/04/spring-3-integration-with-blazeds-32.html (BlazeDS is another implementation of AMF)

Now you might ask, why would I use AMF if I can talk to the database directly?  I’m no expert here but here are a few thoughts.  If I look at the methods to securely communicate from a client to a server, I believe the easiest methods (and compatible with stateful inspection, load balancers, etc) is to leverage the built in capabilities of HTTPS and SSL.  AMF as a format is meant to ride on top of a RESTful architecture such as HTTP.  By way of this you can hide any of the database services from the outside world and simply filter and process requests once they come in from the AMF services.  Along with this AMF can serve as another layer of authentication between client and server with cookie and ticket verifications above and beyond HTTP authentication.

The concept of where the code lives is pretty important.  In the case without AMF, would you include the database calls and ODBC logic directly in a client distributable application?  Wouldn’t a better idea be to include that logic on the server side and simply have the client call a single method from the server which then does the database calls?  This is very similar to having something like PHP locally make requests to a database, however in the case of AMF it is a rich client (Flash) passing objects back and forth.  Anyways.. enough this conversation can go on forever.  The important thing to know about AMF from my perspective is that it is RESTful so it relies of HTTP/S architecture, and allows the remote execution of methods.

Below are a handful of places to get information and existing assemblies that allow for AMF calls.  I wrote my own implementation because I couldn’t find anything out there that worked correctly from Powershell.  What I have done is pretty focused towards a certain application and it’s limited scope of objects it required to pass with AMF.  Adding new types of objects is a matter of 6-8 lines of code now.  Others out there like FlourineFX seem to be very mature in the breadth of capabilities.

Action Message Format – Wikipedia, the free encyclopedia

AMF 3 – Adobe Open Source

Java AMF Client – BlazeDS – Adobe Open Source

FluorineFx Home

Automating VMware View Pool Membership

Posted by vele1655 | Posted in Automation, VDI | Posted on 13-01-2012

Tags:

7

Before I begin this post I want to make sure there is a pretty sharp warning attached.  What I am going to be discussing is a method in which you can programmatically adjust the members of VMware View Pools.  As far as I know this functionality does not exist via Powershell cmdlets or via a published API.  The methods in which I accomplish this task should serve solely as an example and for lab use only.  As always I hope the concept in practice can drive open some doors that previously were closed.  However, consider this method a complete divergence to existing VMware View managed desktops.

Now to continue the post.  The use cases here are interesting.  I have my own personal reasons for creating this functionality and you might have your own, so I am interested to hear your feedback since it would make the case stronger to release this through a published API. 

One of the first use cases I can provide would have to do with leveraging array based snapshots (NFS or block) and publish these new desktops to a specific pool.  This use case is very similar to what VMware View accomplishes today with composer and desktop refreshes/recomposes.  However, instead of linked clones we would be off-loading these tasks to the storage array for creating efficient linked virtual disks that serve as fresh desktops.  There are other things that Composer brings to the table which I am ignoring for this post (more to come).

A second use case I can think of would fall in the domain of Deskop as a Service offerings.  In order to keep efficient levels of desktops of certain types available at all times the current option is to over-provision and add desktops manually when the time comes for their demand.  Leveraging automation to dynamically adjust types of desktops would allow for the most efficient DaaS environment.

The third use case I can highlight I need to be a bit silent about since it is something that is an ongoing project.  I’m afraid you are going to have to wait for this one, but no doubt it will be worth it.  Let’s just say I am able to link VMware View with another VMware product using this method which traditionally would require some complicated databases to track the relationships.

Ok, so enough of the use cases, let’s dive into the details. 

 

We will be splitting the post up as follows.

  • VMware View 5.0 Configuration Database (LDAP)
  • Script in Action (custom_vmware_view.ps1)

 

VMware View Configuration Database (LDAP)

Before diving into the details it is important to understand some of the basics behind how the View Connection brokers maintain their configuration.  As far as I can tell there is only one area that I have found that holds configuration information.  This being an LDAP database on the View Connection brokers.  I hadn’t leveraged LDAP as a replicated database prior but after digging deeply into how LDAP here is used it is a very simple and cool use case.  One of the big benefits of using LDAP is the ability to leverage Microsoft ADAM to perform synchronization among multiple connection brokers to allow for front end redundancy. 

One of the great things about this approach is also the simplicity behind the user interface and the possibilities of manipulating this data.  Before the scripted manipulation portion, let’s dig into the manual methods to see and possibly manipulate the database. 

*Again, what you are seeing below is absolutely not supported by EMC or VMware.  I do not condone the use of what you are going to see other than for informational and educational purposes.*

This method is highly documented across the internet, so nothing new here.  Let’s start by opening an LDAP browser that comes with Microsoft Server 2008.  Go to Start –> Run and type “ADSI edit”.  It should show up in the top left corner of the start menu as follows.

image

 

In order to open the connection you need to specify a “Distinguished Name” and a Computer as a target.  The distinguished name should be exactly as follows “dc=vdi,dc=vmware,dc=int”.  The domain or server should be the IP or hostname of the connection broker.  If there are problems connecting, make sure you are opening the ADSI Edit application with administrator access to the VIew Connection broker server. 

image

 

Once you connect you should see the following screen with “Default naming context” appear.  Go ahead and double click this item, and then the “DC=vdi,DC=vmware,DC=int” should appear.  From there you should be able to expand this and start diggging through the Computer Names and Organizational Units.  Some of the important ones that we will be working with are “Servers” which are the desktops, and “Server Groups” which are the Desktop Pools.  You will find that navigating through the information and finding what you’re looking for under servers might be a bit complex due to how this is organized.

image

 

Just for quick reference, one thing that I’ve found in trying to automate the install of the VMware View agent is that it is easy to verify whether the agent is configured correctly or not by viewing the Agent’s registry settings from the desktop.  Go ahead and open up a desktop and open regedit to the following key HKEY_LOCAL_MACHINE –> Software –> VMware, Inc. –> VMware VDM –> Node Manager.  Notice the Server DN, and the Server Pool DN.  These link directly to what you see in the View LDAP database above.

image

 

Ok, so as you can see we have a working database via LDAP for the View Connection Broker.  In order to start populating pools dynamically there is a attribute under the “Server Groups” (pools) OU that specifies which desktops Computer Names are a part of the pool.  This is the attribute that we will be manipulating to dynamically bring in and remove desktops from pools.

image

 

 

The Script in Action

Now let’s start digging into the script and what we are achieving with it.  From what you saw above and what I experienced in digging into this topic it was pretty clear that we needed a script to assist in browsing the View LDAP database which then helps us manipulate it as well. 

Before getting too deep, here is the script..  By downloading you agree that this script is for educational and non-production environments and that the use of scripts will most likely lead to support problems.

In order to leverage the different built in functionality you can leverage the different actions that we have created functions for.

Action – View-Get-Objects – Get all objects from a specified OU or CN

.\custom_vmware_view_ps.ps1 -username username -password passsword -viewConnBroker viewConnBroker -action view-get-objects -ou servers

.\custom_vmware_view_ps.ps1 -username username -password passsword -viewConnBroker viewConnBroker -action view-get-objects -cn roles

image

 

As you can see we are adding a “ | select -first 1” on the end of the first example above which returns only the first desktop.  One of the great things about the script is that we are outputting all of the information as properly formatted Powershell objects which means we can leverage native cmdlets like Group and Sort.

The following example will show you the amount of desktops in each type of pool.

.\custom_vmware_view_ps.ps1 -username username -password passsword -viewConnBroker viewConnBroker -action view-get-objects -ou servers | select “pae-DisplayName”,”pae-MemberDnOf” | group “pae-MemberDNof”

The following will show the desktops within the first pool.  You can switch out the “select –first 1”, with “where {$_.name -match “poolname”}” to pick a certain lab.

.\custom_vmware_view_ps.ps1 -username username -password passsword -viewConnBroker viewConnBroker -action view-get-objects -ou servers | select “pae-DisplayName”,”pae-MemberDnOf” | group “pae-MemberDNof” | select –first 1 | %{ $_.group | select “pae-DisplayName” }

image

 

As you can see below, we substituted the “servers” for “server groups” as the OU parameter and got the desktop pools.  This will work for anything you see in ADSI edit that shows up as an OU, and you can specify CN as a parameter for things in the top level that show up as a CN.

image

Action – View-Get-Object – Get a specific object

This action is actually called by the next action we are going to specify.  There are three parameters which I can try and write out here to have it make more sense.  In order to get an object we specify the OU in which it lives, we then specify a where clause based on a field and the value is what is contained in that field.

Action – View-Get-Desktop – Get a specific desktop

We call the View-Get-Object here with the following parameters ($ou = “servers”, $field=”pae-DisplayName”,$value=”desktop name”).  The parameter you specify with this action is the “name”. 

.\custom_vmware_view_ps.ps1 -username username -password passsword -viewConnBroker viewConnBroker -action View-Get-Desktop –name desktopName | fl *

image

 

Action – View-Remove-Desktop – Remove Desktop from Pool

In order to get the desktop out of a pool we actually execute the above actions behind the scenes.  First we get the desktop CN you are looking for, then we find the pool CN.  This is followed by manipulating the pae-MemberDNof to exlude the CN of the desktop specified.

.\custom_vmware_view_ps.ps1 -username username -password passsword -viewConnBroker viewConnBroker -action View-Remove-Desktop -name desktopName

 

Action – View-Add-Desktop – Add Desktop to Pool

This action behind the scenes is very similar to the remove.  However, instead of removing from the pae-MemberDNof, we add it to groups of desktop CNs in that attribute.

.\custom_vmware_view_ps.ps1 -username username -password passsword -viewConnBroker viewConnBroker -action View-Add-Desktop -name desktopName -pool poolName

 

 

That’s all for now!  I am interested to hear some use cases so we can fully understand the usefulness of this type of functionality.  Feel free to add comments.

 

Download the script hereBy downloading you agree that this script is for educational and non-production environments and that the use of scripts will most likely lead to support problems.

Programmatically Leveraging SSH with Powershell

Posted by vele1655 | Posted in Automation, Powershell | Posted on 11-01-2012

Tags:

0

When dealing with automation you tend to get into jams sometimes where either you need to quickly turn around some information that is readily available via SSH or you need to create a scripted workflow to accomplish a task.  I personally have thoroughly used this technique to take a concept to reality with minimal amounts of time and effort.

This post is one of those massive scalable tools that I have in my bag that seems to be well worth the time to look at so you have it as an option next time you get a crazy idea between Msft and SSH enabled hosts.

Now for the meat of it, I am looking for a couple of things with this post.  Firstly, I wanted to share my approach to SSH and Powershell as I haven’t found it clearly laid out online.  And second I am looking to start a discussion on this topic to get feedback around better or more cutting edge methods than “screen scraping” SSH (other than APIs).

 

Your First Powershell SSH Script

There are four simple steps that should get you cooking on this concept. 

  • Download the Scripts
  • Identify a unique string
  • Configure the script
  • Test and run the script

1) Download the Scripts

The following files include all of the necessary scripts and assemblies that allow us to create SSH connections via Powershell and .NET.  We will dissect the example use of these scripts (ps_ssh_example.ps1) to show how we leverage the SSH methods provided via the assemblies.  BTW.   If you have never loaded assemblies manually into Powershell, don’t worry we do this for you.  The real directions you need to get this working are provided below.

ps_ssh_example.zip (only download this file)

http://downloads.sourceforge.net/sharpssh/ (where SSH assemblies came from)

 

2) Identify a unique string to “expect” when the statement is completed

For now I am going to assume that you are trying to SSH to a Linux host.  Go ahead and run a “uname –a” command from the Linux host so you have it handy and continue the directions below.  Hopefully it will make sense when you get through the next section.

image

 

3) Configure the script

This script that we are using here is primarily an example of how to issue remote commands via SSH and return the output.  For this purpose we have broken the configurable portions into variables within the script to make it easy to understand.

The first two items shown below (in the beginning of ps_ssh_example.ps1) are critical to this whole script working and take some explaining.  Since SSH itself really has no concept of a command starting or finishing and when to stop listening we rely on “expects” to do this hard work for us.  The expects are configured in two parts.  The first part, $expectCmd is a command that we run with every SSH command.  So for example, if I issue a “ls”, we are actually going to issue a “ls;uname –a” based from the variables below.  This is important so that we know when to look for the end of the output.  But you may be asking, “how about just a line like STOP” to determine the end?  If we simply parse for STOP this is going to mean we see the first line as the end.  Now, you might be saying “Hey that’s a bit hokey.”  This is partly why I am writing this post.  There is no doubt a more streamlined approach from Powershell.

The $expect portion below is based on the output from the command.  Again, we issue a “ls;uname –a” and then we are able to screen scrape the output until we get to what we know that output should be “Linux irvine-celerra1 2”.  Important note here, if this is in any way incorrect then the script will hang the Powershell session.  So it is important that you think about the command running, in our case uname, and you make sure it has obsolescence built in.

$expectCmd = "uname -a"

$expect = "Linux irvine-celerra1 2"

4) Test and run the script

And now comes the best part, having Linux output show up in Powershell.  When you run the script what we are expecting is for the following output from iostat to show up in a repeating fashion every second.  The time to seeing the first output depends on the normal time to SSH to your host.  If you see the output as follows then all is good, you have your first working SSH Powershell script.  If you have a script that is hanging, go back to the previous section and check your expect variables to make sure that when you issue the command in $expectCmd, the output matches the $expect that you set.  Otherwise, the only thing stopping this from running successfully should be your authentication.

Output from SSH

image

Output from Putty (SSH)

image

 

Reviewing the script

Now as always I want to dig a bit deeper into what exactly is happening under the covers so you understand the script and what you can do with it.  I have pasted the complete example script at the very bottom of this post for review.

  • Cool Trick #1 – Getting the script’s path ($MyInvocation)
  • Cool Trick #2 – Intercepting Control-C’s (TreatControlCAsInput)
  • Cool Trick #3 – SSH commands without Expects
  • Cool Trick #4 – SSH commands with Expects
  • Cool Trick #5 – Interpreting Start and End lines (select-string –pattern)

 

Set your variables as described above.

$expectCmd = "uname -a"

$expect = "Linux irvine-celerra1 2"

$serverIp = "serverIp"

$username = "root"

$password = ""

 

Cool Trick #1 – Getting the script’s path

The below lines serve two purposes, 1) load the SSH functions and underlying assemblies 2) sets the path for loading to be based on where the script was executed from.  This helps if you call a script from c:\scripts\xx.ps1 and you aren’t in the same directory. 

$spath = (Split-Path -parent $MyInvocation.MyCommand.Definition) + "\ssh_function.ps1"

. $spath

 

An important thing to mention with this approach is that because we can press Ctrl-C we have the ability to end the SSH session without formally closing the session.  See the picture below for the output during Powershell if we stop the script with a Ctrl-C.

image

 

Cool Trick #2 – Intercepting Control-C’s

Instead of this, we employ a bit of a trick in Powershell.  We use the console namespace to set a method called “TreatControlCAsInput” to true.  This allows us to trap all of the Ctrl-C’s received during the scripts execution and do other things when these buttons are sensed versus just quitting.

[console]::TreatControlCAsInput = $true

The above will tell Powershell not to execute on that Ctrl-C command, which allows us to, during a certain portion of the script, detect these keys and then execute our own clean quit by formally disconnecting from the SSH session.

function cust_sleep {

param($sleep)

    1..($sleep) | %{

        sleep 1

        if ($Host.UI.RawUI.KeyAvailable -and (3 -eq [int]$Host.UI.RawUI.ReadKey("AllowCtrlC,IncludeKeyUp,NoEcho").Character)) {

            [console]::TreatControlCAsInput = $false

            Remove-SshSession

            write "Exiting cleanly and closing SSH session"

            exit

        } 

    }

}

With the TreatControlAsCAsInput set we end up outputting something similar to what you see below when we press Ctrl-C.

 image

Now let’s step into how we are executing the commands and doing some fancy parsing to gather from the SSH output the command output.

 

Below we are going to be creating a function that we will reuse with any SSH command.

function execp_ssh ($tmpCmd) {

    $tmpCmd=$tmpCmd.replace(‘"’,‘\"’)

Cool Trick #3 – SSH commands without Expects

Here comes the first important part, we are using a new SSH function “send-ssh” which sends command without expecting output.  In this case we are actually setting a Linux variable that will hold the command we are sending.

    send-ssh (‘cmd="’+$tmpCmd+‘"’)

Cool Trick #4 – SSH commands with Expects

The following SSH function “invoke-ssh” will invoke and output the results which we capture in $tmpOut.  Notice how we issue a “echo `$cmd | sh”, this tells bash to echo the command and then running it with “sh”.  We then follow this command with the $expectCmd command and then pass the SSH function the $expect variable so it knows when to stop looking for output and return the results.  You may be looking at the first portion and asking why we set the variables in Linux before executing?  It is something that I ran into a while back where the library at certain characters might issue a blank space in the command.  So I was able to limit the size of the commands by encapsulating them in variables.  A good troubleshooting move here is to look at the “history” command during a manual SSH to see what commands are making it over and in what form.

    [array]$tmpOut = invoke-ssh "echo `$cmd |sh;$expectCmd" $expect

Cool Trick #5 – Parsing for line numbers

The Next two lines take the output from the above command and apply pattern matching to find the appropriate line number start and end.  You can see with the pattern of “;$expectCmd” we are looking for the line that includes the command that we ran.  And the “$expect” pattern matches the line that includes the output that specified to match for the end.  Also notice, the “) – 2” which means take the line number that you found and remove 2 lines (1 since we count 0 in arrays and 1 in line numbers, and 1 meaning the previous line).  We finish it up with a $tmpOut[(… which outputs the specified line ranges.

    $tmpStartLine = $tmpOut | select-string -pattern ";$expectCmd" | %{ $_.linenumber } | select -last 1

    $tmpEndLine = ($tmpOut | select-string -pattern $expect | %{ $_.linenumber } | select -first 1) - 2

    if(!$tmpStartLine) { $tmpStartLine = 0 }

    if(!$tmpEndLine) { $tmpEndLine = $tmpOut.count-1 }

    $tmpOut[($tmpStartLine)..($tmpEndLine)]

}

 

Now that we have declared our function we are using for the command execution, the next step is to actually execute on it.  The following will login through SSH, and then repetitively execute the SSH command of “iostat” as well as return those results to the screen.

New-SshSession $username $password $serverIp

for($x) {

    [array]$arrOut = execp_ssh ("iostat")

    $arrOut

    cust_sleep -sleep $sleep

}

remove-sshsession

exit

And that does it for my typical approach to programmatically using SSH.  Where I go from here is the data cleansing steps where I would massage the $arrOut array into something like an array of PSObjects that can be passed in any number of ways.  I have found that if I can get Linux commands to output in CSV that this method can be very clean and reliable. 

I’m hoping that what you have seen above has opened a few doors.  This has helped me tremendously with making tough things and typically after thoughts a reality in automation and stats collection.

 

Where have I used this? ESX/i, vSCSIstats, Avamar, DART, Linux, VPLEX, VNXe, Isilon

EMC Community Network – ECN- Powershell scripts for VPlex

Duplicating a vApp – CPU and Memory Settings

Posted by vele1655 | Posted in Automation | Posted on 07-01-2012

Tags:

0

In a previous post, Duplicating a vApp  – The Startup Order, I took a first stab at defining one of the many facets of a vApp that may be important to duplicate.  After putting a bit more thought into the topic I began to realize that the concept that I was really after had do with a vApp Template.  This is a concept isn’t new to the VMware community, see the links below, however I believe my approach to it and the underlying personal drivers behind making it a reality might be slightly different. 

My efforts here are really no different than things I see at some of the shops that I work with that tend to script out their exact needs since it might not exist as a product.  This approach alike any custom development lacks sustainability, which drives one of my desires to publish some of this information.  Hopefully there are things that make sense on this blog that can drive some cool things to happen and the functionality presented can be a part of official releases.  So yes, a fork from a good path, but possibly only a a temporary one.

It is also important to mentioned as discussed above that the concept of the vApp Template isn’t new.  It has been formally adopted by VMware and is a part of the vCloud Director framework.  This makes sense as well since what we are really dealing with here is automating provisioning tasks which is a core requirement of any Cloud based management software.  And as always, how deep and wide that provisioning tool goes defines it’s maturity and capabilities.

http://www.doublecloud.org/2010/08/secret-of-vapp-template-in-vsphere/

http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1026327

Now, if I was to paint the picture of a perfect vApp Template is might include things like what you see below.  Some of this stuff has been tackled in vCloud Director for multi-tenancy purposes at higher levels among the Virtual Datacenters.  These VDCs are at the end of the day just (vSphere Resource Pools) under the covers.  Now you might ask what am I presenting here that could be seen as different?  My personal needs were to control resources at the most granular level possible and duplicate them from a vApp Template in the most efficient ways possible.

  • Startup Order (vApp Container)
  • Memory Resource Settings (VM Object)
  • CPU Resource Settings (VM Object)
  • Storage IO Control Settings (VM Object)
  • Network Connection Port Groups (VM Object)
  • Linked Clones to a Specific Datastore
  • Guest Customizations

 

Duplicating Memory and CPU Resource Settings

Option #1 – After Creating a new vApp of VMs

$source_vapp_name = "sourcevappname"

$clonename = "clonevappname"

$VAppView1 = get-vapp $source_vapp_name | get-view

$VAppView2 = get-vapp $clonename | get-view

$vAppView1.vAppConfig.EntityConfig | %{

    $e1=$_

    $vAppView2.vAppConfig.EntityConfig |

    where {$_.tag -match $e1.tag} | %{

        $sourceResourceConfig = get-VMResourceConfiguration $e1.tag

        $cloneResourceConfig = get-VMResourceConfiguration $_.tag

        $arrProperties = @("CpuReservationMhz","CpuLimitMhz","MemReservationMB","MemLimitMB")

        invoke-expression ("set-vmresourceconfiguration -config `$cloneResourceConfig "+(

            $arrProperties | %{ if ($sourceResourceConfig.$_ -ge 0) { "-$($_) $($sourceResourceConfig.$_)" } else { } }) -join " "

        )

    }

}

If you have seen the first post on Duplicating a vApp you will see that we we are performing the matching the VMs in a vApp in the same way where we expect the parent VM to match a portion of the child VM’s name (ParentWeb matches ParentWeb01).  Now let’s step through this to see what’s really happening.

 

We get the views of the vApps here.

$VAppView1 = get-vapp $source_vapp_name | get-view

$VAppView2 = get-vapp $clonename | get-view

 

We iterate through and set $e1 to the current VM in the vApp source vApp.

$vAppView1.vAppConfig.EntityConfig | %{

    $e1=$_

This starts an iteration through the second vApp and we apply a where clause so we can match on the VM name of the child vApp to the parent vApp, once we find a match we move on.

    $vAppView2.vAppConfig.EntityConfig |

    where {$_.tag -match $e1.tag} | %{

The following gets the current resource configuration objects from the source and clone VMs.

        $sourceResourceConfig = get-VMResourceConfiguration $e1.tag

        $cloneResourceConfig = get-VMResourceConfiguration $_.tag

Here we create an array with the name of the properties that we are targeting to bring into the cloned VM.

        $arrProperties = @("CpuReservationMhz","CpuLimitMhz","MemReservationMB","MemLimitMB")

And finally we create a dynamic command using invoke-expression that ends up looking similar to the following “set-VMResourceConfiguration –config $cloneResourceConfig –CpuReservationMhz x…”  This is necessary since the configuration object properties are read-only.  An alternative would be to build a new object dynamically and set all necessary properties via get/set.  Notice the “`” before $cloneResourceConfig, yes this is the shift ~, which preserves the $variable for the invoke-expression.

        invoke-expression ("set-VMResourceConfiguration -config `$cloneResourceConfig "+(

            $arrProperties | %{ if ($sourceResourceConfig.$_ -ge 0) { "-$($_) $($sourceResourceConfig.$_)" } else { } }) -join " "

        )

And that’s it for Option 1!  There are other things that you can duplicate by adding those names to the Properties array, do a “get-VMResourceConfiguration | fl *” to see all available properties.

Option #2 – During VM Cloning

This method is definitely a bit more elegant, but requires that you leverage assemblies directly to create a configuration spec.  There are a lot of examples on the internet for doing this, so I will try and be as meat and potatoes as possible here.  The following will create a linked clone on a datastore filtered by $dsMatch1 that has the most free space.  And of course the main purpose of this example is showing how we can get the VMware.Vim.VirtualMachineConfigSpec which has the CPUAllocation and MemoryAllocation objects that we duplicate into the new VM.

 

$cloneSpec = new-object Vmware.Vim.VirtualMachineCloneSpec

$cloneSpec.config = new-object VMware.Vim.VirtualMachineConfigSpec

$cloneSpec.config.cpuallocation = $sourceVMView.config.cpuallocation

$cloneSpec.config.memoryallocation = $sourceVMView.config.memoryallocation

$cloneSpec.Snapshot = $sourceVM.Snapshot.CurrentSnapshot

$cloneSpec.Location = new-object Vmware.Vim.VirtualMachineRelocateSpec

$cloneSpec.Location.pool = get-view -id $destResourcePool.id | %{ $_.moref }

$cloneSpec.Location.Host = $objVMHost | get-view | %{ $_.moref }

$cloneSpec.Location.Datastore = $objVMHost | get-datastore |

    where {$_.name -match $dsMatch1} | sort FreeSpaceMB -desc | select –first 1 |

    get-view | %{ $_.moref }

$cloneSpec.Location.DiskMoveType = [Vmware.Vim.VirtualMachineRelocateDiskMoveOptions]::createNewChildDiskBacking

$sourceVM.CloneVM($cloneFolder, $cloneName, $cloneSpec)

 

 

Now let’s break this down a bit. 

 

The following establishes a new VirtualMachineConfigSpec object where we grab the source VM’s existing CPUAllocation and MemoryAllocation objects to set on the target VM.

$cloneSpec = new-object Vmware.Vim.VirtualMachineCloneSpec

$cloneSpec.config = new-object VMware.Vim.VirtualMachineConfigSpec

$cloneSpec.config.cpuallocation = $sourceVMView.config.cpuallocation

$cloneSpec.config.memoryallocation = $sourceVMView.config.memoryallocation

 

This line specifies which snapshot to use when establishing the linked clone.

$cloneSpec.Snapshot = $sourceVM.Snapshot.CurrentSnapshot

 

The following specifies which resource pool to place the clone VM into, and which host to register the clone VM with.

$cloneSpec.Location = new-object Vmware.Vim.VirtualMachineRelocateSpec

$cloneSpec.Location.pool = get-view -id $destResourcePool.id | %{ $_.moref }

$cloneSpec.Location.Host = $objVMHost | get-view | %{ $_.moref }

 

Below we choose a datastore based on a filter of $dsMatch1, sorts the datastores by their free space, and then we choose the first datastore and set it as our target datastore.

$cloneSpec.Location.Datastore = $objVMHost | get-datastore |

    where {$_.name -match $dsMatch1} | sort FreeSpaceMBdesc | select –first 1 |

    get-view | %{ $_.moref }

 

The following specifies that we are doing a linked clone targeted at an existing snapshot, and then to execute the CloneVM method with the associated configuration specs and details that we specified earlier.

$cloneSpec.Location.DiskMoveType = [Vmware.Vim.VirtualMachineRelocateDiskMoveOptions]::createNewChildDiskBacking

$sourceVM.CloneVM($cloneFolder, $cloneName, $cloneSpec)

 

 

Pretty easy eh? 

An FC dive: Preparing FC Switches for a VPLEX Metro Install

Posted by vele1655 | Posted in Infrastructure | Posted on 06-01-2012

2

I just completed the install of VPLEX and thought I would post a bit about preparing the FC infrastructure for a specific type of install.  I am not going to go into what VPLEX is here, other than it is a killer storage virtualization technology from EMC (who I work for) that allows for running stretched VMware clusters in an Active-Active storage array configuration.  This means we have multiple storage arrays under the covers and we can perform vMotions in order to move workloads between blocks of infrastructure (Network+Storage+Compute).  This helps for workload mobility, disaster avoidance, and can be complimentary to disaster restart scenarios (VMware SRM).  See teammate, Scott Lowe’s blog for some information on VPLEX.

 

A Quick Review of VPLEX Storage Objects – blog.scottlowe.org – The

A Deeper Look at VPLEX – blog.scottlowe.org – The weblog of an IT

Using VPLEX and Data Replication Together – blog.scottlowe.org

VPLEX – Virtualization and Private Cloud – EMC

 

Hardware Specs

  • Hardware Version: VPLEX VS2
  • Operating Mode: 2 x Single Engine (Metro), each engine attached to its own storage array
  • FC Switches: 4x Cisco MDS 9148 5.0(4d)
  • VPLEX Engine Communication: FC (IP is an option for module or FCIP through an ISL I believe)
  • Storage Array: EMC VNX 5700

 

WARNING: These notes are my own from the install that I performed.  Please use this information simply as a reference.  If you find any information from EMC that conflicts with this, EMC’s information is of course correct.

I am assuming before you look through the following that you have unboxed, racked, stacked, and followed the directions from the awesome VPLEX manuals.  The rest of what you see will be focused on the FC infrastructure and ensuring that it is prepared zoned and configured appropriately to allow for communication between the VPLEX engines.  Zoning and FC configuration from the ESX hosts to VPLEX is very easy (when possible zone to less engines per host).  See the Implementation and Planning Best Practices for EMC VPLEX regarding VPLEX to storage array zoning since it depends on the storage array.

 

There are four categories of FC connectivity that occurs within and among the VPLEX engines.

  • LocalCOM – Connectivity between directors among a cluster of VPLEX engines.  In a single engine case we are doing direct connect between VPLEX directors.  In a multi-engine cluster you would use an internal SAN switch (different from customer connected SAN switch) to provide connectivity in the backend between the directors of the cluster.
  • WANCOM – FC/Ethernet connectivity between directors of different clusters (in our case FC, only in Metro and Geo)
  • BE – Connectivity between VPLEX directors (initiators) and back-end storage (targets) that is to be virtualized
  • FE – Connectivity between hosts (initiators) and VPLEX directors (targets)

An overview of what is to be covered

  • Configuring WANCOM VSANs
  • Creating an ISL
  • Zoning WANCOM ports

Useful commands on MDS

  • sh flogi databse – List the logged in ports and their associated WWN’s
  • sh zoneset active – List the active zonesets and which ports are logged in
  • sh fcalias – List the FCALIAS database to show device name to WWN associations
  • sh fcdomain – Show the active FCDOMAIN’s for the configured VSANs

 

1) Configuring WANCOM VSANs

The below is assuming you will be switching out my VSAN numbers for your own.  What we are doing is pretty simple.  We are creating a VSAN on each of the switches and aligning this new VSAN between the primary switches of the blocks and the secondary switches of the blocks.  Once we create an ISL between said switches we will then be able to zone initiators and targets among the distinct blocks of infrastructure.  The only initiators and targets that will be zones are for the VPLEX unit (WANCOM ports for VPLEX metro FC communication).  We will not be zoning ESX hosts to adjacent infrastructure.  Make sure the VSAN numbers do not align with existing VSAN numbers in use!

“fcdoman 1 static vsan 101” – This line creates an FCDOMAIN of id 1 within the VSAN 101.  An FCDOMAIN is like a Layer-2 subnet in the FC world.  In order for an initiator to talk to a target on an opposite switch it needs to be in the same VSAN (if not Inter-VSAN routing) and it needs to exist in an FCDOMAIN in that switch.  In this case we join switches together by way of a VSAN and ISL (Inter Switch Link), and the initators talk to the targets via different FCDOMAIN (where the FC services handle what we would consider in Ethernet L3 routing to get between FCDOMAINS).  FCDOMAIN id’s are unique per VSAN.

“zoneset distribute full vsan 101” – To save on configuration we are telling the principal switch (lowest priority number) to distribute the zonesets to it’s subordinates

 

From BLOCK01 Switch-A


vsan database

vsan 101 name "VPLEX_WANCON_VSAN101"

fcdomain priority 1 vsan 101

fcdomain domain 1 static vsan 101

zoneset distribute full vsan 101

fcdomain restart vsan 101

From BLOCK01 Switch-B


vsan database

vsan 102 name "VPLEX_WANCON_VSAN102"

fcdomain priority 1 vsan 102

fcdomain domain 1 static vsan 102

zoneset distribute full vsan 102

fcdomain restart vsan 102

From BLOCK02 Switch-A


vsan database

vsan 101 name "VPLEX_WANCON_VSAN101"

fcdomain priority 2 vsan 101

fcdomain domain 2 static vsan 101

fcdomain restart vsan 101

From BLOCK02 Switch-B


vsan database

vsan 102 name "VPLEX_WANCON_VSAN102"

fcdomain priority 2 vsan 102

fcdomain domain 2 static vsan 102

fcdomain restart vsan 102

 

2) Creating an ISL

The below is assuming you will be switching out my VSAN number and FC ports for your own.  Here we are creating an Inter Switch Link between the primary/primary switches as well as the secondary/secondary.  This ISL will carry the VSAN traffic for the WANCOM connectivity as described above.

 

“switchport trunk allowed vsan 101” – Only allow advertise the 101 VSAN to the other switch.  This is critical to ensure we isolate production VSANs from each other across the ISL and prevent VSAN 101 isolation in the case of configuration problems.

From BLOCK01 Switch-A and BLOCK02 Switch-A


interface fc1/39

port-license acquire

channel-group 1

 

interface fc1/40

port-license acquire

channel-group 1

interface port-channel 1

switchport trunk allowed vsan 101

From BLOCK02 Switch-A and BLOCK02 Switch-A


interface fc1/39

port-license acquire

channel-group 1

 

 

interface fc1/40

port-license acquire

channel-group 1

interface port-channel 1

switchport trunk allowed vsan 101

 

Bring up all of the interfaces and port-channels on all switches


int fc1/39

no shut

int fc1/40

no shut

int port-channel 1

no shut

 

Check your port connectivity with a “sh int brief” command.  You should see the status of the physical ports and the port-channel at the bottom of the page as trunking.

image

image

 

Check your FCDOMAIN status to see if the switches have properly communicated and agreed on their priorities and roles.  As the below describes, you should see Switch-A and Switch-B in the first block being reported at the “Principal Switch” with the interfaces for ISL connectivity listed at the bottom showing the role as Downstream.

Switch-A of BLOCK01

image

 

As you can see below the switch in the adjacent block is showing his role as Subordinated Switch.”  This means that he will rely on the Principal switch to carry out domain services.

Switch-A of BLOCK02

image

 

3) Zoning WANCOM Ports

At this point we are assuming you have gone through the above and have Primary->Primary switch communicating and the FCDOMAINs working as described above.  We are also assuming that you have followed the VPLEX Configuration Guide up to the point where it has enabled the WANCOM ports.  The next step is then to create zones and zonesets on the primary switches that will then get distributed to the secondaries that allow for the WANCOM ports to communicate between VPLEX clusters.

 

Since VPLEX has enabled the WANCOM ports for FLOGI’s we can go to the switch and view the WWNs of those ports.  There are other means to get the WANCOM ports but this is how I typically find WWN port name WWN that are to be used for zoning.

image

 

When doing zoning I always use FCALIAS’s to simplify and make the zoneset’s a bit more dynamic and easier to read and understand.  By doing this I can easily issue a command like “sh zoneset active” and see the names of the WWN’s that are logged in or out.

fcalias name BLOCK2_VPLEX_WANCON_E1D1_p2_1 vsan 101  pwwn 50:00:14:42:70:02:59:20

fcalias name BLOCK2_VPLEX_WANCON_E1D2_p2_1 vsan 101  pwwn 50:00:14:42:60:02:59:20

fcalias name BLOCK1_VPLEX_WANCON_E1D1_p2_1 vsan 101  pwwn 50:00:14:42:70:4a:5e:20

fcalias name BLOCK1_VPLEX_WANCON_E1D2_p2_1 vsan 101  pwwn 50:00:14:42:60:4a:5e:20

 

And then I use those aliases in the zone’s.

zone name BLOCK1_VPLEX_WANCON_E1D1_p2_1_to_BLOCK2_E1D1_p2_1_E1D2_p2_1 vsan 101    member fcalias BLOCK2_VPLEX_WANCON_E1D1_p2_1    member fcalias BLOCK2_VPLEX_WANCON_E1D2_p2_1    member fcalias BLOCK1_VPLEX_WANCON_E1D1_p2_1

zone name BLOCK1_VPLEX_WANCON_E1D2_p2_1_to_BLOCK2_E1D1_p2_1_E1D2_p2_1 vsan 101    member fcalias BLOCK2_VPLEX_WANCON_E1D1_p2_1    member fcalias BLOCK2_VPLEX_WANCON_E1D2_p2_1    member fcalias BLOCK1_VPLEX_WANCON_E1D2_p2_1

zone name BLOCK2_VPLEX_WANCON_E1D2_p2_1_to_BLOCK1_E1D2_p2_1_E1D1_p2_1 vsan 101    member fcalias BLOCK2_VPLEX_WANCON_E1D2_p2_1    member fcalias BLOCK1_VPLEX_WANCON_E1D1_p2_1    member fcalias BLOCK1_VPLEX_WANCON_E1D2_p2_1

zone name BLOCK2_VPLEX_WANCON_E1D1_p2_1_to_BLOCK1_E1D2_p2_1_E1D1_p2_1 vsan 101    member fcalias BLOCK2_VPLEX_WANCON_E1D2_p2_1    member fcalias BLOCK1_VPLEX_WANCON_E1D1_p2_1    member fcalias BLOCK1_VPLEX_WANCON_E1D2_p2_1

 

We then take these zones and include them in a single zoneset.

zoneset name VSAN_101 vsan 101    member BLOCK1_VPLEX_WANCON_E1D1_p2_1_to_BERT_E1D1_p2_1_E1D2_p2_1    member BLOCK1_VPLEX_WANCON_E1D2_p2_1_to_BERT_E1D1_p2_1_E1D2_p2_1    member BLOCK2_VPLEX_WANCON_E1D2_p2_1_to_ELMO_E1D2_p2_1_E1D1_p2_1    member BLOCK2_VPLEX_WANCON_E1D1_p2_1_to_ELMO_E1D2_p2_1_E1D1_p2_1

We then take that zoneset and activate it to the VSAN with the following command “zoneset activate name VSAN_101 vsan 101”.  I am going to paste the same code for the other SWITCH-B of the BLOCK1 below.

fcalias name BLOCK2_VPLEX_WANCON_E1D1_p2_0 vsan 102    member pwwn 50:00:14:42:60:02:59:21

fcalias name BLOCK2_VPLEX_WANCON_E1D2_p2_0 vsan 102    member pwwn 50:00:14:42:70:02:59:21

fcalias name BLOCK1_VPLEX_WANCON_E1D1_p2_0 vsan 102    member pwwn 50:00:14:42:70:4a:5e:21

fcalias name BLOCK1_VPLEX_WANCON_E1D2_p2_0 vsan 102    member pwwn 50:00:14:42:60:4a:5e:21zone name BLOCK1_VPLEX_WANCON_E1D1_p2_0_to_BLOCK2_E1D1_p2_0_E1D2_p2_0 vsan 102    member fcalias BLOCK2_VPLEX_WANCON_E1D1_p2_0    member fcalias BLOCK2_VPLEX_WANCON_E1D2_p2_0    member fcalias BLOCK1_VPLEX_WANCON_E1D1_p2_0

zone name BLOCK1_VPLEX_WANCON_E1D2_p2_0_to_BLOCK2_E1D1_p2_0_E1D2_p2_0 vsan 102    member fcalias BLOCK2_VPLEX_WANCON_E1D1_p2_0    member fcalias BLOCK2_VPLEX_WANCON_E1D2_p2_0    member fcalias BLOCK1_VPLEX_WANCON_E1D2_p2_0

zone name BLOCK2_VPLEX_WANCON_E1D2_p2_0_to_BLOCK1_E1D2_p2_0_E1D1_p2_0 vsan 102    member fcalias BLOCK2_VPLEX_WANCON_E1D2_p2_0    member fcalias BLOCK1_VPLEX_WANCON_E1D1_p2_0    member fcalias BLOCK1_VPLEX_WANCON_E1D2_p2_0

zone name BLOCK2_VPLEX_WANCON_E1D1_p2_0_to_BLOCK1_E1D2_p2_0_E1D1_p2_0 vsan 102    member fcalias BLOCK2_VPLEX_WANCON_E1D2_p2_0    member fcalias BLOCK1_VPLEX_WANCON_E1D1_p2_0    member fcalias BLOCK1_VPLEX_WANCON_E1D2_p2_0zoneset name VSAN_102 vsan 102    member BLOCK1_VPLEX_WANCON_E1D1_p2_0_to_BLOCK2_E1D1_p2_0_E1D2_p2_0    member BLOCK1_VPLEX_WANCON_E1D2_p2_0_to_BLOCK2_E1D1_p2_0_E1D2_p2_0    member BLOCK2_VPLEX_WANCON_E1D2_p2_0_to_BLOCK1_E1D2_p2_0_E1D1_p2_0    member BLOCK2_VPLEX_WANCON_E1D1_p2_0_to_BLOCK1_E1D2_p2_0_E1D1_p2_0

zoneset activate name VSAN_102 vsan 102

 

Now let’s see if our handwork paid off? Issue a “sh zoneset active” command.

It should look like the following on both switches!  The star represents that the port performed a FLOGI and is currently logged into the fabric.  If you are not seeing stars then you need to go back to the basics and ensure the you know the proper WWN (look it up with a sh flogi database command to verify port-> wwn association) and the port is active.

 

image

 

 

And that’s it for zoning the WANCOM ports.  The information here might help you through the zoning of the BE/FE ports as well which is pretty straight forward from an FC perspective.  Feel free to shoot me any comments you may have and hopefully this helps in some way with any of your FC work! 

Rubbing a bit of Linux INIT into Powershell

Posted by vele1655 | Posted in Powershell | Posted on 03-01-2012

Tags:

0

One of the things that I’ve grown to use a lot lately is the try and catch functionality in Powershell which helps to isolate error conditions.  The functionality is great, but sometimes the GUI side of me asks for some more colored output.  The idea with what you see below is that we want to model a Linux INIT look and feel as far as colors and formatting goes.  This can be very useful in order to communicate intuitively to a user by way of colorful and properly formatted output context of successes and failures.

See the following screenshot for an example of the output when using the INIT function for Powershell provided below.

image

 

Without further ado here are the functions.

 

function formatOut {

    param($tmpText,$state)

    if($silent) { return }

    if($tmpText.length -ge 65) { $tmpText = $tmpText.substring(0,65) }

    if($state -eq $true) { $state = "OK" } else { $state = "FAILED" }

    $len = 70 - $tmpText.length

    "{0,0} {1,$len}" -f $tmpText,"[ $state ]"

}

 

function initOut {

    param($tmpText)

    if($silent) { return }

    write-host (($tmpText | %{ $_ -split "(\[)|(\])" } | %{

        if($_ -eq " OK ") { write-host -f "green" -nonewline $_ }

        elseif ($_ -eq " FAILED "){ write-host -f "red" -nonewline $_}

        else { write-host -nonewline $_ }}) -join "")

}

If you want to try it out, copy and paste the previous code into a Powershell window.  Entering “initOut (formatOut "Action" $true)” without quotes should output something similar to the following.

 

image

 

As you can see the “Action” portion is the text and the $true/$false/$null references whether an OK/FAILED/blank are filled in between the brackets.

 

Now if you want to make use of the functions in try and catch statements, see the following examples.  You can see that the first try/catch section will result in a success because there is no error thrown intentionally.  The second try/catch statement will result in a failure since we are issuing a throw and the catch statement will immediately follow the throw.

 

try {

        initOut (formatOut "Action" $true)

} catch { initOut (formatOut "Action" $false) }

 

try {

        throw "Testing a failure"

        initOut (formatOut "Action" $true)

} catch { initOut (formatOut "Action" $false) }

 

Duplicating a vApp – The Startup Order

Posted by vele1655 | Posted in Automation | Posted on 02-01-2012

Tags:

0

This is a first of a grouping of posts to follow that tackle the concept of duplicating all of the properties of a vApp.  This is something that is definitely on my wish list when it comes to the maturity of vApps in a VMware world.  In what I see as the nirvana state a vApp would be able to be completely duplicated without a programmatic approach and maintains a single meaning and operational awareness across all of VMware’s products.  Unfortunately we aren’t quite at that state, but this should help get people thinking about it differently.

 

The following expects that you have duplicated a vApp already and the VM names within the target vApp that look something similar to the following.

VAPP#1 VM#1 = Web

VAPP #2 VM#1 = Web-0001

 

$vAppName1 = "vApp1"

$vAppName2 = "vApp2"

 

$vAppView1 = Get-vApp $vAppName1 | Get-View

$vAppView2 = Get-vApp $vAppName2 | Get-View

 

$vAppView1.vAppConfig.EntityConfig | %{

      $e1=$_

      $vAppView2.vAppConfig.EntityConfig |

      where {$_.tag -match $e1.tag} | %{

            $EntityConfig = $_

        $e1.psobject.properties | where {$_.name -notmatch "key|tag" -and $_.issettable} | %{

            $EntityConfig.($_.name) = $_.value

        }

        $EntityConfig.Key = (Get-View $_.Key).MoRef

        $vAppConfigSpec = New-Object VMware.Vim.VAppConfigSpec

        $vAppConfigSpec.EntityConfig = $EntityConfig

        $vAppView2.UpdateVAppConfig($vAppConfigSpec)

      }

}

 

Now let’s break this down a bit.

1) Get the Views of the vApps

$vAppView1 = Get-vApp $vAppName1 | Get-View

$vAppView2 = Get-vApp $vAppName2 | Get-View

2) Loop through the entities within the first vApp and set $e1 as the current Entity within the first iteration

$vAppView1.vAppConfig.EntityConfig | %{

      $e1=$_

3) Loop through the second vApp and find the entity that matches the $e1 that we set previously.  This means that we are looking at the VM in source and target vApps.

$vAppView2.vAppConfig.EntityConfig |

      where {$_.tag -match $e1.tag} | %{

4) Iterate through the entity PSObject properties and grab the ones that we want from the source EntityConfig ($_ from $e1) and set them in the target EntityConfig ($EntityConfig).

$e1.psobject.properties | where {$_.name -notmatch "key|tag" -and $_.issettable} | %{

            $EntityConfig.($_.name) = $_.value

        }

5) Set the other required item (key) and then update the vApp with the UpdateVAppConfig method.

        $EntityConfig.Key = (Get-View $_.Key).MoRef

        $vAppConfigSpec = New-Object VMware.Vim.VAppConfigSpec

        $vAppConfigSpec.EntityConfig = $EntityConfig

        $vAppView2.UpdateVAppConfig($vAppConfigSpec)

 

Optimizing the execution of Powershell and PowerCLI

Posted by vele1655 | Posted in Powershell | Posted on 01-01-2012

Tags:

1

Have you ever noticed a certain delay when launching Powershell or when trying to run a first cmdlet in PowerCLI from a fresh session?  This is a well known problem that has been documented in a handful of places.  This is going to be a quick post that shows how to fix this scenario for both Powershell and PowerCLI.  If you haven’t run any of the following on your system, then there is no doubt that you will see some significant impact to leveraging this information.

This kind of thing has been especially critical for me since I utilize Powershell occasionally in a multi-threaded manner where I launch background jobs from a single Powershell console.  Sometimes PowerCLI is launched within these jobs, and also even full on Powershell consoles.  For me, minimizing any time and overhead to start new threads is critical!

 

Manually Compiling .NET PowerCLI Serializers

The first improvement that can help anyone has to do with manually compiling a few things ahead of time instead of having .NET compile them on the fly every time PowerCLI is loaded.  See the following code sections for 32-bit and 64-bit.  You should be able to purely copy and paste into a Powershell window based on whether you are running Windows Powershell (64-bit) or/and Windows Powershell (x86) (32-bit).

64-bit


C:\Windows\Microsoft.NET\Framework64\v2.0.50727\ngen.exe install "VimService50.XmlSerializers, Version=5.0.0.0, Culture=neutral, PublicKeyToken=10980b081e887e9f"

C:\Windows\Microsoft.NET\Framework64\v2.0.50727\ngen.exe install "VimService41.XmlSerializers, Version=4.1.0.0, Culture=neutral, PublicKeyToken=10980b081e887e9f"

C:\Windows\Microsoft.NET\Framework64\v2.0.50727\ngen.exe install "VimService40.XmlSerializers, Version=4.0.0.0, Culture=neutral, PublicKeyToken=10980b081e887e9f"

C:\Windows\Microsoft.NET\Framework64\v2.0.50727\ngen.exe install "VimService25.XmlSerializers, Version=2.5.0.0, Culture=neutral, PublicKeyToken=10980b081e887e9f"



 

32-bit


C:\Windows\Microsoft.NET\Framework\v2.0.50727\ngen.exe install "VimService50.XmlSerializers, Version=5.0.0.0, Culture=neutral, PublicKeyToken=10980b081e887e9f"

C:\Windows\Microsoft.NET\Framework\v2.0.50727\ngen.exe install "VimService41.XmlSerializers, Version=4.1.0.0, Culture=neutral, PublicKeyToken=10980b081e887e9f"

C:\Windows\Microsoft.NET\Framework\v2.0.50727\ngen.exe install "VimService40.XmlSerializers, Version=4.0.0.0, Culture=neutral, PublicKeyToken=10980b081e887e9f"

C:\Windows\Microsoft.NET\Framework\v2.0.50727\ngen.exe install "VimService25.XmlSerializers, Version=2.5.0.0, Culture=neutral, PublicKeyToken=10980b081e887e9f"

 

 

 

Disabling Certificate Revocation Checking

The second improvement is more generally for Powershell and possibly not relevant in all cases.  There is a feature where Powershell will check Microoft’s CRL (Certificate Revocation List) for publishers when bringing in libraries to ensure that they are legitimately signed by software publishers.  If you lack an internet connection this feature can cause Powershell to hang for a long time.  If you do have an internet connection it can cause a slight delay (seconds) in launching Powershell or bringing in new libraries.

There are three different ways that I know of to fix this problem.

1) The first method requires the least work but does not apply to all users on the computer.  It involves opening Internet Explorer and going to Tools –> Internet Options and pressing the Advanced tab.  Look for the security section and then uncheck the box next to “Check for publisher’s certification revocation.”

image

 

2) The second method is a system wide change that is easy to do and very effective in all cases.  It helped me since there are scenarios where I execute scripts as the SYSTEM user which is more difficult to work with as described in the first method.  Under this method there are configuration files that you can edit that are executed when you launch Powershell or anything that leverages a Powershell console.  Take the text that is shown below in the textbox and copy-paste it to a locally running notepad or editor of choice.  Save this file as “powershell.exe.config” and place it in the two locations  listed below (if running both 64 and 32-bit).  This file is one to take note of for future reference since it allows you to do this sort of thing where we set the revocation setting for all Powershell instances as well as force certain version of the .NET libraries to be loaded with Powershell.

Location of files

c:\windows\system32\windowspowershell\v1.0\powershell.exe.config

c:\windows\syswow64\windowspowershell\v1.0\powershell.exe.config


<configuration>

<runtime>

<generatePublisherEvidence enabled="false"/>

</runtime>

</configuration>

 

3) The third method to fix this issue is done by way of Group Policies.  I haven’t personally done it this way..

 

So there it is! If you are using PowerCLI or Powershell daily this no doubt will help out with speed.  We hope that in future versions of PowerCLI these kinds of things would be options during the install so this post and all others like it are irrelevant.. wink wink VMware =)

 

Blog References

http://msdn.microsoft.com/en-us/library/bb629393.aspx

http://blogs.vmware.com/vipowershell/2011/06/how-to-speed-up-the-execution-of-the-first-powercli-cmdlet.html

http://vnugglets.com/2011/11/speed-up-first-powercli-5-cmdlet.html

http://communities.vmware.com/message/1855364?tstart=0