<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>LucD notes</title>
	
	<link>http://www.lucd.info</link>
	<description>My PowerShell ramblings</description>
	<lastBuildDate>Wed, 16 May 2012 19:38:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/LucdNotes" /><feedburner:info uri="lucdnotes" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>vNIC transmit and receive rates</title>
		<link>http://feedproxy.google.com/~r/LucdNotes/~3/_djzefLibZM/</link>
		<comments>http://www.lucd.info/2012/04/21/vnic-transmit-and-receive-rates/#comments</comments>
		<pubDate>Sat, 21 Apr 2012 18:59:32 +0000</pubDate>
		<dc:creator>LucD</dc:creator>
				<category><![CDATA[NIC]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[statistics]]></category>
		<category><![CDATA[Virtual Machine]]></category>
		<category><![CDATA[PowerCLI]]></category>
		<category><![CDATA[VM]]></category>

		<guid isPermaLink="false">http://www.lucd.info/?p=3991</guid>
		<description><![CDATA[The VMTN PowerCLI Community is a constant source of inspiration for blog posts. User roswellevent raised, in the thread Any way to get virtual machine Nic card usage?, the question if it was possible to get the transmit and receive rate for each vNIC in virtual machines. Since I&#8217;m interested in all things statistics in [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://communities.vmware.com/community/vmtn/server/vsphere/automationtools/powercli?view=discussions&amp;start=0" target="_blank">VMTN PowerCLI Community</a> is a constant source of inspiration for blog posts. User <a href="http://communities.vmware.com/people/roswellevent" target="_blank">roswellevent</a> raised, in the thread <a href="http://communities.vmware.com/message/2029742#2029742">Any way to get virtual machine Nic card usage?</a>, the question if it was possible to get the <strong>transmit</strong> and <strong>receive</strong> rate for each <strong>vNIC</strong> in <strong>virtual machines</strong>.</p>
<p>Since I&#8217;m interested in all things statistics in vSphere I decided to tackle the question. Finding the metrics to use for this kind of report is not too difficult. Under the <a href="http://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/network_counters.html" target="_blank">PerformanceManager Network</a> section we find the metrics <strong>net.received.average</strong> and <strong>net.transmitted.average</strong>. And, provided your <strong>Statistics Level</strong> is set to <strong>3</strong> for the timeframe you want to report on, the metrics capture statistics on the <strong>device level</strong>.</p>
<p>Great, exactly what we need! A quick check in the <strong>Performance</strong> tab in the <strong>vSphere Client</strong> showed an additional problem to solve. The instance didn&#8217;t mention <strong>Network Adapter 1</strong> but a number.</p>
<p><img class="alignnone  wp-image-3994" title="nic-stat1" src="http://lucd.info/wp-content/uploads/2012/04/nic-stat1.png" alt="" width="578" height="284" /></p>
<p><span id="more-3991"></span></p>
<span id="Background"><h2>Background</h2></span>
<p>It turns out that this number is the internal <strong>Key</strong> used for the vNICs. Could have been a bit more user-friendly in the vSphere Client <img src='http://lucd.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>The solution is quite simple, the script fetches all the vNICs of a VM and then stores the Key together with the human-understandable name in a <strong>hash table</strong>. This hash table allows the script to replace the <strong>Instance</strong> value by the <strong>Name</strong> of the vNIC.</p>
<span id="The_script"><h2>The script</h2></span>
<pre class="brush: powershell; title: ; notranslate">
function Get-VmNicStat{
&lt;#
.SYNOPSIS  Retrieve network rates per vNIC per VM
.DESCRIPTION The function will calculate the average
  transmit receive rate, over a select time interval,
  for each vNIC on the VMs selected.
.NOTES  Author:  Luc Dekens
.PARAMETER VM
  The Virtual Machine(s)
  This is a required parameter.
.PARAMETER Start
  A DateTime value that specifies the start of the timeframe
  you want to use.
  This is a required parameter.
.PARAMETER Finish
  A DateTime value that specifies the end of the timeframe
  you want to use.
  The default is the current time.
.EXAMPLE
  PS&gt; Get-VM | Get-VmNicStat -Start $start
#&gt;

  param(
  [CmdletBinding()]
  [parameter(Mandatory = $true, ValueFromPipeline = $true)]
  [VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl[]]$VM,
  [parameter(Mandatory = $true)]
  [System.DateTime]$Start,
  [System.DateTime]$Finish = (Get-Date)
  )

  begin{
    $metrics = &quot;net.received.average&quot;,&quot;net.transmitted.average&quot;
  }

  process{
    $stats = Get-Stat -Entity $VM -Stat $metrics -Start $Start

    foreach($vm in ($stats | Group-Object -Property {$_.Entity.Name})){
      $nicTab = @{}
      $vm.Group[0].Entity.NetworkAdapters | %{
        $key = [string]$_.ExtensionData.Key
        $value = $_.Name
        $nicTab.Add($key,$value)
      }

      $vm.Group | where {$nicTab.ContainsKey($_.Instance)} |
      Group-Object -Property Instance | %{
        New-Object PSObject -Property @{
          VM = $vm.Name
          Start = $Start
          Finish = $Finish
          NIC = $nicTab[$_.Group[0].Instance]
          &quot;Avg Received (KBps)&quot; = [Math]::Round(($_.Group |
            where {$_.MetricId -eq &quot;net.received.average&quot;} |
            Measure-Object -Property Value -Average).Average,1)
          &quot;Avg Transmitted (KBps)&quot; = [Math]::Round(($_.Group |
            where {$_.MetricId -eq &quot;net.transmitted.average&quot;} |
            Measure-Object -Property Value -Average).Average,1)
        }
      }
    }
  }
}
</pre>
<span id="Annotations"><h4>Annotations</h4></span>
<p><strong>Line 33</strong>: The metrics the functions uses.</p>
<p><strong>Line 37</strong>: Retrieve the statistical data for the virtual machines over the selected timeframe.</p>
<p><strong>Line 39</strong>: The function uses the Group-Object cmdlet to split the returned statistical by VM.</p>
<p><strong>Line 40-45</strong>: Look at all the vNICs connected to the VM and create a hash table, linking the Key with the Name of the vNIC.</p>
<p><strong>Line 47</strong>: The Where-clause will filter out the statistical data for the vNICs of the VM</p>
<p><strong>Line 48</strong>: Use the Group-Object to to split the statistical data per vNIC</p>
<p><strong>Line 49-60</strong>: Create an object per vNIC per VM</p>
<p><strong>Line 53</strong>: Use the hash table to fetch the &#8220;Network Adapter x&#8221; name of the vNIC</p>
<p><strong>Line 54-59</strong>: Calculate the average transmit and recieve values over the selected timeframe.</p>
<span id="Sample_usage"><h2>Sample usage</h2></span>
<p>You can use the function like this</p>
<pre class="brush: powershell; title: ; notranslate">
$vms = Get-VM -Name vm*
Get-VmNicStat -VM $vms -Start (Get-Date).AddHours(-1)
</pre>
<p>And you can also use it in a pipeline, like this</p>
<pre class="brush: powershell; title: ; notranslate">
Get-VM -Name vm* |
Get-VmNicStat -Start (Get-Date).AddHours(-1) |
Select VM,Start,Finish,NIC,&quot;Avg Received (KBps)&quot;,&quot;Avg Transmitted (KBps)&quot; |
Format-Table -AutoSize
</pre>
<p>The resulting output looks like this</p>
<p><img class="alignnone  wp-image-4000" title="nic-stat2" src="http://lucd.info/wp-content/uploads/2012/04/nic-stat2.png" alt="" width="698" height="82" /></p>
<p>Enjoy!</p>
<img src="http://feeds.feedburner.com/~r/LucdNotes/~4/_djzefLibZM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lucd.info/2012/04/21/vnic-transmit-and-receive-rates/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.lucd.info/2012/04/21/vnic-transmit-and-receive-rates/</feedburner:origLink></item>
		<item>
		<title>Test if the datastore can be unmounted</title>
		<link>http://feedproxy.google.com/~r/LucdNotes/~3/gTZH0N0MWY4/</link>
		<comments>http://www.lucd.info/2012/04/15/test-if-the-datastore-can-be-unmounted/#comments</comments>
		<pubDate>Sun, 15 Apr 2012 21:29:48 +0000</pubDate>
		<dc:creator>LucD</dc:creator>
				<category><![CDATA[datastore]]></category>
		<category><![CDATA[PowerCLI]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[SDRS]]></category>
		<category><![CDATA[SIOC]]></category>
		<category><![CDATA[unmount]]></category>

		<guid isPermaLink="false">http://www.lucd.info/?p=3980</guid>
		<description><![CDATA[Lately I have been playing around with the new Storage related features in vSphere 5. One of the novelties is that you can now unmount a VMFS datastore and detach a SCSI LUN through the API. To be able to unmount a datastore, some conditions have to be met. In the vSphere Client you get [...]]]></description>
			<content:encoded><![CDATA[<p>Lately I have been playing around with the new Storage related features in vSphere 5. One of the novelties is that you can now <strong>unmount</strong> a VMFS datastore and <strong>detach</strong> a SCSI LUN through the API.<br />
To be able to unmount a datastore, some <strong>conditions</strong> have to be met. In the vSphere Client you get an informative popup that tells what is prohibiting the datastore unmount. If not all conditions are met, you can not continue with the unmount.</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/04/Datastore-unmount.png"><img class=" wp-image-3906 alignnone" title="DS unmount" src="http://lucd.info/wp-content/uploads/2012/04/Datastore-unmount.png" alt="" width="421" height="316" /></a></p>
<p>Nice feature, but what for those of us that want to automate this ?</p>
<p><span style="background-color: #ffff00;"><strong>Update April 23th 2012</strong></span>: Use the <a href="http://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.ClusterComputeResource.html#retrieveDasAdvancedRuntimeInfo" target="_blank">RetrieveDasAdvancedRuntimeInfo</a> method to find the actual datastores that are used for the heartbeat.</p>
<p><span id="more-3980"></span></p>
<span id="What_to_look_for_"><h2>What to look for ?</h2></span>
<p>From the popup, it is quite obvious what specific feature can prohibit the unmount of a datastore.</p>
<p>But if you look at Cormac&#8217;s post called <a href="http://blogs.vmware.com/vsphere/2012/02/what-could-be-writing-to-a-vmfs-when-no-virtual-machines-are-running.html" target="_blank">What could be writing to a VMFS when no Virtual Machines are running?</a>, there are a couple of other settings that might influence the ability to unmount a datastore.</p>
<p>In Cormac&#8217;s post you&#8217;ll find that a <strong>Distributed Virtual Switch configuration file</strong> or the presence of a <strong>scratch partition</strong> might also cause IO that would prevent a datastore unmount.</p>
<p>So I decided to expand the function with a check for those 2 additional causes.</p>
<span id="The_script"><h2>The script</h2></span>
<pre class="brush: powershell; title: ; notranslate">
function Get-DatastoreUnmountStatus{
&lt;#
.SYNOPSIS  Check if a datastore can be unmounted.
.DESCRIPTION The function checks a number of prerequisites
  that need to be met to be able to unmount a datastore.
.NOTES  Author:  Luc Dekens
.PARAMETER Datastore
  The datastore for which you want to chekc the conditions.
  You can pass the name of the datastore or the Datastore
  object returned by Get-Datastore
.EXAMPLE
  PS&gt; Get-DatastoreUnmountStatus -Datastore DS1
.EXAMPLE
  PS&gt; Get-Datastore | Get-DatastoreUnmountStatus
#&gt;
  param(
  [CmdletBinding()]
  [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
  [PSObject[]]$Datastore
  )

  process{
    foreach($ds in $Datastore){
      if($ds.GetType().Name -eq &quot;string&quot;){
        $ds = Get-Datastore -Name $ds
      }
      $parent = Get-View $ds.ExtensionData.Parent
      New-Object PSObject -Property @{
        Datastore = $ds.Name
        # No Virtual machines
        NoVM = $ds.ExtensionData.VM.Count -eq 0
        # Not in a Datastore Cluster
        NoDastoreClusterMember = $parent -isnot [VMware.Vim.StoragePod]
        # Not managed by sDRS
        NosDRS = &amp;{
          if($parent -is [VMware.Vim.StoragePod]){
            !$parent.PodStorageDrsEntry.StorageDrsConfig.PodConfig.Enabled
          }
          else {$true}
        }
        # SIOC disabled
        NoSIOC = !$ds.StorageIOControlEnabled
        # No HA heartbeat
        NoHAheartbeat = &amp;{
          $hbDatastores = @()
          $cls = Get-View -ViewType ClusterComputeResource -Property Host |
            where{$_.Host -contains $ds.ExtensionData.Host[0].Key}
          $cls | %{
            ($_.RetrieveDasAdvancedRuntimeInfo()).HeartbeatDatastoreInfo | %{
              $hbDatastores += $_.Datastore
            }
          }
          $hbDatastores -notcontains $ds.ExtensionData.MoRef
        }
        # No vdSW file
        NovdSwFile = &amp;{
          New-PSDrive -Location $ds -Name ds -PSProvider VimDatastore -Root '\' | Out-Null
          $result = Get-ChildItem -Path ds:\ -Recurse |
          where {$_.Name -match '.dvsData'}
          Remove-PSDrive -Name ds -Confirm:$false
          if($result){$false}else{$true}
        }
        # No scratch partition
        NoScratchPartition = &amp;{
          $result = $true
          $ds.ExtensionData.Host | %{Get-View $_.Key} | %{
            $diagSys = Get-View $_.ConfigManager.DiagnosticSystem
            $dsDisks = $ds.ExtensionData.Info.Vmfs.Extent | %{$_.DiskName}
            if($dsDisk -contains $diagSys.ActivePartition.Id.DiskName){
              $result = $false
            }
          }
          $result
        }
      }
    }
  }
}
</pre>
<span id="Annotations"><h4>Annotations</h4></span>
<p><strong>Line 24-26</strong>: A simple Object By Name implementation. It allows to pass the datastores by name or by object to the function.</p>
<p><strong>Line 27</strong>: The parent of the datastore is used in a couple of tests further on in the script</p>
<p><strong>Line 31</strong>: Test if there are any VMs or Templates present on the datastore</p>
<p><strong>Line 33</strong>: Test if the datastore belongs to a Storage Cluster</p>
<p><strong>Line 35-40</strong>: Test if the datastore is managed by Storage DRS. The Enabled property in the <a href="http://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.storageDrs.PodConfigInfo.html" target="_blank">StorageDrsPodConfigInfo</a> object is used as the indicator.</p>
<p><strong>Line 42</strong>: Test if SIOC is enabled for the datastore</p>
<p><strong>Line 44-54</strong>: Test if the datastore is one of the Heartbeat Datastores. The test first gets all the clusters known in vCenter and then filters out those clusters that have hosts on which the datastore is visible.</p>
<p><strong>Line 56-62</strong>: Test to see if the is a Distributed Virtual Switch configuration file present on the datastore.</p>
<p><strong>Line 64-74</strong>: Test if the datastore is used as a scratch partition.</p>
<span id="Sample_usage"><h2>Sample usage</h2></span>
<p>The function can be used in a stand-alone or in a pipeline construct.</p>
<pre class="brush: powershell; title: ; notranslate">
Get-DatastoreUnmountStatus -Datastore DS1
</pre>
<p>The pipeline construct could look like this</p>
<pre class="brush: powershell; title: ; notranslate">
Get-Datastore DS* | Get-DatastoreUnmountStatus
</pre>
<p>The function produces 1 object per datastore. Each of the properties in the object represents 1 test that the function executes. Something like this.</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/04/dsUnmountout.png"><img class=" wp-image-3906 alignnone" title="DS unmount output" src="http://lucd.info/wp-content/uploads/2012/04/dsUnmountout.png" alt="" width="576" height="130" /></a></p>
<p>The output shows us that we will probably not be able to unmount datastore DS1, because:</p>
<ul>
<li>the datastore is part of a Datastore Cluster</li>
<li>the datastore is managed by Storage DRS</li>
<li>there are VMs (or Templates) on the datastore</li>
<li>the datastore is used by the Datastore Heartbeat</li>
<li>the datastore has SIOC enabled</li>
</ul>
<p>The functions to solve this and allow an unmount of the datastore will follow in some future posts.</p>
<p>Enjoy !</p>
<img src="http://feeds.feedburner.com/~r/LucdNotes/~4/gTZH0N0MWY4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lucd.info/2012/04/15/test-if-the-datastore-can-be-unmounted/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://www.lucd.info/2012/04/15/test-if-the-datastore-can-be-unmounted/</feedburner:origLink></item>
		<item>
		<title>Automate your VMTN search</title>
		<link>http://feedproxy.google.com/~r/LucdNotes/~3/C_6hRnhjpXI/</link>
		<comments>http://www.lucd.info/2012/02/29/automate-your-vmtn-search/#comments</comments>
		<pubDate>Wed, 29 Feb 2012 21:26:54 +0000</pubDate>
		<dc:creator>LucD</dc:creator>
				<category><![CDATA[PowerCLI]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[VMTN]]></category>

		<guid isPermaLink="false">http://www.lucd.info/?p=3963</guid>
		<description><![CDATA[Recently I had the pleasure of doing a guest post, called Finding your way in the PowerCLI Community, on the PowerCLI blog. The subject of the post was how to find community threads, that might hold an answer to your question. Now this wouldn&#8217;t be a PowerShell/PowerCLI blog, if I didn&#8217;t try to automate the [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I had the pleasure of doing a guest post, called <a href="http://blogs.vmware.com/vipowershell/2012/02/guest-post-finding-your-way-in-the-powercli-community.html" target="_blank">Finding your way in the PowerCLI Community,</a> on the <a href="http://blogs.vmware.com/vipowershell/" target="_blank">PowerCLI blog</a>. The subject of the post was how to find community threads, that might hold an answer to your question.</p>
<p>Now this wouldn&#8217;t be a PowerShell/PowerCLI blog, if I didn&#8217;t try to <strong>automate</strong> the procedure. And with a serious amount of <strong>RegEx</strong> involved, I was able to create some working code. Here it is, my <strong>Find-VMTNPowerCLI</strong> function.</p>
<p style="padding-left: 60px;"><a href="http://lucd.info/wp-content/uploads/2012/02/spyglass.gif"><img class=" wp-image-3906 alignnone" title="variations" src="http://lucd.info/wp-content/uploads/2012/02/spyglass.gif" alt="" width="317" height="162" /></a></p>
<p><strong><span style="background-color: #ffff00;">Warning</span></strong>: pure <strong>PowerShell</strong>, no <strong>PowerCLI</strong> content !</p>
<p><span id="more-3963"></span></p>
<span id="The_script"><h2>The script</h2></span>
<pre class="brush: powershell; title: ; notranslate">
function Find-VMTNPowerCLI{
&lt;#
.SYNOPSIS  Search the VMTN PowerCLI related communities
.DESCRIPTION The function automates the functionality that
  is available through the Search page
.NOTES  Author:  Luc Dekens
.PARAMETER Question
  The question as you would enter it on the VMTN Search page
.PARAMETER Start
  The start date of the period in which you are looking for
  threads that fitt your search.
  The default is December 24th 2007.
.PARAMETER Finish
  The start date of the period in which you are looking for
  threads that fitt your search.
  The default is now.
.PARAMETER ReplyStart
  The start date of the period in which you are looking for
  replies that fitt your search.
  The default is December 24th 2007.
.PARAMETER ReplyFinish
  The start date of the period in which you are looking for
  replies that fitt your search.
  The default is now.
.PARAMETER Author
  Filter the returned threads to those started by one of the
  authors.
.PARAMETER ReplyAuthor
  Filter the returned threads to those where the reply came
  from one of the authors.
.PARAMETER PowerCLI
  Switch, search the PowerCLI Community.
  The default for this switch is $true.
.PARAMETER Onyx
  Switch, search the Onyx Community.
  The default for this switch is $false.
.PARAMETER UpdateManager
  Switch, search the UpdateManager Community.
  The default for this switch is $false.
.PARAMETER PowerShellers
  Switch, search the PowerShellers group.
  The default for this switch is $false.
.PARAMETER AutomationTools
  Switch, search the AutomationTools COmmunity.
  The default for this switch is $false.
.PARAMETER Descending
  Switch, when true the returned threads will be
  in a descending Reply Date order.
  The default for this switch is $true.
.EXAMPLE
  PS&gt; Find-VMTNPowerCLI -Question 'svmotion thin'
.EXAMPLE
  PS&gt; Find-VMTNPowerCLI -Question '5.0.1' -PowerShellers
.EXAMPLE
  PS&gt; Find-VMTNPowerCLI -Question 'regex get-view' `
  &gt;&gt; -Start (Get-Date).AddDays(-14)
#&gt;

  param(
  [CmdletBinding()]
  [parameter(Mandatory = $true)]
  [string]$Question,
  [datetime]$Start = (New-Object DateTime -ArgumentList 2007,12,24),
  [datetime]$Finish = (Get-Date),
  [datetime]$ReplyStart = $Start,
  [datetime]$ReplyFinish = $Finish,
  [string[]]$Author,
  [string[]]$ReplyAuthor,
  [switch]$PowerCLI = $true,
  [switch]$Onyx,
  [switch]$UpdateManager,
  [switch]$PowerShellers,
  [switch]$AutomationTools,
  [switch]$Descending = $true
  )

  function Get-VMTNSearch{
    param(
    [string]$url,
    [switch]$Group
    )

    $pst = [TimeZoneInfo]::FindSystemTimeZoneById(&quot;Pacific Standard Time&quot;)
    $t0 = Get-Date
    $t1 = [TimeZoneInfo]::ConvertTime($t0,$pst)
    $tdiff = $t0 - $t1

    $regBodyText = [regex]'(?s)\[DocumentBodyStart.*?--&gt;(?&lt;bodyText&gt;.*)&lt;!--'
    $strAnswerAuthorGroup = 'jive-thread-reply jive-thread-reply-alt  clearfix[\w\W]*?xxxxxxx[\w\W]*?&lt;a href=&quot;/people/(?&lt;user&gt;.*)&quot;'
    $strAnswerAuthorOther = '&lt;a name=&quot;xxxxxxx[\w\W]*?&lt;a href=&quot;/people/(?&lt;user&gt;.*)&quot;'
    $regThreadAuthor = [regex]'jive-thread-post-body[\w\W]*?&lt;a href=&quot;/people/(?&lt;user&gt;.*)&quot;'
    $regThreadDate = [regex]'jive-thread-reply-date[\w\W]*?&lt;span&gt;(?&lt;threaddate&gt;.*?)&lt;/span&gt;'
    $regReplies = [regex]'(?&lt;replies&gt;\d*) Replies'

    $web = New-Object System.Net.WebClient
    $answerFeed = 1$web.DownloadString($url)
    $answerFeed.rss.channel.item |
    Sort-Object -Property {[datetime]$_.pubDate} -Descending |
    Select @{N=&quot;ReplyDate&quot;;E={[datetime]$_.pubDate}}, Title,
    @{N=&quot;Text&quot;;E={
        $bodyText = &quot;&quot;
        if($_.InnerText -match $regBodyText){
          $bodyText = $matches['bodyText']
          $bodyText = $bodyText -replace &quot;&lt;/p&gt;|&lt;br/&gt;&quot;,&quot;`n&quot;
          $bodyText = $bodyText -replace '&lt;blockquote class=&quot;jive-quote&quot;&gt;|&lt;/blockquote&gt;'
          $bodyText = $bodyText -replace &quot;&lt;.*?&gt;&quot;
          $bodyText = $bodyText -replace &quot;&amp;gt;&quot;,&quot;&gt;&quot;
          $bodyText = $bodyText -replace &quot;&amp;#160;&quot;,&quot;`t&quot;
        }
        $bodyText}},
    @{N=&quot;Reply&quot;;E={
        Set-Variable -Name page -Value $web.DownloadString($_.Link) -Scope 1
        $bookmark = $_.Link.Split('#')[1]
        if($group){
          $regAnswerAuthor = [regex]$strAnswerAuthorGroup.Replace('xxxxxxx',$bookmark)
        }
        else{
          $regAnswerAuthor = [regex]$strAnswerAuthorOther.Replace('xxxxxxx',$bookmark)
        }
        $user = &quot;&quot;
        if($page -match $regAnswerAuthor){
          $user = $matches['user']
        }
        [System.Web.HttpUtility]::UrlDecode($user)
      }},
    @{N=&quot;Poster&quot;;E={
        $user = &quot;&quot;
        if($page -match $regThreadAuthor){
          $user = $matches['user']
        }
        [System.Web.HttpUtility]::UrlDecode($user)
      }},
    @{N=&quot;ThreadDate&quot;;E={
        $threadDate = &quot;&quot;
        if($page -match $regThreadDate){
          $threadDate = ([datetime]$matches['threaddate']).Add($tdiff)
        }
        $threadDate
      }},
    @{N=&quot;Replies&quot;;E={
        if($page -match $regReplies){
          $matches['replies']
        }
        else{0}
      }},
    Link

    $web.Dispose()
  }

  $containerPowerCLI = 2530
  $containerOnyx = 3498
  $containerUpdateManager = 3482
  $containerAutomationTools = 3102
  $containerPowerShellers = 1013
  $typePowerShellers = 700

  $searchUrl = &quot;http://communities.vmware.com/community/feeds/search&quot;
  $questionText = &quot;q=&quot; + [System.Web.HttpUtility]::UrlEncode($Question)
  $peopleEnabled = &quot;peopleEnabled=true&quot;
  $containerType = &quot;containerType=14&quot;
  $container = &quot;container=$containerPowerCLI&quot;
  $dateRange = &quot;dateRange=all&quot;
  $numResults = &quot;numResults=&quot; + [int]::MaxValue

  $query = $questionText + &quot;&amp;&quot; + $peopleEnabled + &quot;&amp;&quot; + $containerType +
  &quot;&amp;&quot; + $container + &quot;&amp;&quot; + $dateRange + &quot;&amp;&quot; + $numResults
  $url = $searchUrl + &quot;?&quot; + $query

  $result = @()
  if($PowerCLI){
     $result += Get-VMTNSearch -Url $url
  }
  if($Onyx){
    $url = $url -replace &quot;(container=)(\d+)&quot;,&quot;`${1}$containerOnyx&quot;
    $result += Get-VMTNSearch -Url $url
  }
  if($UpdateManager){
    $url = $url -replace &quot;(container=)(\d+)&quot;,&quot;`${1}$containerUpdateManager&quot;
     $result += Get-VMTNSearch -Url $url
  }
  if($PowerShellers){
    $url = $url -replace &quot;(container=)(\d+)&quot;,&quot;`${1}$containerPowerShellers&quot;
    $url = $url -replace &quot;(containerType=)(\d+)&quot;,&quot;`${1}$typePowerShellers&quot;
    $result += Get-VMTNSearch -Url $url -Group
  }

  $condition = '$_.ReplyDate -ge $ReplyStart -and $_.ReplyDate -le $ReplyFinish -and'
  $condition += '  $_.ThreadDate -ge $Start -and $_.ThreadDate -le $Finish'
  if($Author){
    $condition += ' -and $Author -contains $_.Poster'
  }
  if($ReplyAuthor){
    $condition += ' -and $ReplyAuthor -contains $_.Reply'
  }
  $sblock = $executioncontext.InvokeCommand.NewScriptBlock($condition)
  $result | where {&amp;$sblock} | Sort-Object -Property ReplyDate -Descending:$Descending
}
</pre>
<span id="Annotations"><h4>Annotations</h4></span>
<p><strong>Line 63</strong>: The first thread in the PowerCLI Community dates from December 24th 2007. No reason to go further back in time <img src='http://lucd.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p><strong>Line 77-149</strong>: An internal helper function. This is the real workhorse of the function, in here all the RegEx mgic takes place.</p>
<p><strong>Line 80</strong>: The way <strong>Jive</strong> returns results for a community or a group is slightly different. Hence the Group switch, which will allow the function Get-VMTNSearch to act differently for the PowerShellers group.</p>
<p><strong>Line 83-86</strong>: The ThreadData is returned in <strong>PST</strong> time (I suppose that is where the VMTN servers are located). These lines will calculate the time difference between the location where you run the script and PST time.</p>
<p><strong>Line 88-93</strong>: The RegEx expressions that will be used in the function to extract the desired fields.</p>
<p><strong>Line 96</strong>: The URL, which is passed from the calling function, contains the actual Search keywords. Here we download the results from the search and convert it to an XML list for further handling.</p>
<p><strong>Line 97</strong>: The individual &#8216;items&#8217; from the search result are retrieved and used to extract the data.</p>
<p><strong>Line 103-108</strong>: The content of the reply post is interspersed with HTML code. The series of <strong>-Replace</strong> operators will convert and filter away the HTML tags.</p>
<p><strong>Line 112</strong>: The function fetches the complete page for the thread. This required for extracting the properties that follow. The <strong>-Scope 1</strong> parameter makes sure that the $page variable is available outside the calculated property code block.</p>
<p><strong>Line 113-119</strong>: The RegEx string contains the bookmark for the specific reply we are looking at. That is why the script updates the RegEx string with the bookmark. The Reply field has a different layout depending if it comes from a Community or a Group.</p>
<p><strong>Line 124,131</strong>: Some user names might contain blanks or other special characters, to avoid displaying the Javascript encoding for these special characters, the property value is decoded.</p>
<p><strong>Line 136</strong>: The thread date is returned in PST time (see above). This converts the datetime value to your local time.</p>
<p><strong>Line 151-155</strong>: All the VMTN Communities have a specific ID. This ID needs to be used in the search URL.</p>
<p><strong>Line 156</strong>: The PowerShellers group has a specific type, different from the Community type.</p>
<p><strong>Line 158</strong>: The basic Search page URL</p>
<p><strong>Line 159</strong>: The search URL needs to have all special characters converted.</p>
<p><strong>Line 160-164</strong>: The other parameters passed on the search URL</p>
<p><strong>Line 164</strong>: On the Search page, the results are returned in batches of 10, 15 or 30. In the function we want all the results in one go, hence the maximum [int] value.</p>
<p><strong>Line 171-186</strong>: The Get-VMTNSearch internal function is called for each of the selected communities.</p>
<p><strong>Line 188-195</strong>: All the selected conditions are stored in a [string]</p>
<p><strong>Line 196</strong>: The string with the conditions is converted in a code block</p>
<p><strong>Line 197</strong>: The generated code block is used in the Where-clause to filter the results according to the passed parameters.</p>
<span id="Sample_usage"><h2>Sample usage</h2></span>
<p>The function is quite simple to use. The Question parameter accepts the exact same search strings as you can enter on the <strong>Search page</strong>. See the VMTN <a href="http://communities.vmware.com/search-tips.jspa" target="_blank">Search Tips</a> for the details.</p>
<p>A simple example that will look for the keyword &#8216;<em><strong>move-vmthin</strong></em>&#8216; in the <strong>PowerCLI Community</strong>.</p>
<pre class="brush: powershell; title: ; notranslate">
$qtext = &quot;move-vmthin&quot;

Find-VMTNPowerCLI -Question $qtext |
Export-Csv .\search-results.csv -NoTypeInformation -UseCulture
</pre>
<p>The resulting CSV file looks like this</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/02/search1.png"><img class=" wp-image-3906 alignnone" title="Search 1" src="http://lucd.info/wp-content/uploads/2012/02/search1.png" alt="" width="940" height="146" /></a></p>
<p>Note that in the <strong>Text</strong> column you can find the complete content of the reply. This can make it quite easy to copy code to your favorite PowerShell editor.</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/02/search2.png"><img class=" wp-image-3906 alignnone" title="Search 1 Text" src="http://lucd.info/wp-content/uploads/2012/02/search2.png" alt="" width="804" height="281" /></a></p>
<p>The next example will look for the text &#8216;<em><strong>baseline groups remediate-inventory</strong></em>&#8216; only in the <strong>Update Manager PowerCLI</strong> Community.</p>
<pre class="brush: powershell; title: ; notranslate">
$qtext = 'baseline groups remediate-inventory'

Find-VMTNPowerCLI -Question $qtext -UpdateManager -PowerCLI:$false |
Export-Csv D:\Tools\PowerShell\Scripts\search-results.csv -NoTypeInformation -UseCulture
</pre>
<p>The result</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/02/search3.png"><img class=" wp-image-3906 alignnone" title="Search 2 Text" src="http://lucd.info/wp-content/uploads/2012/02/search3.png" alt="" width="748" height="73" /></a></p>
<p>With the search functionality, you could for example look for replies that contain functions. Searching for the words &#8216;<em><strong>function param</strong></em>&#8216; we would find quite a number of replies that contain code.</p>
<pre class="brush: powershell; title: ; notranslate">
$qtext = &quot;function param&quot;

Find-VMTNPowerCLI -Question $qtext |
Export-Csv D:\Tools\PowerShell\Scripts\search-results.csv -NoTypeInformation -UseCulture
</pre>
<p>The resulting CSV file contains 167 rows. Perhaps a bit too much. So let&#8217;s limit the replies to a specific <strong>time period</strong>. We only look for replies after <strong>September 1st 2011</strong>.</p>
<pre class="brush: powershell; title: ; notranslate">
$qtext = &quot;function param&quot;
$start = Get-Date -Year 2011 -Month 9 -Day 1

Find-VMTNPowerCLI -Question $qtext -ReplyStart $start |
Export-Csv D:\Tools\PowerShell\Scripts\search-results.csv -NoTypeInformation -UseCulture
</pre>
<p>Much better, now we find 23 replies, with recent code.</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/02/search4.png"><img class=" wp-image-3906 alignnone" title="Search 3 Text" src="http://lucd.info/wp-content/uploads/2012/02/search4.png" alt="" width="778" height="405" /></a></p>
<span id="A_word_of_warning"><h2>A word of warning</h2></span>
<p>I&#8217;m pretty sure there are some threads around that will break the function. With so many threads and replies in these very active PowerCLI related communities and groups, there are bound to be some that I didn&#8217;t encounter during my tests and that will break the function.</p>
<p>Should you encounter something like that, feel free to post the parameters in the comments for this post and I will try to fix the function.</p>
<p>Enjoy !</p>
<img src="http://feeds.feedburner.com/~r/LucdNotes/~4/C_6hRnhjpXI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lucd.info/2012/02/29/automate-your-vmtn-search/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.lucd.info/2012/02/29/automate-your-vmtn-search/</feedburner:origLink></item>
		<item>
		<title>dvSwitch scripting – Part 12 – Find free ports</title>
		<link>http://feedproxy.google.com/~r/LucdNotes/~3/BZeQS4OliJM/</link>
		<comments>http://www.lucd.info/2012/02/14/dvswitch-scripting-part-12-find-free-ports/#comments</comments>
		<pubDate>Tue, 14 Feb 2012 20:16:33 +0000</pubDate>
		<dc:creator>LucD</dc:creator>
				<category><![CDATA[dvSwitch]]></category>
		<category><![CDATA[port]]></category>
		<category><![CDATA[portkey]]></category>
		<category><![CDATA[PowerCLI]]></category>

		<guid isPermaLink="false">http://www.lucd.info/?p=3954</guid>
		<description><![CDATA[On the PowerCLI Community there was an interesting question about dvSwitches, portgroups and connecting VMs. Turns out you will need to provide a free port to connect a VM&#8217;s NIC to a portgroup on dvSwitch. Since the solution is a nice follow up on my previous, somewhat lengthy post, called Variations on a port, I [...]]]></description>
			<content:encoded><![CDATA[<p>On the <a href="http://communities.vmware.com/community/vmtn/server/vsphere/automationtools/powercli?view=discussions&amp;start=0" target="_blank">PowerCLI Community</a> there was an interesting <a href="http://communities.vmware.com/message/1987845#1987845" target="_blank">question</a> about dvSwitches, portgroups and connecting VMs. Turns out you will need to provide a free port to connect a VM&#8217;s NIC to a portgroup on dvSwitch.<br />
Since the solution is a nice follow up on my previous, somewhat lengthy post, called <a href="http://www.lucd.info/2012/01/29/variations-on-a-port/" target="_blank">Variations on a port</a>, I decided to create a short post on the subject in my <a href="http://www.lucd.info/category/vsphere/dvswitch/" target="_blank">dvSwitch series</a>.</p>
<p><span id="more-3954"></span></p>
<p>To connect a VM&#8217;s NIC to a dvSwitch portgroup you can use the <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/Set-NetworkAdapter.html" target="_blank">Set-NetworkAdapter</a> cmdlet like this.</p>
<pre class="brush: powershell; title: ; notranslate">
Get-vm $vmname | Get-NetworkAdapter |
Set-NetworkAdapter -DistributedSwitch dvSwitch1 -PortKey 403
</pre>
<p>But how do we get that <strong>PortKey</strong> number ?<br />
<a href="http://lucd.info/wp-content/uploads/2012/02/freeport.png"><img class=" wp-image-3906 alignnone" title="variations" src="http://lucd.info/wp-content/uploads/2012/02/freeport.png" alt="" /></a></p>
<p>Since PowerCLI is all about automation, we are not going to use the vSphere client to get the number. Hence the following function.</p>
<span id="The_script"><h2>The script</h2></span>
<pre class="brush: powershell; title: ; notranslate">
function Get-dvPgFreePort{
  &lt;#
.SYNOPSIS  Get free ports on a dvSwitch portgroup
.DESCRIPTION The function will return 1 or more
  free ports on a dvSwitch portgroup
.NOTES  Author:  Luc Dekens
.PARAMETER PortGroup
  Specify the portgroup for which you want to retrieve
  free ports
.PARAMETER Number
  Specify the number of free ports you want to retrieve.
  The default is 1 port. If Number is greater than the
  number of available ports, the function will return all
  available ports
.EXAMPLE
  PS&gt; Get-dvPgFreePort -PortGroup $pg
.EXAMPLE
  PS&gt; Get-dvPgFreePort -PortGroup $pg -Number 5
#&gt;

  param(
  [CmdletBinding()]
  [string]$PortGroup,
  [int]$Number = 1
  )

  $nicTypes = &quot;VirtualE1000&quot;,&quot;VirtualE1000e&quot;,&quot;VirtualPCNet32&quot;,
  &quot;VirtualVmxnet&quot;,&quot;VirtualVmxnet2&quot;,&quot;VirtualVmxnet3&quot;
  $ports = @{}

  $pg = Get-VirtualPortGroup -Distributed -Name $PortGroup
  $pg.ExtensionData.PortKeys | %{$ports.Add($_,$pg.Name)}

  Get-View $pg.ExtensionData.Vm | %{
    $nic = $_.Config.Hardware.Device |
    where {$nicTypes -contains $_.GetType().Name -and
      $_.Backing.GetType().Name -match &quot;Distributed&quot;}
    $nic | %{$ports.Remove($_.Backing.Port.PortKey)}
  }

  if($Number -gt $ports.Keys.Count){
    $Number = $ports.Keys.Count
  }
  ($ports.Keys | Sort-Object)[0..($Number - 1)]
}
</pre>
<span id="Annotations"><h4>Annotations</h4></span>
<p><strong>Line 27-28</strong>: All the possible NIC types</p>
<p><strong>Line 29</strong>: To collect the ports, the script uses a hash table.</p>
<p><strong>Line 32</strong>: The script adds all ports available on the portgroup to the hash table</p>
<p><strong>Line 34</strong>: For all the VMs connected to the portgroup, the script will find the NICs connected to this portgroup.</p>
<p><strong>Line 38</strong>: For the NICs that are connected to the portgroup, the script will remove the corresponding portkey from the hash table</p>
<p><strong>Line 41-43</strong>: If the caller asked more ports than there are free on the portgroup, the function will return all the free ports.</p>
<p><strong>Line 44</strong>: The script returns the free ports in ascending order</p>
<p>Sample usage</p>
<p>The use of the function is quite simple. Just pass the name of the portgroup and the number of ports you want returned.</p>
<pre class="brush: powershell; title: ; notranslate">

Get-dvPgFreePort -PortGroup &quot;dvPG12&quot; -Number 5
</pre>
<p>The result is an ordered list of 5 free ports, which you can use on the PortKey parameter of the <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/Set-NetworkAdapter.html" target="_blank">Set-NetworkAdapter</a> cmdlet.</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/02/portkeys.png"><img class=" wp-image-3906 alignnone" title="variations" src="http://lucd.info/wp-content/uploads/2012/02/portkeys.png" alt="" /></a></p>
<p>Enjoy !</p>
<img src="http://feeds.feedburner.com/~r/LucdNotes/~4/BZeQS4OliJM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lucd.info/2012/02/14/dvswitch-scripting-part-12-find-free-ports/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.lucd.info/2012/02/14/dvswitch-scripting-part-12-find-free-ports/</feedburner:origLink></item>
		<item>
		<title>Variations on a port</title>
		<link>http://feedproxy.google.com/~r/LucdNotes/~3/rV72EKYnFhM/</link>
		<comments>http://www.lucd.info/2012/01/29/variations-on-a-port/#comments</comments>
		<pubDate>Sun, 29 Jan 2012 16:34:11 +0000</pubDate>
		<dc:creator>LucD</dc:creator>
				<category><![CDATA[dvSwitch]]></category>
		<category><![CDATA[New-VIProperty]]></category>
		<category><![CDATA[PowerCLI]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[SDK]]></category>
		<category><![CDATA[port]]></category>

		<guid isPermaLink="false">http://www.lucd.info/?p=3891</guid>
		<description><![CDATA[I got an interesting question from one of my co-authors of the PowerCLI Reference book. He was looking for a method to find the port used by a VM when connected to a portgroup on a dvSwitch. Finding the answer to that question is not too difficult, once you know which property holds the value. [...]]]></description>
			<content:encoded><![CDATA[<p>I got an interesting question from one of my co-authors of the <a href="http://www.powerclibook.com/" target="_blank">PowerCLI Reference</a> book. He was looking for a method to find the <strong>port</strong> used by a <strong>VM</strong> when connected to a <strong>portgroup</strong> on a <a href="http://www.lucd.info/category/vsphere/dvswitch/" target="_blank">dvSwitch</a>.</p>
<p style="text-align: left;">Finding the answer to that question is not too difficult, once you know which property holds the value. But while writing and testing the script, I thought that this question would be a good opportunity to show several ways and methods that you have at your disposal in <a href="http://communities.vmware.com/community/vmtn/server/vsphere/automationtools/powercli?view=overview" target="_blank">PowerCLI</a> and PowerShell, to come to a solution.</p>
<p style="text-align: left;"><a href="http://lucd.info/wp-content/uploads/2012/01/JSBvariations.jpg"><img class=" wp-image-3906 alignnone" title="variations" src="http://lucd.info/wp-content/uploads/2012/01/JSBvariations.jpg" alt="" width="450" height="188" /></a></p>
<p style="text-align: left;">Here it goes.</p>
<p><span id="more-3891"></span></p>
<span id="The_basic_solution"><h2>The basic solution</h2></span>
<p>With a bit of (logical) thinking and the help of the <strong>Get-Member</strong> cmdlet, it didn&#8217;t take long to discover where the <a href="http://www.lucd.info/category/vsphere/dvswitch/" target="_blank">dvSwitch</a> port information is hiding.</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/VMport.png"><img class="alignnone  wp-image-3926" title="VMport" src="http://lucd.info/wp-content/uploads/2012/01/VMport.png" alt="" width="476" height="313" /></a></p>
<p>As a matter of fact the port information is kept with the <a href="http://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.VirtualMachine.html" target="_blank">VirtualMachine</a> itself, under the virtual devices, in the NIC backing object, which is called <a href="http://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.vm.device.VirtualEthernetCard.DistributedVirtualPortBackingInfo.html" target="_blank">VirtualEthernetCardDistributedVirtualPortBackingInfo</a>.</p>
<p>A quick-and-dirty script to get the ports could look like this.</p>
<pre class="brush: powershell; title: ; notranslate">
foreach($vm in Get-VM){
  $vm.NetworkAdapters | Select @{N=&quot;VM&quot;;E={$vm.Name}},
  @{N=&quot;NIC&quot;;E={$_.Name}},
  @{N=&quot;PG&quot;;E={$_.NetworkName}},
  @{N=&quot;Port&quot;;E={$_.ExtensionData.Backing.Port.PortKey}}
}
</pre>
<span id="Annotations"><h4>Annotations</h4></span>
<p><strong>Line 2</strong>: The script loops through all NIC that are defined on a VM</p>
<p>The result will appear on screen and will look something like this.</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/port-basic.png"><img class="alignnone  wp-image-3918" title="port-basic" src="http://lucd.info/wp-content/uploads/2012/01/port-basic.png" alt="" width="520" height="160" /></a></p>
<p>Notice that for NICs that are connected to <strong>standard portgroups</strong>, the Port property is left <strong>empty</strong>.</p>
<p>To get the results into a CSV file, you will have to store the results temporarily in a variable, and then, after the ForEach loop, you can pipe this variable to the Export-Csv cmdlet.</p>
<pre class="brush: powershell; title: ; notranslate">
$report = foreach($vm in Get-VM){
  $vm.NetworkAdapters | Select @{N=&quot;VM&quot;;E={$vm.Name}},
  @{N=&quot;NIC&quot;;E={$_.Name}},
  @{N=&quot;PG&quot;;E={$_.NetworkName}},
  @{N=&quot;Port&quot;;E={$_.ExtensionData.Backing.Port.PortKey}}
}

$report | Export-Csv &quot;C:\report.csv&quot; -NoTypeInformation -UseCulture
</pre>
<span id="A_faster_solution"><h2>A faster solution</h2></span>
<p>When you visited the <a href="http://communities.vmware.com/community/vmtn/server/vsphere/automationtools/powercli?view=discussions&amp;start=0" target="_blank">PowerCLI Community</a> recently, you might have noticed that there is a <a href="http://communities.vmware.com/poll.jspa?poll=1327" target="_blank">poll</a> going on about &#8216;regular&#8217; and &#8216;fast&#8217; solutions. A &#8216;regular&#8217; solution would be one that uses the PowerCLI cmdlets to retrieve <strong>PowerCLI objects</strong> and a &#8216;fast&#8217; solution is one that uses the <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/Get-View.html" target="_blank">Get-View</a> cmdlet to retrieve (read-only copies of) <strong>vSphere objects</strong>.</p>
<p>In bigger environments the difference in execution time between regular and fast solutions might be substantial.</p>
<p>So how would we tackle the problem at hand with a &#8216;fast&#8217; solution ?</p>
<pre class="brush: powershell; title: ; notranslate">
$Nics = &quot;VirtualE1000&quot;,&quot;VirtualE1000e&quot;,&quot;VirtualPCNet32&quot;,&quot;VirtualVmxnet&quot;,&quot;VirtualVmxnet2&quot;,&quot;VirtualVmxnet3&quot;

foreach($vm in (Get-View -ViewType VirtualMachine -Property Name,Network,Config.Hardware.Device)){
  $pgs = @{}
  Get-View $vm.Network | %{
    if($_.Key){$key = $_.Key}else{$key=$_.MoRef.Value}
    $pgs.Add($key,$_.Name)
  }

  $vm.Config.Hardware.Device | where {$Nics -contains $_.GetType().Name} |
  Select @{N=&quot;VM&quot;;E={$vm.Name}},
    @{N=&quot;NIC&quot;;E={$_.DeviceInfo.Label}},
    @{N=&quot;PG&quot;;E={
      if($_.Backing.Port){$key=$_.Backing.Port.PortgroupKey}else{$key=$_.Backing.Network.Value}
      $pgs[$key]}},
    @{N=&quot;Port&quot;;E={$_.Backing.Port.PortKey}}
}
</pre>
<span id="Annotations_1"><h4>Annotations</h4></span>
<p><strong>Line 1</strong>: To select the NIC devices, out of all other devices connected to the VM, the script will check if the Type of the Device is present in this array. This array contains the typenames of all possible NIC types.</p>
<p><strong>Line 3</strong>: The script retrieves all the VMs. In the Property parameter the script tells the engine to only fetch those specific properties. This will cause a time saving in the execution time.</p>
<p><strong>Line 4-8</strong>: The NIC device object does not have a property with the actual name of the portgroup to which it is connected. There is a property that has a &#8216;key&#8217; for the portgroups. To avoid having to scan the connected portgroups each time to find the name, the script sets up a hash table.</p>
<p><strong>Line 10</strong>: This line will loop through all devices connected to the VM and will only pass the NIC devices to the Select-Object in the following line.</p>
<p><strong>Line 14</strong>: The key that points to the portgroup (see above) is stored in a different property, depending if the portgroup is a regular or a distributed portgroup.</p>
<p><strong>Line 15</strong>: The portgroupname is retrieved from the hash table.</p>
<p>This &#8216;fast&#8217; version of the script looks, and is, more complex than the basic function we showed before. The reason for that is that the script will have to do everything, like finding the portgroupname, by itself. In the basic function, which uses PowerCLI objects, a lot of that work is done by the logic behind the PowerCLI cmdlet.</p>
<p>It makes you appreciate the work the <strong>PowerCLI Dev Team</strong> put in the development of the PowerCLI cmdlets, even more.</p>
<p>The output of this script looks of course exactly the same (besides the order in which the VM object are returned).</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/port-fast.png"><img class="alignnone  wp-image-3920" title="port-fast" src="http://lucd.info/wp-content/uploads/2012/01/port-fast.png" alt="" width="531" height="154" /></a></p>
<span id="A_function"><h2>A function</h2></span>
<p>If we want to report on these port numbers regularly, it is better to write a function around the logic we have from the scripts above. A function will allow us to call the functionality, just like we would call any other cmdlet.</p>
<p>Let&#8217;s create the function in such a way that we can retrieve the port information in 2 ways.</p>
<ul>
<li>Retrieve the port information for one or more VMs (similar to the functions above)</li>
<li>Retrieve the port information for all VMs connected to specific Portgroups</li>
</ul>
<p>By using parameter sets it is quite easy to package both methods in 1 function. Something like this</p>
<pre class="brush: powershell; title: ; notranslate">
function Get-dvVmPort{
&lt;#
.SYNOPSIS  Get the dvSwitch port for a VM network adapter
.DESCRIPTION The function will retrieve the dvSwitch port
  for all network adapters, provided the network adapters
  are connected to a dvSwitch.
.NOTES  Author:  Luc Dekens
.PARAMETER VM
  Specify the virtual machine(s) for whose network adapters
  you want to retrieve the port numbers.
.PARAMETER PortGroup
  Specify the portgroup(s) for which you want to retrieve
  the port numbers for all network adapters that have a
  connection to the portgroup(s)
.EXAMPLE
  PS&gt; Get-dvVmPort
.EXAMPLE
  PS&gt; Get-dvVmPort -VM VM1,VM2,VM3
.EXAMPLE
  PS&gt; Get-VM -Name VM* | Get-dvVmPort
.EXAMPLE
  PS&gt; Get-dvVmPort -PortGroup dvPg1
#&gt;

  [CmdletBinding(DefaultParametersetName=&quot;VM&quot;)]
  param(
  [parameter(ParameterSetName=&quot;VM&quot;,ValueFromPipeline = $true)]
  [PSObject[]]$VM,
  [parameter(ParameterSetName=&quot;Portgroup&quot;)]
  [PSObject[]]$Portgroup
  )

  begin{
    $Nics = &quot;VirtualE1000&quot;,&quot;VirtualE1000e&quot;,&quot;VirtualPCNet32&quot;,&quot;VirtualVmxnet&quot;,
    &quot;VirtualVmxnet2&quot;,&quot;VirtualVmxnet3&quot;
    $pgMask = Get-VirtualPortGroup | Sort-Object -Unique | %{$_.Name}
  }

  process{
    switch($PSCmdlet.ParameterSetName){
      &quot;VM&quot;{
        if($VM){
          if($VM[0] -isnot [String]){
            $VM = $VM | %{$_.Name}
          }
          $names = [string]::Join('|',($VM | %{$_}))
        }
        else{
          $names = &quot;.+&quot;
        }
        $VMs = @(Get-View -ViewType VirtualMachine -Filter @{&quot;Name&quot;=$names})
      }
      &quot;Portgroup&quot;{
        if($PortGroup[0] -isnot [String]){
          $PortGroup = $PortGroup | %{$_.Name}
        }
        $names = [string]::Join('|',($PortGroup | %{$_}))
        $PortGroups = @(Get-View -ViewType DistributedVirtualPortgroup -Filter @{&quot;Name&quot;=$names})
        $pgMask = $PortGroups | %{$_.Name}
        $VMs = $PortGroups | where {$_.Vm} | %{Get-View -Id $_.Vm} | Sort-Object -Property Name -Unique
      }
    }
    if($VMs){
      foreach($object in $VMs){
        $pgs = @{}
        Get-View $object.Network | %{
          if($_.Key){$key = $_.Key}else{$key = $_.MoRef.Value}
          $pgs.Add($key,$_.Name)
        }

        $object.Config.Hardware.Device |
        where {$Nics -contains $_.GetType().Name} | %{
          New-Object PSOBject -Property @{
            VM = $object.Name
            NIC = $_.DeviceInfo.Label
            PortGroup = &amp;{
              if($_.Backing.Port){
                $key = $_.Backing.Port.PortgroupKey
              }
              else{
                $key = $_.Backing.Network.Value
              }
              $pgs[$key]
            }
            Port = $_.Backing.Port.PortKey
          } | where {$pgMask -contains $_.PortGroup}
        }
      }
    }
  }
}
</pre>
<span id="Annotations_2"><h4>Annotations</h4></span>
<p><strong>Line 27-30</strong>: The function uses 2 parametersets, one to pass VMs and one to pass Portgroups. The default is VMs.</p>
<p><strong>Line 29</strong>: Note that the script doesn&#8217;t accept Portgroups from the pipeline. Implementing such a feature is possible, but would require testing the type of the parameter value. I used the &#8216;keep it simple&#8217; rule <img src='http://lucd.info/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p><strong>Line 34-35</strong>: The script needs to test if the device is a NIC. This array should contain all the possible NIC types a VM can have.</p>
<p><strong>Line 36,59,86</strong>: For the PortGroup parameter the script needs to test if the VM under investigation is connected to the requested portgroup. By default we take all the portgroups. If the PortGroup parameter is used, the script will only report on NICs connected to that portgroup.</p>
<p><strong>Line 40-62</strong>: The Switch statement which handles the 2 parametersets.</p>
<p><strong>Line 43-50</strong>: For the VM parameter the script can handle 1 or more VM names, or 1 or more <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/VirtualMachine.html" target="_blank">VirtualMachineImpl</a> objects.</p>
<p><strong>Line 49</strong>: When no value is passed with the VM parameter, the script will take all VMs known in the connected vCenter. Since the script uses the Get-View cmdlet with the Filter parameter, the regular expression &#8216;.+&#8217; is used to find all VMs.</p>
<p><strong>Line 51,60</strong>: For both parametersets, the script passes a variable $VMs to the code after the Switch statement. The $VMs variable is populated with the VMs for which the portgroup port needs to be reported upon.</p>
<p><strong>Line 57</strong>: The mask for the Get-View <strong>Filter</strong> parameter is generated. It&#8217;s of the form &#8220;vm1|vm2|vm3&#8243;</p>
<p><strong>Line 65-69</strong>: The script uses a hash table to allow the portgroup name to be retrieved  with the portgroup key.</p>
<p><strong>Line 71-86</strong>: For each NIC an object holding the information is generated.</p>
<p><strong>Line 78,81</strong>: Note that the portgroup key is located in different properties, depending if the portgroup is on a regular vSwitch or a distributed vSwitch.</p>
<p>There are several ways you can call the function. Some examples</p>
<pre class="brush: powershell; title: ; notranslate">
Get-dvVmPort | Sort-Object -Property VM,NIC | Select VM,NIC,PortGroup,Port
</pre>
<p>No parameter is passed, so the <strong>VM</strong> parameterset will be chosen. The function will report on all the available VMs. This will produce the following output.<br />
<a href="http://lucd.info/wp-content/uploads/2012/01/fport-ex1.png"><img class="alignnone  wp-image-3928" title="fport-ex1" src="http://lucd.info/wp-content/uploads/2012/01/fport-ex1.png" alt="" width="558" height="159" /></a></p>
<p>Note that we had to use a Select-Object cmdlet to define the order of the displayed properties. In <strong>PowerShell v2</strong> one doesn&#8217;t have any way to specify the order of the properties defined ona <strong>New-Object</strong> cmdlet. In <strong>PowerShell v3</strong> this will change !</p>
<p>Another example, with a selected set of VM that are passed through the pipeline.</p>
<pre class="brush: powershell; title: ; notranslate">
Get-VM -Name &quot;VM[13]&quot; | Get-dvVmPort | Sort-Object -Property VM,NIC | Select VM,NIC,PortGroup,Port
</pre>
<p>This will give</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/fport-ex2.png"><img class="alignnone  wp-image-3930" title="fport-ex2" src="http://lucd.info/wp-content/uploads/2012/01/fport-ex2.png" alt="" width="576" height="88" /></a></p>
<p>And finally an example with the <strong>PortGroup</strong> parameterset.</p>
<pre class="brush: powershell; title: ; notranslate">
Get-dvVmPort -Portgroup (Get-VirtualPortGroup -Distributed) |  Select VM,NIC,PortGroup,Port
</pre>
<p>This call will produce a report on all the VMs that have a NIC connected to any of the distributed portgroups.</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/fport-ex3.png"><img class="alignnone  wp-image-3931" title="fport-ex3" src="http://lucd.info/wp-content/uploads/2012/01/fport-ex3.png" alt="" width="597" height="126" /></a></p>
<span id="A_new_property"><h2>A new property</h2></span>
<p>If we want to display this port information with each NIC connected to a VM, when we do a <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/Get-NetworkAdapter.html" target="_blank">Get-NetworkAdapter</a>, we can wrap the above logic in a <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/New-VIProperty.html" target="_blank">New-VIProperty</a>.</p>
<p>The <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/New-VIProperty.html" target="_blank">New-VIProperty</a> cmdlet allows us to extend the default set of properties that come with a PowerCLI object.</p>
<p>In this case the code is quite simple</p>
<pre class="brush: powershell; title: ; notranslate">
New-VIProperty -Name dvPort -ObjectType NetworkAdapter `
  -Value {
    param($nic)

    $nic.ExtensionData.Backing.Port.PortKey
  } -Force | Out-Null
</pre>
<p>When we do</p>
<pre class="brush: powershell; title: ; notranslate">
Get-VM -Name VM4 | Get-NetworkAdapter | Select Name,NetworkName,dvPort | Format-Table
</pre>
<p>We will get the following.</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/newviproperty.png"><img class="alignnone  wp-image-3933" title="newviproperty" src="http://lucd.info/wp-content/uploads/2012/01/newviproperty.png" alt="" width="536" height="98" /></a></p>
<p>I hope this showed a bit the numerous possibilities you have with PowerCLI and PowerShell to tackle your vSphere administrative tasks.</p>
<p>Enjoy !</p>
<img src="http://feeds.feedburner.com/~r/LucdNotes/~4/rV72EKYnFhM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lucd.info/2012/01/29/variations-on-a-port/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.lucd.info/2012/01/29/variations-on-a-port/</feedburner:origLink></item>
		<item>
		<title>Get complete vCenter session info</title>
		<link>http://feedproxy.google.com/~r/LucdNotes/~3/RIysJySLnH8/</link>
		<comments>http://www.lucd.info/2012/01/17/get-complete-vcenter-session-info/#comments</comments>
		<pubDate>Tue, 17 Jan 2012 19:03:39 +0000</pubDate>
		<dc:creator>LucD</dc:creator>
				<category><![CDATA[event]]></category>
		<category><![CDATA[PowerCLI]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Session Manager]]></category>
		<category><![CDATA[SessionManager]]></category>

		<guid isPermaLink="false">http://www.lucd.info/?p=3869</guid>
		<description><![CDATA[There was an interesting thread in the PowerCLI Community today. It raised the question how one could report on the current vCenter sessions, including the IP address or hostname from where the session was started. Unfortunately the SessionManager doesn&#8217;t hold any information from where the session was started. But there are other ways of finding [...]]]></description>
			<content:encoded><![CDATA[<p>There was an interesting <a href="http://communities.vmware.com/thread/343345?tstart=0" target="_blank">thread</a> in the <a href="http://communities.vmware.com/community/vmtn/server/vsphere/automationtools/powercli?view=discussions&amp;start=0" target="_blank">PowerCLI Community</a> today. It raised the question how one could report on the current vCenter sessions, including the <strong>IP address</strong> or <strong>hostname</strong> from where the session was started.</p>
<p>Unfortunately the <a href="http://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.SessionManager.html" target="_blank">SessionManager</a> doesn&#8217;t hold any information from where the session was started.</p>
<p>But there are other ways of finding that information. The <a href="http://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.event.UserLoginSessionEvent.html" target="_blank">UserLoginSessionEvent</a> object has a property, called <strong>ipAddress</strong>, that has the information we&#8217;re after.</p>
<p>Btw if you are only interested in looking for idle sessions, independent from which host they were started, there is a great post, called <a href="http://blogs.vmware.com/vipowershell/2011/09/list-and-disconnect-vcenter-sessions.html" target="_blank">List and Disconnect vCenter Sessions</a> on the <a href="http://blogs.vmware.com/vipowershell/" target="_blank">PowerCLI blog</a>.</p>
<p><span style="background-color: #ffff00;"><strong>Update May 4th 2012</strong>: function updated to handle multiple vCenter connections.</span><br />
<span id="more-3869"></span></p>
<span id="The_script"><h2>The script</h2></span>
<pre class="brush: powershell; title: ; notranslate">
function Get-VISessionInfo{
&lt;#
.SYNOPSIS  Retrieve vCenter session information
.DESCRIPTION The function will retrieve the open vCenter
  session, including the IP address and hostname from where
  the session was started
.NOTES  Author:  Luc Dekens
.PARAMETER AllowedDifference
  The timestamps from the Session Manager entries and the
  event objects can sometimes differ, depending on the vCenter
  activity. The default is 1 second, but this can be changed
  with this parameter. The unit for this parameter is seconds.
.EXAMPLE
  PS&gt; Get-VISessionInfo
#&gt;

  param(
  [CmdletBinding()]
  [int]$AllowedDifference = 1
  )

  process{
    if((Get-PowerCLIConfiguration).DefaultVIServerMode -eq &quot;Multiple&quot;){
      $vcenter = $defaultVIServers
    }
    else{
      $vcenter = $defaultVIServers[0]
    }

    foreach($vc in $vcenter){
      $sessMgr = Get-View SessionManager -Server $vc
      $oldest = ($sessMgr.SessionList | Sort-Object -Property LoginTime | Select -First 1).LoginTime
      $users = $sessMgr.SessionList | %{$_.UserName}
      $events = Get-VIEvent -MaxSamples ([int]::MaxValue) -Start $oldest.AddHours(-1) -Server $vc |
      where {$_ -is [VMware.Vim.UserLoginSessionEvent] -and $users -contains $_.UserName} |
      Sort-Object -Property CreatedTime

      $allowedDiffTS = New-TimeSpan -Seconds $AllowedDifference

      foreach($session in $sessMgr.SessionList){
        $events |
        where {[math]::Abs(($session.LoginTime.ToLocalTime() - $_.CreatedTime).Ticks) -lt $allowedDiffTS.Ticks -and
          $users -contains $_.UserName} | %{
          New-Object PSObject -Property @{
            vCenter = $vc.Name
            &quot;Session login&quot; = $session.LoginTime
            UserName = $_.UserName
            IPAddress = $_.IPAddress
            Hostname = [System.Net.Dns]::GetHostEntry($_.IPAddress).HostName
          }
        }
      }
    }
  }
}
</pre>
<span id="Annotations"><h4>Annotations</h4></span>
<p><strong>Line 23-28</strong>: If the PowerCLI session is configured in &#8220;Multiple&#8221; mode, the function will loop through all connected vCenters. The <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/Get-PowerCLIConfiguration.html" target="_blank">Get-PowerCLIConfiguration</a> cmdlet is used to retrieve the active mode.</p>
<p><strong>Line 32</strong>: The script will look for the session with the oldest login time. This will allow us to limit the number of events that need to be retrieved.</p>
<p><strong>Line 33</strong>: Besides the timestamps, the script will also check if the username that appears in an user session login event, is one of the users that has an open vCenter session.</p>
<p><strong>Line 34-36</strong>: We retrieve the <a href="http://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.event.UserLoginSessionEvent.html" target="_blank">UserLoginSessionEvent</a> for users that have an open vCenter session.</p>
<p><strong>Line 38</strong>: The time difference we allow between the timestamp in the session and the corresponding <a href="http://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.event.UserLoginSessionEvent.html" target="_blank">UserLoginSessionEvent</a> is converted to a TimeSpan object.</p>
<p><strong>Line 42</strong>: To link a vCenter session to a <a href="http://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.event.UserLoginSessionEvent.html" target="_blank">UserLoginSessionEvent</a> the script calculates the time difference between the timestamps in the <a href="http://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.event.UserLoginSessionEvent.html" target="_blank">UserLoginSessionEvent</a> and the session object from the SessionManager. If the absolute time difference falls below the accepted time difference ($AllowedDifference), the event is linked to the session.</p>
<p><strong>Line 44-49</strong>: The result is placed in the pipeline</p>
<p><strong>Line 45</strong>: The output contains the name of the vCenter where the session was found.</p>
<p><strong>Line 49</strong>: The script converts the IP address to the <strong>hostname</strong> with the <a href="http://msdn.microsoft.com/en-US/library/ms143998(v=vs.80).aspx" target="_blank">GetHostEntry</a> method.</p>
<span id="Sample_usage"><h2>Sample usage</h2></span>
<p>The function is rather simple in use.</p>
<pre class="brush: powershell; title: ; notranslate">

Get-VISessionInfo
</pre>
<p>And the result looks something like this.</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/visession.png"><img class="alignnone size-full wp-image-3885" title="visession" src="http://lucd.info/wp-content/uploads/2012/01/visession.png" alt="" width="548" height="166" /></a></p>
<p>Enjoy!</p>
<img src="http://feeds.feedburner.com/~r/LucdNotes/~4/RIysJySLnH8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lucd.info/2012/01/17/get-complete-vcenter-session-info/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://www.lucd.info/2012/01/17/get-complete-vcenter-session-info/</feedburner:origLink></item>
		<item>
		<title>Proxy cmdlet revisited: Connect-VIServer and Disconnect-VIServer</title>
		<link>http://feedproxy.google.com/~r/LucdNotes/~3/V3E-HsbfbZM/</link>
		<comments>http://www.lucd.info/2012/01/16/proxy-cmdlet-revisted-connect-viserver-and-disconnect-viserver/#comments</comments>
		<pubDate>Mon, 16 Jan 2012 18:12:05 +0000</pubDate>
		<dc:creator>LucD</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[proxy]]></category>
		<category><![CDATA[Connect-VIServer]]></category>
		<category><![CDATA[Disconnect-VIServer]]></category>
		<category><![CDATA[PowerCLI]]></category>

		<guid isPermaLink="false">http://www.lucd.info/?p=3855</guid>
		<description><![CDATA[In PowerCLI 5.0.1 a handy feature that showed the connected vSphere Servers in the title bar of the PowerCLI window was apparently removed. In a PowerCLI Community thread some users found this a useful feature that they would like to have back. I&#8217;m sure the PowerCLI Team will listen to their users and fix this [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://communities.vmware.com/community/vmtn/server/vsphere/automationtools/powercli?view=overview" target="_blank">PowerCLI 5.0.1</a> a handy feature that showed the connected vSphere Servers in the title bar of the PowerCLI window was apparently removed.<br />
In a PowerCLI Community <a href="http://communities.vmware.com/thread/342796?tstart=0" target="_blank">thread</a> some users found this a useful feature that they would like to have back.<br />
I&#8217;m sure the PowerCLI Team will listen to their users and fix this problem in the coming PowerCLI version.</p>
<p>But while we are waiting for a new PowerCLI build that brings back the title bar text, you can fix this for yourself thanks to the proxy cmdlet feature.</p>
<p><span id="more-3855"></span></p>
<p>Proxy cmdlets is (another) handy feature in PowerShell which allows you to modify and extend existing cmdlets. You can add parameters, change the output and do other crazy things. In the <a href="http://blogs.msdn.com/b/powershell/archive/2009/01/04/extending-and-or-modifing-commands-with-proxies.aspx" target="_blank">Extending and/or Modifing Commands with Proxies</a> post from Jeffrey Snover you can find all the details.</p>
<p>In that same post you can also find the MetaProgramming module which makes it a breeze to customise cmdlets.</p>
<p>You just call the New-ProxyCommand and redirect the output to a .ps1 file, which you can then use to write your customisations for the cmdlet.</p>
<p>In this case I did that for the <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/Connect-VIServer.html" target="_blank">Connect-VIServer</a> and <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/Disconnect-VIServer.html" target="_blank">Disconnect-VIServer</a> cmdlets as follows</p>
<pre class="brush: powershell; title: ; notranslate">

New-ProxyCommand Connect-VIServer &gt; .\Connect-VIServer.ps1

New-ProxyCommand Disconnect-VIServer &gt; .\Disconnect-VIServer.ps1
</pre>
<p>The resulting .ps1 files can now be edited to introduce our customisations to these cmdlets.</p>
<span id="My_Connect-VIServer"><h2>My Connect-VIServer</h2></span>
<pre class="brush: powershell; title: ; notranslate">
function Connect-VIServer{
  [CmdletBinding(DefaultParameterSetName='Default')]
  param(
  [Parameter(ParameterSetName='Default', Mandatory=$true, Position=0)]
  [ValidateNotNullOrEmpty()]
  [System.String[]]
  ${Server},

  [Parameter(ParameterSetName='Default')]
  [ValidateNotNull()]
  [ValidateRange(0, 65535)]
  [System.Int32]
  ${Port},

  [Parameter(ParameterSetName='Default')]
  [ValidateSet('http','https')]
  [System.String]
  ${Protocol},

  [Parameter(ParameterSetName='Default', ValueFromPipeline=$true)]
  [ValidateNotNullOrEmpty()]
  [System.Management.Automation.PSCredential]
  ${Credential},

  [Parameter(ParameterSetName='Default', ValueFromPipeline=$true)]
  [Alias('Username')]
  [System.String]
  ${User},

  [Parameter(ParameterSetName='Default')]
  [System.String]
  ${Password},

  [Parameter(ParameterSetName='Default')]
  [System.String]
  ${Session},

  [Parameter(ParameterSetName='Default')]
  [switch]
  ${NotDefault},

  [Parameter(ParameterSetName='Default')]
  [switch]
  ${SaveCredentials},

  [Parameter(ParameterSetName='Default')]
  [switch]
  ${AllLinked},

  [Parameter(ParameterSetName='Menu', Mandatory=$true)]
  [switch]
  ${Menu})

  begin
  {
    try {
      $outBuffer = $null
      if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
      {
        $PSBoundParameters['OutBuffer'] = 1
      }
      $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Connect-VIServer', [System.Management.Automation.CommandTypes]::Cmdlet)
      $scriptCmd = {&amp; $wrappedCmd @PSBoundParameters }
      $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
      $steppablePipeline.Begin($PSCmdlet)
    } catch {
      Throw
    }
  }

  process
  {
    try {
      $steppablePipeline.Process($_)
    } catch {
      Throw
    }
    switch($defaultVIServers.Count){
      0 {
        $text = &quot;Not Connected&quot;
      }
      1 {
        $text = &quot;Connected to &quot; + $defaultVIServers[0].Name + &quot; as &quot; + $defaultVIServers[0].User
      }
      Default {
        $text = &quot;Connected to &quot; + $defaultVIServers.Count + &quot; servers: &quot;
        $text += [string]::Join(',',($defaultVIServers | %{$_.Name}))
      }
    }
    (Get-Host).UI.RawUI.WindowTitle = $text
  }

  end
  {
    try {
      $steppablePipeline.End()
    } catch {
      Throw
    }
  }
&lt;#

.ForwardHelpTargetName Connect-VIServer
.ForwardHelpCategory Cmdlet

#&gt;
}
</pre>
<span id="Annotations"><h4>Annotations</h4></span>
<p><strong>Line 1,107</strong>: We make this a function<br />
<strong>Line 78,90</strong>: The code we add to the original cmdlet. This will place the text in the title bar.</p>
<span id="My_Disconnect-VIServer"><h2>My Disconnect-VIServer</h2></span>
<pre class="brush: powershell; title: ; notranslate">
function Disconnect-VIServer{
  [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='High')]
  param(
  [Parameter(Position=0, ValueFromPipeline=$true)]
  [ValidateNotNullOrEmpty()]
  [VMware.VimAutomation.ViCore.Types.V1.VIServer[]]
  ${Server},

  [switch]
  ${Force})

  begin
  {
    try {
      $outBuffer = $null
      if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
      {
        $PSBoundParameters['OutBuffer'] = 1
      }
      $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Disconnect-VIServer', [System.Management.Automation.CommandTypes]::Cmdlet)
      $scriptCmd = {&amp; $wrappedCmd @PSBoundParameters }
      $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
      $steppablePipeline.Begin($PSCmdlet)
    } catch {
      Throw
    }
  }

  process
  {
    try {
      $steppablePipeline.Process($_)
    } catch {
      Throw
    }
    switch($defaultVIServers.Count){
      0 {
        $text = &quot;Not Connected&quot;
      }
      1 {
        $text = &quot;Connected to &quot; + $defaultVIServers[0].Name + &quot; as &quot; + $defaultVIServers[0].User
      }
      Default {
        $text = &quot;Connected to &quot; + $defaultVIServers.Count + &quot; servers: &quot;
        $text += [string]::Join(',',($defaultVIServers | %{$_.Name}))
      }
    }
    (Get-Host).UI.RawUI.WindowTitle = $text
  }

  end
  {
    try {
      $steppablePipeline.End()
    } catch {
      Throw
    }
  }
&lt;#

.ForwardHelpTargetName Disconnect-VIServer
.ForwardHelpCategory Cmdlet

#&gt;
}
</pre>
<span id="Annotations_1"><h4>Annotations</h4></span>
<p><strong>Line 1,65</strong>: We make this a function<br />
<strong>Line 36,48</strong>: The code we add to the original cmdlet. This will place the text in the title bar.</p>
<span id="Usage_samples"><h2>Usage samples</h2></span>
<p>First you will need to dot-source the .ps1 files with the customised versions of both cmdlets.</p>
<pre class="brush: powershell; title: ; notranslate">

. ./Connect-VIServer.ps1

. ./Disconnect-VIServer.ps1
</pre>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/dot-source.png"><img class="alignnone  wp-image-3857" title="dot-source" src="http://lucd.info/wp-content/uploads/2012/01/dot-source.png" alt="" width="330" height="94" /></a></pre>
<p>We now have a function and a cmdlet for both.</p>
<pre class="brush: powershell; title: ; notranslate">

Get-Command Connect-VIServer

Get-Command Disconnect-VIServer
</pre>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/commands.png"><img class="alignnone  wp-image-3858" title="commands" src="http://lucd.info/wp-content/uploads/2012/01/commands.png" alt="" width="521" height="202" /></a></p>
<p>But PowerShell will use a function before a cmdlet when both have the same name. Exactly what we need !</p>
<p>If you want to learn more about these precedences, do a</p>
<pre class="brush: powershell; title: ; notranslate">

Get-Help About_command_precendence
</pre>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/precedence.png"><img class="alignnone  wp-image-3859" title="precedence" src="http://lucd.info/wp-content/uploads/2012/01/precedence.png" alt="" width="517" height="151" /></a></p>
<p>Now we are ready to use our customised cmdlets. When we do a first connect</p>
<pre class="brush: powershell; title: ; notranslate">

$vc = Connect-VIServer -Server MyVC
</pre>
<p>the PowerCLI window will show</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/MyVC-connected1.png"><img class="alignnone  wp-image-3861" title="MyVC-connected" src="http://lucd.info/wp-content/uploads/2012/01/MyVC-connected1.png" alt="" width="406" height="64" /></a></p>
<p>When we connect an additional vSphere Server</p>
<pre class="brush: powershell; title: ; notranslate">

$esx = Connect-VIServer -Server MyEsx1 -User root -Password MyPswd
</pre>
<p>the PowerCLI window will show.</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/MyEsx1-connected.png"><img class="alignnone  wp-image-3862" title="MyEsx1-connected" src="http://lucd.info/wp-content/uploads/2012/01/MyEsx1-connected.png" alt="" width="498" height="59" /></a></p>
<p>When we disconnect from one of the vSphere Servers, the title bar will be updated as well.</p>
<pre class="brush: powershell; title: ; notranslate">

Disconnect-VIServer -Server $vc
</pre>
<p>The title bar will show</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/MyVC-disconnected.png"><img class="alignnone  wp-image-3863" title="MyVC-disconnected" src="http://lucd.info/wp-content/uploads/2012/01/MyVC-disconnected.png" alt="" width="496" height="60" /></a></p>
<p>There are of a couple of open problems</p>
<ul>
<li>The initial PowerCLI window shows "<strong>Not connected</strong>". This could eventually be solved by adapting the PowerCLI initialisation script, but I didn't want to change that script</li>
<li>The Disconnect-VIServer cmdlet also accepts a [<strong>string</strong>] for the <strong>Server</strong> argument. The proxy cmdlet doesn't accept that, you will have to give it a VIServer object on the Server parameter.</li>
</ul>
<p>Enjoy !</p>
<img src="http://feeds.feedburner.com/~r/LucdNotes/~4/V3E-HsbfbZM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lucd.info/2012/01/16/proxy-cmdlet-revisted-connect-viserver-and-disconnect-viserver/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.lucd.info/2012/01/16/proxy-cmdlet-revisted-connect-viserver-and-disconnect-viserver/</feedburner:origLink></item>
		<item>
		<title>Change the root password in hosts and Host Profiles</title>
		<link>http://feedproxy.google.com/~r/LucdNotes/~3/-21bR_OSyRU/</link>
		<comments>http://www.lucd.info/2012/01/15/change-theroot-password-in-hosts-and-host-profiles/#comments</comments>
		<pubDate>Sun, 15 Jan 2012 21:40:03 +0000</pubDate>
		<dc:creator>LucD</dc:creator>
				<category><![CDATA[Host Profile]]></category>
		<category><![CDATA[password]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[root]]></category>
		<category><![CDATA[PowerCLI]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://www.lucd.info/?p=3846</guid>
		<description><![CDATA[For good security measures you should change the password of your root account on your ESX(i) servers on a regular basis. Instead of logging on to each and everyone of your ESX(I) servers, you can easily automate this process. But what about the new ESX(i) hosts you will roll out in between root password changes [...]]]></description>
			<content:encoded><![CDATA[<p>For good security measures you should change the password of your root account on your ESX(i) servers on a regular basis. Instead of logging on to each and everyone of your ESX(I) servers, you can easily automate this process.</p>
<p>But what about the new ESX(i) hosts you will roll out in between root password changes and where you use a <strong>Host Profile</strong> to configure these new ESX(i) hosts ? Will you need to run a script after the deployment to change the root password ?</p>
<p>Turns out that you can easily update  the root password in your Host Profile with the help of an SDK method.</p>
<p><span id="more-3846"></span></p>
<span id="The_installed_hosts"><h2>The installed hosts</h2></span>
<p>There are numerous scripts available in the blogosphere to accomplish this. But for good measure, this is one script that can do the task.</p>
<pre class="brush: powershell; title: ; notranslate">
$currentPswd = &quot;currentPassword&quot;
$newPswd = &quot;newPassword&quot;

$excludeServers = &quot;esx51&quot;,&quot;esx56&quot;

$multiState = (Get-PowerCLIConfiguration).DefaultVIServerMode
$warnings = (Get-PowerCLIConfiguration).DisplayDeprecationWarnings
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -Confirm:$false -DisplayDeprecationWarnings:$false | Out-Null

Get-VMHost | where{$excludeServers -notcontains $_.Name.Split('.')[0]} | %{
  Connect-VIServer -Server $_.Name -User root -Password $currentPswd | Out-Null
  Write-Verbose &quot;Connected to $_&quot;
  Set-VMHostAccount -UserAccount root -Password $newPswd -Confirm:$false | Out-Null
  Disconnect-VIServer -Server $_.Name -Confirm:$false
}

Set-PowerCLIConfiguration -DefaultVIServerMode $multiState -DisplayDeprecationWarnings $warnings -Confirm:$false | Out-Null
</pre>
<span id="Annotations"><h4>Annotations</h4></span>
<p><strong>Line 1-2</strong>:  Provide the current and the new password for the root account.</p>
<p><strong>Line 4</strong>: The script allows for ESX(i) hosts whose root password should not be changed to the password specified in this run of the script. These ESX(i) hosts can excluded by adding their hostname to this array.</p>
<p><strong>Line 6-8</strong>: The script needs to run in <strong>Multiple</strong> mode, in other words it needs connections to multiple vSphere servers at the same time. For the run of this script I also disable the warning messages for deprecated properties, this to avoid a long list of warning messages. The script remembers the current settings before changing them.</p>
<p><strong>Line 10</strong>: The script gets all the ESX(i) servers and excludes the ones we defined in the array in line 4.</p>
<p><strong>Line 11-14</strong>: The script makes a connection to the ESX(i) server and changes the password of the root account.</p>
<p><strong>Line 12</strong>: If you want to track the ESX(i) hosts for which the script is changing the root password, you can set the $verbosePreference variable to <strong>Continue</strong> instead of the default <strong>SilentlyContinue</strong>.</p>
<p><strong>Line 17</strong>: The script restores the PowerCLI Configuration settings.</p>
<span id="The_Host_Profile"><h2>The Host Profile</h2></span>
<p>When you use Host Profiles to configure your newly deployed ESX(i) servers, you will need to update the root account in those Host Profiles on a regular basis as well. That way the new ESX(i) hosts you roll out will immediately have the current root password.</p>
<pre class="brush: powershell; title: ; notranslate">
function Set-VMHostProfileExtended{
&lt;#
.SYNOPSIS  Update the root password in a Host Profile
.DESCRIPTION The function will update the root password in
  a Host Profile.
.NOTES  Author:  Luc Dekens
.PARAMETER Profile
  The Host Profile for which you want to change the root
  password. You can pass the name of the Host Profile
  or the VMHostProfile object
.PARAMETER AdminPassword
  The new root password.
.EXAMPLE
  PS&gt; $prof = Get-VMHostProfile -Name MyProfile
  PS&gt; Set-VMHostProfileExtended -Profile $prof -AdminPassword &quot;abc&quot;
#&gt;

  param(
  [CmdletBinding()]
  [parameter(Mandatory = $true, ValueFromPipeline = $true)]
  [PSObject]$Profile,
  [string]$AdminPassword
  )

  begin{
    function Copy-Property ($From, $To, $PropertyName =&quot;*&quot;)
    {
      foreach ($p in Get-Member -In $From -MemberType Property -Name $propertyName)
      {        trap {
          Add-Member -In $To -MemberType NoteProperty -Name $p.Name -Value $From.$($p.Name) -Force
          continue
        }
        $To.$($P.Name) = $From.$($P.Name)
      }
    }
  }

  process{
    if($Profile.GetType().Name -eq &quot;string&quot;){
      $Profile = Get-VMHostProfile -Name $Profile -Server $defaultVIServers[0]
    }

    $spec = New-Object VMware.Vim.HostProfileCompleteConfigSpec

    Copy-Property -From $Profile.ExtensionData.Config -To $spec

    $secpol = New-Object VMware.Vim.ProfilePolicy
    $secpol.Id = &quot;AdminPasswordPolicy&quot;
    $secpol.PolicyOption = New-Object VMware.Vim.PolicyOption
    $secpol.PolicyOption.Id = &quot;FixedAdminPasswordOption&quot;
    $secpol.PolicyOption.Parameter += New-Object VMware.Vim.KeyAnyValue
    $secpol.PolicyOption.Parameter[0].Key = &quot;password&quot;
    $secpol.PolicyOption.Parameter[0].Value = New-Object VMware.Vim.PasswordField
    $secpol.PolicyOption.Parameter[0].Value.Value = $AdminPassword
    $spec.ApplyProfile.Security.Policy = @($secpol)

    $Profile.ExtensionData.UpdateHostProfile($spec)

    Get-VMHostProfile -Name $Profile.Name
  }
}
</pre>
<span id="Annotations_1"><h4>Annotations</h4></span>
<p><strong>Line 26-35</strong>: The function needs to copy all the <strong>Config</strong> properties from the <a href="http://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.profile.host.HostProfile.html" target="_blank">HostProfile</a> to the <a href="http://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.profile.host.HostProfile.CompleteConfigSpec.html" target="_blank">HostProfileCompleteConfigSpec</a> object. Instead of reinventing the wheel, I used a function called <a href="http://blogs.msdn.com/b/powershell/archive/2006/12/29/use-copy-property-to-make-it-easier-to-write-read-and-review-scripts.aspx">Copy-Property function</a> from <strong>Dennis Verwiej</strong>.</p>
<p><strong>Line 39-41</strong>: My simplistic Object By Name (OBN) implementation.</p>
<p><strong>Line 45</strong>: The copy of the <strong>Config</strong> property to the <a href="http://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.profile.host.HostProfile.CompleteConfigSpec.html" target="_blank">HostProfileCompleteConfigSpec</a> object.</p>
<p><strong>Line 47-55</strong>: To the copied HostProfile configuration the script adds the <strong>AdminPasswordPolicy</strong> definitions.</p>
<p><strong>Line 57</strong>: The <a href="http://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.profile.host.HostProfile.html" target="_blank">HostProfile</a> is updated with the <a href="http://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.profile.host.HostProfile.html#update" target="_blank">UpdateHostProfile</a> method.</p>
<p><strong>Line 59</strong>: To emulate the behaviour of the <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/Set-VMHostProfile.html" target="_blank">Set-VMHostProfile</a> cmdlet, the function places the updated <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/VMHostProfile.html" target="_blank">VMHostProfile</a> object on the pipeline.</p>
<span id="Sample_usage"><h2>Sample usage</h2></span>
<p>The function to update the Host Profile can be called with the Host Profile as a parameter.</p>
<pre class="brush: powershell; title: ; notranslate">
$hostProf = &quot;MyProfile&quot;
$newProf = Set-VMHostProfileExtended -Profile $hostProf -AdminPassword &quot;secret&quot;
</pre>
<p>or</p>
<pre class="brush: powershell; title: ; notranslate">
$hostProf = Get-VMHostProfile -Name MyProfile
$newProf = Set-VMHostProfileExtended -Profile $hostProf -AdminPassword &quot;secret&quot;
</pre>
<p>Or you can place the Host Profile on the pipeline.</p>
<pre class="brush: powershell; title: ; notranslate">
Get-VMHostProfile -Name MyProfile | Set-VMHostProfileExtended -AdminPassword &quot;secret&quot;
</pre>
<p>Notice that I called the function Set-VMHostProfileExtended. The reason for that is that one can update several other settings in a Host Profile this way. I&#8217;ll probably add some other settings to the function in a later stage.</p>
<p>Enjoy !</p>
<img src="http://feeds.feedburner.com/~r/LucdNotes/~4/-21bR_OSyRU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lucd.info/2012/01/15/change-theroot-password-in-hosts-and-host-profiles/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		<feedburner:origLink>http://www.lucd.info/2012/01/15/change-theroot-password-in-hosts-and-host-profiles/</feedburner:origLink></item>
		<item>
		<title>PowerCLI 5.0.1 goes Cloud</title>
		<link>http://feedproxy.google.com/~r/LucdNotes/~3/MphI8FwmN-s/</link>
		<comments>http://www.lucd.info/2012/01/10/powercli-5-0-1-goes-cloud/#comments</comments>
		<pubDate>Tue, 10 Jan 2012 04:55:32 +0000</pubDate>
		<dc:creator>LucD</dc:creator>
				<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[vCD]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[PowerCLI]]></category>

		<guid isPermaLink="false">http://www.lucd.info/?p=3811</guid>
		<description><![CDATA[As a belated Christmas present the new PowerCLI version 5.0.1 is available. This new build brings us the Cloud snapin. The availability of vCD cmdlets was already announced during VMworld 2011 and now the vCD cmdlets make their public appearance. The first release of the Cloud snapin brings us primarily Get type cmdlets. But there [...]]]></description>
			<content:encoded><![CDATA[<p>As a belated Christmas present the new <a href="http://www.vmware.com/downloads/download.do?downloadGroup=PCLI501" target="_blank"><strong>PowerCLI version 5.0.1</strong></a> is available. This new build brings us the <strong>Cloud snapin</strong>. The availability of vCD cmdlets was already announced during <strong>VMworld 2011</strong> and now the <strong>vCD cmdlets</strong> make their public appearance.</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/powercli-cloud1.png"><img class="alignnone size-full wp-image-3815" title="powercli-cloud" src="http://lucd.info/wp-content/uploads/2012/01/powercli-cloud1.png" alt="" width="545" height="407" /></a></p>
<p>The first release of the Cloud snapin brings us primarily <strong>Get</strong> type cmdlets. But there is more, just as the <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/Get-View.html" target="_blank">Get-View</a> cmdlet opened up access to the <strong>vSphere API</strong>, the new <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/Get-CIView.html" target="_blank">Get-CIView</a> cmdlet, and the <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/ExtensionData.html" target="_blank">ExtensionData</a> property, opens up access  to all the <strong>vCD APIs</strong>.</p>
<p><span id="more-3811"></span></p>
<p>First a quick list of all the cmdlets that are available in the Cloud snapin.</p>
<p><iframe src="https://sheet.zoho.com/publish/dekens.luc/powercli501-xref" frameborder="0" scrolling="no" width="500" height="400"></iframe></p>
<p><span style="font-size: x-small;">PS: the list above has been created with the script from my <a href="http://www.lucd.info/2011/03/04/powercli-cmdlet-xref-another-look/" target="_blank">PowerCLI cmdlet XRef – Another look</a> post.</span></p>
<p>The PowerCLI help pages are available <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/index.html" target="_blank">online</a>.</p>
<p>Btw the <strong>CI</strong> noun prefix that you will see as a prefix to most of the Cloud cmdlets nouns, stands for <strong>Cloud Infrastructure</strong>.</p>
<p>To start a session you use the <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/Connect-CIServer.html" target="_blank">Connect-CIServer</a> cmdlet, similar to what you do with the <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/Connect-VIServer.html" target="_blank">Connect-VIServer</a> cmdlet. The difference is that you will have to specify a <strong>vCloud Director server</strong> instead of a vSphere Server.</p>
<pre class="brush: powershell; title: ; notranslate">
Connect-Ciserver -Server MyVCD -User Luc -Password MyPswd
</pre>
<p>And you&#8217;ll immediately notice a first change, the Certificate warning message has changed. You are prompted to answer with one of the listed options.</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/connect-ciserver.png"><img class="alignnone  wp-image-3826" title="connect-ciserver" src="http://lucd.info/wp-content/uploads/2012/01/connect-ciserver.png" alt="" width="514" height="347" /></a></p>
<p>Does this mean you will have to do this every time (provided you don&#8217;t update the Certificate) ?<br />
No, the <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/Set-PowerCLIConfiguration.html" target="_blank">Set-PowerCLIConfiguration</a> cmdlet has been extended with a new parameter, called InvalidCertificateAction. You can provide the parameter with one of the values of the BadCertificateAction enumeration, and PowerCLI will take that as the default action for future connects.</p>
<p>Notice that we didn&#8217;t specify an Organization name, through the <strong>Org</strong> parameter, to the <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/Connect-CIServer.html" target="_blank">Connect-CIServer</a> cmdlet. That means your session will get connected to the System organization.</p>
<p>Once you are connected, you can start having a look around with the help of all the Get type cmdlets. The VMs in the Cloud</p>
<pre class="brush: powershell; title: ; notranslate">
Get-CIVM
</pre>
<p>returns something like<br />
<a href="http://lucd.info/wp-content/uploads/2012/01/get-civm.png"><img class="alignnone  wp-image-3827" title="get-civm" src="http://lucd.info/wp-content/uploads/2012/01/get-civm.png" alt="" width="510" height="67" /></a></p>
<p>The Roles that are present</p>
<pre class="brush: powershell; title: ; notranslate">

Get-CIRole
</pre>
<p>which gives</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/get-cirole.png"><img class="alignnone  wp-image-3828" title="get-cirole" src="http://lucd.info/wp-content/uploads/2012/01/get-cirole.png" alt="" width="508" height="96" /></a></p>
<p>And the available vApps in this cloud</p>
<pre class="brush: powershell; title: ; notranslate">

Get-CIvApp
</pre>
<p>This tells us there currently 4 vApps present</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/get-civapp.png"><img class="alignnone  wp-image-3829" title="get-civapp" src="http://lucd.info/wp-content/uploads/2012/01/get-civapp.png" alt="" width="478" height="89" /></a></p>
<p>But is this all we can do ? Only produce reports of what is available in our cloud ?</p>
<p>No, luckily there are already a couple of other cmdlets that will allow you to populate your cloud.</p>
<p>Let&#8217;s take the case where we want to import a VM from our vCenter into our Cloud.</p>
<p>First connect to the vCenter server, then get the VM you want to import and pass the VM to the <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/Import-CIVApp.html" target="_blank">Import-CIVApp</a> cmdlet. Note that for the creation of this new vApp you will have to provide an <strong>Organization VDC</strong>. The organization VDCs can be listed with the <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/Get-OrgVdc.html" target="_blank">Get-OrgVdc</a> cmdlet.</p>
<pre class="brush: powershell; title: ; notranslate">

Connect-VIServer -Server MyVC

$orgVdc = Get-OrgVdc -Name MyOrgVdc

Get-VM -Name TestVM2 | Import-CIVApp -OrgVdc $orgVdc -Name TestVapp
</pre>
<p>You will first see that VM, called TestVM2, is <strong>cloned</strong> in your vCenter, followed by an import of the clone into your Cloud. This import will display a progress bar.</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/import-civapp.png"><img class="alignnone  wp-image-3830" title="import-civapp" src="http://lucd.info/wp-content/uploads/2012/01/import-civapp.png" alt="" width="506" height="47" /></a></p>
<p>The VM will be part of the new Cloud vApp called <strong>TestVapp</strong>.</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/get-civapp2.png"><img class="alignnone  wp-image-3831" title="get-civapp2" src="http://lucd.info/wp-content/uploads/2012/01/get-civapp2.png" alt="" width="502" height="101" /></a></p>
<p>And the imported VM is in the new vApp called TestVapp.</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/get-civm2.png"><img class="alignnone  wp-image-3832" title="get-civm2" src="http://lucd.info/wp-content/uploads/2012/01/get-civm2.png" alt="" width="508" height="87" /></a></p>
<p>Adding additional VMs to this vApp is done this way.</p>
<pre class="brush: powershell; title: ; notranslate">

Get-VM -Name TestVM3 | Import-CIVApp -Name TestVapp
</pre>
<p>That&#8217;s all there is to it.</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/get-civm3.png"><img class="alignnone  wp-image-3833" title="get-civm3" src="http://lucd.info/wp-content/uploads/2012/01/get-civm3.png" alt="" width="506" height="97" /></a></p>
<p>Now what if you want to do something that is not (yet) covered by the Cloud snapin cmdlets ?</p>
<p>With the <strong>Get-CIView</strong> cmdlet and the <strong>ExtensionData</strong> property on the Cloud objects, you can have access to all the vCloud object properties and methods.</p>
<p>If you intend to use these vCloud .Net object, I advise to have the reference guide available. Download the <a href="http://communities.vmware.com/community/vmtn/developer/forums/vcloudsdk-net?view=overview" target="_blank">VMware vCloud SDK for .Net</a> file, extract the files from the ZIP archive and then open <strong>.\VMware-vCloudDirector-.NetSDK-1.5.0.2\Docs\ndoc3_msdn_temp\index.html</strong> from the folder where you unzipped the archive.</p>
<p>A quick sample, where we list the  methods accessible through the <strong>ExtensionData</strong> of a VM.</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/vm-methods.png"><img class="alignnone  wp-image-3835" title="vm-methods" src="http://lucd.info/wp-content/uploads/2012/01/vm-methods.png" alt="" width="504" height="395" /></a></p>
<p>The other way to get there is through the <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/Get-CIView.html" target="_blank">Get-CIView</a> cmdlet. This gives access to the same methods (and properties).</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/vm-methods2.png"><img class="alignnone  wp-image-3836" title="vm-methods2" src="http://lucd.info/wp-content/uploads/2012/01/vm-methods2.png" alt="" width="510" height="236" /></a></p>
<p>The access to these methods comes in handy when we need to perform some action that is not available through the cmdlets.</p>
<p>As an example, we want to <strong>delete</strong> the VM called TestVM3 from the TestVapp vApp. With the access to the vCD API this is now a piece of cake.</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/vm-delete.png"><img class="alignnone  wp-image-3837" title="vm-delete" src="http://lucd.info/wp-content/uploads/2012/01/vm-delete.png" alt="" width="515" height="116" /></a></p>
<p>That was my short tour of the Cloud snapin, but it only scratched the surface. There&#8217;s tons more of good stuff to be discovered.</p>
<p>Before I forget, make sure to <strong>select</strong> the Cloud snapin when you install/upgrade PowerCLI 5.0.1. By default the Cloud snapin is not installed !</p>
<p>Needless to say that there are <a href="http://www.vmware.com/support/developer/PowerCLI/changelog.html#PowerCLI501" target="_blank">other improvements</a> in <strong>PowerCLI 5.0.1</strong>. One that I will definitely have a closer look at is the new <strong>XML</strong> feature that is provided with the <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/Get-EsxCli.html" target="_blank">Get-EsxCli</a> cmdlet.</p>
<p>And btw, the mixup of the <strong>FreeSpaceGB</strong> and <strong>CapacityGB</strong> properties, both in the objects returned by the <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI501/html/Get-Datastore.html" target="_blank">Get-Datastore</a> cmdlet, is fixed <img src='http://lucd.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Enjoy PowerCLI 5.0.1 !</p>
<img src="http://feeds.feedburner.com/~r/LucdNotes/~4/MphI8FwmN-s" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lucd.info/2012/01/10/powercli-5-0-1-goes-cloud/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://www.lucd.info/2012/01/10/powercli-5-0-1-goes-cloud/</feedburner:origLink></item>
		<item>
		<title>Will Invoke-VMScript work ?</title>
		<link>http://feedproxy.google.com/~r/LucdNotes/~3/Z8P5vslUDXY/</link>
		<comments>http://www.lucd.info/2012/01/01/will-invoke-vmscript-work/#comments</comments>
		<pubDate>Sun, 01 Jan 2012 22:36:50 +0000</pubDate>
		<dc:creator>LucD</dc:creator>
				<category><![CDATA[PowerCLI]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Virtual Machine]]></category>
		<category><![CDATA[Invoke-VMScript]]></category>

		<guid isPermaLink="false">http://www.lucd.info/?p=3798</guid>
		<description><![CDATA[The Invoke-VMScript cmdlet can be a very useful cmdlet, but sometimes it will fail against one or more of your VMs. And it is not always immediately clear why the Invoke-VMScript cmdlet will not work against that specific VM. The cmdlet help contains a number of prerequisites, but how do you verify if all the [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI50/html/Invoke-VMScript.html" target="_blank">Invoke-VMScript</a> cmdlet can be a very useful cmdlet, but sometimes it will fail against one or more of your VMs. And it is not always immediately clear why the <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI50/html/Invoke-VMScript.html" target="_blank">Invoke-VMScript</a> cmdlet will not work against that specific VM.<br />
The cmdlet help contains a number of <strong>prerequisites</strong>, but how do you verify if all the prerequisites are fulfilled?<br />
I decided to create a function that would verify the prerequisites, and that would, if requested, which of the prerequisites was missing.</p>
<p><span id="more-3798"></span></p>
<span id="The_prerequisites"><h2>The prerequisites</h2></span>
<span id="Official"><h3>Official</h3></span>
<p>The official prerequisites are all documented in the help for the <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI50/html/Invoke-VMScript.html" target="_blank">Invoke-VMScript</a> cmdlet. The following table is a summary.</p>
<table style="width: 515px; height: 222px;" border="0" cellspacing="0" cellpadding="0">
<colgroup>
<col width="324" />
<col width="87" />
<col width="97" />
<col width="90" /> </colgroup>
<tbody>
<tr>
<td width="324" height="20">PowerCLI</td>
<td style="text-align: center;" width="87">4.1</td>
<td style="text-align: center;" width="97">4.1U1</td>
<td style="text-align: center;" width="90">5</td>
</tr>
<tr>
<td height="20">only 32-bit engine</td>
<td style="text-align: center;">x</td>
<td style="text-align: center;">x</td>
<td style="text-align: center;">x</td>
</tr>
<tr>
<td height="20">VMware Tools installed</td>
<td style="text-align: center;">x</td>
<td style="text-align: center;">x</td>
<td style="text-align: center;">x</td>
</tr>
<tr>
<td height="20">read access to VM folder</td>
<td style="text-align: center;">x</td>
<td style="text-align: center;">x</td>
<td style="text-align: center;">x</td>
</tr>
<tr>
<td height="20">Virtual Machine.Interaction.Console privilege</td>
<td style="text-align: center;">x</td>
<td style="text-align: center;">x</td>
<td style="text-align: center;">x</td>
</tr>
<tr>
<td height="20">VM powered on</td>
<td style="text-align: center;">x</td>
<td style="text-align: center;">x</td>
<td style="text-align: center;">x</td>
</tr>
<tr>
<td height="20">port 902 to ESX(i) hosting the VM</td>
<td style="text-align: center;">x</td>
<td style="text-align: center;">x</td>
<td style="text-align: center;">x</td>
</tr>
<tr>
<td height="20">VIX 1.6.2</td>
<td style="text-align: center;">x</td>
<td style="text-align: center;">x</td>
<td style="text-align: center;"></td>
</tr>
<tr>
<td height="20">VIX 1.10</td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;">x</td>
</tr>
<tr>
<td width="324" height="40">Windows XP, Windows 7, Windows 2003 Server, Windows 2008 Server,Redhat Enterprise 5</td>
<td style="text-align: center;">x</td>
<td style="text-align: center;">x</td>
<td style="text-align: center;">x</td>
</tr>
</tbody>
</table>
<span id="Unofficial"><h3>Unofficial</h3></span>
<p>From my own experience and from several posts in the <a href="http://communities.vmware.com/community/vmtn/server/vsphere/automationtools/powercli?view=discussions&amp;start=0" target="_blank">PowerCLI Community</a>, I have 2 additional prerequisites.</p>
<ul>
<li>The cmdlet seems to work most of the time when the guest OS is <strong>Windows 2008 R2</strong>. Note that there have been reports about errors with this OS. In the current PowerCLI build Windows 2008 R2 is <strong>not</strong> in the list of supported guest OS.</li>
<li>When you use the hostname in the Connect-VIServer cmdlet, the Invoke-VMScript doesn&#8217;t seem to work. When you do the Connect-VIServer with the <strong>FQDN</strong> or the <strong>IP address</strong>, the cmdlet works. The error message looks like this</li>
</ul>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/invoke-connect.png"><img class="alignnone  wp-image-3801" title="invoke-connect" src="http://lucd.info/wp-content/uploads/2012/01/invoke-connect.png" alt="" width="652" height="67" /></a></p>
<p>The list of my 2 non-official prerequisites</p>
<table style="width: 517px; height: 62px;" border="0" cellspacing="0" cellpadding="0">
<colgroup>
<col width="324" />
<col width="87" />
<col width="97" />
<col width="90" /> </colgroup>
<tbody>
<tr>
<td width="324" height="20">PowerCLI</td>
<td style="text-align: center;" width="87">4.1</td>
<td style="text-align: center;" width="97">4.1U1</td>
<td style="text-align: center;" width="90">5</td>
</tr>
<tr>
<td height="20">Windows 2008 R2 Server</td>
<td></td>
<td></td>
<td style="text-align: center;">x</td>
</tr>
<tr>
<td height="20">Connected with FQDN or IP</td>
<td style="text-align: center;">x</td>
<td style="text-align: center;">x</td>
<td style="text-align: center;">x</td>
</tr>
</tbody>
</table>
<span id="The_Script"><h2>The Script</h2></span>
<pre class="brush: powershell; title: ; notranslate">
function Test-InvokeVMScript{
&lt;#
.SYNOPSIS  Test if Invoke-VMScript will work
.DESCRIPTION The function verifies if all prerequisites
  are present to use the Invoke-VMScript cmdlet.
.NOTES  Author:  Luc Dekens
.PARAMETER VM
  The virtual machine for which you want to test the
  prerequisites. You can pass the name of the virtual
  machine or the VM object
.PARAMETER Official
  This switch specifies if only the official prerequistes
  should be verified or not. The default value is $True,
  so only the official prerequisites
.PARAMETER Detail
  Switch that specifies if all the prerequisite details
  should be returned or not. The default is $False
.EXAMPLE
  PS&gt; Test-InvokeVMScript -VM $vm -Detail
.EXAMPLE
  PS&gt; Get-VM VM* | Test-InvokeVMScript -Official:$false
#&gt;

  param(
  [CmdletBinding()]
  [parameter(Mandatory = $true, ValueFromPipeline = $true)]
  [PSObject]$VM,
  [switch]$Official = $True,
  [switch]$Detail
  )

  begin{
    $pCLIMajor,$pCLIMinor = Get-PowerCLIVersion | %{$_.Major,$_.Minor}
    $apiMajor,$apiMinor = (Get-View ServiceInstance).Content.About.ApiVersion.Split('.')
  }

  process{
    if($VM.GetType().Name -eq &quot;string&quot;){
      $VM = Get-VM -Name $VM
    }

    $condPoweredOn = $condCpu = $condTools = $condPort = $condRead = $condRole = $condOS = $False

    # Common prerequisites

    # Powered on
    if($vm.PowerState -eq &quot;PoweredOn&quot;){
      $condPoweredOn = $True
    }

    # 32-bit engine
    if ($env:Processor_Architecture -eq &quot;x86&quot;){
      $condCpu = $true
    }

    # Tools installed
    if($VM.Guest.State -eq &quot;Running&quot; -and $VM.ExtensionData.Summary.Guest.ToolsVersionStatus -eq &quot;guestToolsCurrent&quot;){
      $condTools = $True
    }

    # Port 902 open
    $originalEA = $ErrorActionPreference
    $ErrorActionPreference = “SilentlyContinue”
    $socket = New-Object Net.Sockets.TcpClient
    $socket.Connect($VM.Host.Name,902)
    if($socket.Connected){
      $condPort = $True
      $socket.Close()
    }
    Remove-Variable -Name socket -Confirm:$false
    $ErrorActionPreference = $originalEA

    # Folder read access
    $datastore,$file = $VM.ExtensionData.Config.Files.VmPathName.Split(']')
    $datastoreName = $datastore.Trim('[')
    $fileName = $file.Split('/')[1]
    $file = $file.TrimStart(' ')
    $ds = Get-Datastore -Name $datastoreName
    New-PSDrive -Location $ds -Name DS -PSProvider VimDatastore -Root '\' | Out-Null
    $currentProgPref = $ProgressPreference
    $ProgressPreference = 'SilentlyContinue'
    Copy-DatastoreItem -Item ('DS:\' + $file) -Destination $env:Temp -ErrorAction SilentlyContinue
    $ProgressPreference = $currentProgPref
    Remove-PSDrive -Name DS
    $path = $env:Temp + '\' + $fileName
    $condRead = Test-Path -Path $path
    if($condRead){
      Remove-Item -Path $path -Confirm:$false
    }

    # Privilege
    $authMgr = Get-View AuthorizationManager
    $role = $authMgr.RoleList | where {$vm.ExtensionData.EffectiveRole -eq $_.RoleId}
    $condRole = $role.Privilege -contains &quot;VirtualMachine.Interact.ConsoleInteract&quot;

    # Supported OS
    $supportedOS = &quot;winLonghornGuest&quot;,  # Windows 2008
    &quot;winLonghorn64Guest&quot;,               # Windows 2008 (64 bit)
    &quot;windows7Guest&quot;,                     # Windows 7
    &quot;windows7_64Guest&quot;,                 # Windows 7 (64 bit)
    &quot;windows7Server64Guest&quot;,            # Windows Server 2008 R2 (64 bit)
    &quot;winXPProGuest&quot;,                     # Windows XP Professional
    &quot;winXPPro64Guest&quot;,                   # Windows XP Professional Edition (64 bit)
    &quot;winXPHomeGuest&quot;,                   # Windows XP Home Edition
    &quot;rhel5Guest&quot;,                       # Red Hat Enterprise Linux 5
    &quot;rhel5_64Guest&quot;,                     # Red Hat Enterprise Linux 5 (64 bit)
    &quot;rhel6Guest&quot;,                       # Red Hat Enterprise Linux 6
    &quot;rhel6_64Guest&quot;                     # Red Hat Enterprise Linux 6 (64 bit)
    $guestId = $VM.ExtensionData.Summary.Guest.GuestId
    if($guestId -like &quot;winNet*&quot; -or $supportedOS -contains $guestId){
      $condOS = $true
    }

    # Version dependent prerequisites
    $propertiesVix =[System.Diagnostics.FileVersionInfo]::GetVersionInfo($env:programfiles + '\VMware\VMware VIX\VixCOM.dll')
    $majorVix = $propertiesVix.FileMajorPart
    $minorVix = $propertiesVix.FileMinorPart
    $buildVix = $propertiesVix.FileBuildPart
    $versionVix = ([string]$majorVix + '.' + [string]$minorVix + '.' + [string]$buildVix)

    if(($pCLIMajor -eq 5 -and $versionVix -eq '1.10.0') -or
    ($pCLIMajor -eq 4 -and $versionVix -eq '1.6.2')){
      $condVix = $true
    }

    # Unofficial conditions
    if(!$Official){
      $condFQDN_U = $condOS_U = $False

      # OS that seems to work (most of the time)
      if($guestId -like &quot;windows7Server64Guest&quot;){  # Windows Server 2008 R2 (64 bit)
        $condOS_U = $True
      }

      # Short name
      $condFQDN_U = $global:DefaultVIserver.Name.Contains('.')
    }

    # Result
    if($Official){
      $result = $condPoweredOn -and $condCpu -and $condTools -and
        $condPort -and $condRead -and $condRole -and $condOS
    }
    else{
      $result = $condPoweredOn -and $condCpu -and $condTools -and
        $condPort -and $condRead -and $condRole -and
        ($condOS -or $condOS_U) -and $condFQDN_U
    }

    $resultObj = New-Object PSObject -Property @{
      VM = $VM.Name
      OK = $result
    }
    if($Detail){
      $resultObj = $resultObj |
      Add-Member -Name PoweredOn -Value $condPoweredOn -MemberType NoteProperty -PassThru |
      Add-Member -Name X86Engine -Value $condCpu -MemberType NoteProperty -PassThru |
      Add-Member -Name ToolsInstalled -Value $condTools -MemberType NoteProperty -PassThru |
      Add-Member -Name Port902Open -Value $condPort -MemberType NoteProperty -PassThru |
      Add-Member -Name FolderReadAccess -Value $condRead -MemberType NoteProperty -PassThru |
      Add-Member -Name PrivilegeConsoleInteraction -Value $condRole -MemberType NoteProperty -PassThru |
      Add-Member -Name SupportedOS -Value $condOs -MemberType NoteProperty -PassThru
      if(!$Official){
        $resultObj = $resultObj |
        Add-Member -Name FQDNorIPConnection -Value $condFQDN_U -MemberType NoteProperty -PassThru
      }
    }
    $resultObj
  }
}
</pre>
<span id="Annotations"><h4>Annotations</h4></span>
<p><strong>Line 32-35</strong>: Retrieve some properties the script will use later.</p>
<p><strong>Line 38-40</strong>: My poor man&#8217;s Object By Name (OBN) implementation.</p>
<p><strong>Line 42</strong>: Set all prerequisites to $false</p>
<p><strong>Line 73-89</strong>: To test if the caller has read access to the VM folder, the script will copy the VMX file to local storage.</p>
<p><strong>Line 82</strong>: This is the major bottleneck in the function. The <a href="http://www.vmware.com/support/developer/PowerCLI/PowerCLI50/html/Copy-DatastoreItem.html" target="_blank">Copy-DatastoreItem</a> cmdlet is quite slow compared to the other PowerCLI cmdlets.</p>
<p><strong>Line 110</strong>: All Windows Server 2003 variations have a guestId that starts with &#8220;winNet&#8221;. See the <a href="http://pubs.vmware.com/vsphere-50/topic/com.vmware.wssdk.apiref.doc_50/vim.vm.GuestOsDescriptor.GuestOsIdentifier.html" target="_blank">VirtualMachineGuestOsIdentifier</a> enumeration.</p>
<p><strong>Line 131-133</strong>: Chekc if the guest OS is Windows 2009 R2. If you don&#8217;t want this test, just comment out these lines.</p>
<p><strong>Line 136</strong>: By testing if there any dots in the name, we can verify if it is a Fully Qualified Domain Name or an IP address.</p>
<span id="Sample_use"><h2>Sample use</h2></span>
<p>A very straightforward example</p>
<pre class="brush: powershell; title: ; notranslate">
$vm = Get-VM -Name MyVM
Test-InvokeVMScript -VM $vm
</pre>
<p>This will return a simple object, where the OK property will say if the prerequisites are met or not.</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/invoke-ex1.png"><img class="alignnone  wp-image-3802" title="invoke-ex1" src="http://lucd.info/wp-content/uploads/2012/01/invoke-ex1.png" alt="" width="387" height="53" /></a></p>
<p>If we want to know which of the prerequisites failed, we can do</p>
<pre class="brush: powershell; title: ; notranslate">
$vm = Get-VM -Name MyVM
Test-InvokeVMScript -VM $vm -Detail
</pre>
<p>From the output we can immediately see why the Invoke-VMScript cmdlet would fail.</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/invoke-ex2.png"><img class="alignnone  wp-image-3803" title="invoke-ex2" src="http://lucd.info/wp-content/uploads/2012/01/invoke-ex2.png" alt="" width="313" height="107" /></a></p>
<p>Looks like we are not running this in a 32-bit engine.</p>
<p>To also see my non-official prerequisites, we can do</p>
<pre class="brush: powershell; title: ; notranslate">
Get-VM MyVM2 | Test-InvokeVMScript -Official:$false -Detail
</pre>
<p>This produces the following</p>
<p><a href="http://lucd.info/wp-content/uploads/2012/01/invoke-ex3.png"><img class="alignnone  wp-image-3804" title="invoke-ex3" src="http://lucd.info/wp-content/uploads/2012/01/invoke-ex3.png" alt="" width="313" height="122" /></a></p>
<p>All the official prerequisites are fulfilled, but it looks as if our Connect-VIServer might have been done with a short hostname.</p>
<p>Let me know if you know of any other prerequisites, and I will add them to the function.</p>
<p>Enjoy the function.</p>
<img src="http://feeds.feedburner.com/~r/LucdNotes/~4/Z8P5vslUDXY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.lucd.info/2012/01/01/will-invoke-vmscript-work/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://www.lucd.info/2012/01/01/will-invoke-vmscript-work/</feedburner:origLink></item>
	</channel>
</rss>

