• View Communities
    • Citrix Developer Network
      The place for unfiltered straight talk on Citrix products. Blogs, code downloads, best practices, APIs, and more can all be found here.
    • Citrix Ready Community Verified
      Does it work with Citrix? Application compatibility questions are a thing of the past with the new Citrix Community Verified site.
    • Blogs
      Learn the latest from the Citrix employees who are building application delivery infrastructure technologies.
    • Blogosphere
      The Citrix Blogosphere is a window into the thousands of conversations taking place about Citrix and Application Delivery.
  •  Sign In
The Citrix Blog
Personal Blog
Ewan Mellor
Related Tags
posted by Ewan Mellor

Introduction


In this article I shall demonstrate the new XenServer PowerShell snap-in, using the simple example of "chained" VM starts: waiting for one VM to finish booting before starting the next.

The new SnapIn is available at http://community.citrix.com/cdn/xs/sdks.

In this example, we are using the XenServer Tools to detect when booting is complete: once they advertise the VM's IP address, we assume that the VM is ready. Of course, you may want to make this more sophisticated, for example waiting for a domain controller to start before moving on. I'll leave this to your imagination!

In the first screenshot, I've got XenCenter 5.0 talking to a XenServer 5.0 pool, XS-PS started afresh, and the script that runs this example, Start-VM.Wait.ps1. The PowerShell install is out-of-the-box, though I've already set the ExecutionPolicy to RemoteSigned.



Namespaces and Initialize-XenServer:Aliases


Firstly, a quick word about how we handle namespaces in XS-PS.

A lot of the Xen-API's names are very generic; a cmdlet called "Create-Message" could clash with any number of things. With this in mind, XenServer's cmdlets are named within a XenServer namespace, something like this:

Create-XenServer:VM
Destroy-XenServer:VM
Get-XenServer:VM
Get-XenServer:VM.NameLabel
Set-XenServer:VM.NameLabel
Invoke-XenServer:VM.Start

This is great for people who want to use XS-PS in a mixed environment, but it's obviously a bit verbose for quick scripting, so we've added the ability to alias these full names to something shorter. In Start-VM.Wait's process block, you can see the following call:

Initialize-XenServer:Aliases Start

This introduces a full set of aliases, so that we can now use names such as

Create-VM
Destroy-VM
Get-VM
Get-VM.NameLabel
Set-VM.NameLabel
Start-VM

These aliases are scoped within this script, so they won't pollute the user's environment. If you want, you can pass it a -Scope parameter, and have them put into an outer or global scope instead.

Initialize-XenServer:Aliases actually supports three styles of alias, so you can choose the style that best suits your environment, or you can stick with the full names if you prefer.

PS C:\Users\Ewan Mellor> Initialize-XenServer:Aliases
Invoke-Xen = Get-Xen:VM / Invoke-Xen:VM.Start
Invoke     = Get-VM / Invoke-VM.Start
Start      = Get-VM / Start-VM



Start-VM.Wait


Start-VM.Wait takes its VMs from the pipeline. It then processes them one at a time, like this:

  • If the VM record represents the control domain, or a template, then silently skip it.
  • If the VM is unstartable (because it's already running, say), then log the fact, and skip it.
  • Otherwise, call Start-VM. This will block until the VM boot process begins.
  • Next, wait for up to five minutes for the VM to boot. We wait for the VM.guest_metrics field to be populated, and for an entry to appear in VM_guest_metrics.networks. Once there's an entry here, we know that the XenServer Tools are ready, and the VM has an IP address configured (from DHCP, for example).
  • If polling this field fails after 5 minutes, then warn, and just move on to the next VM.


function Start-VM.Wait
{
    begin
    {
        $timeout = 5 * 60 * 1000
        Initialize-XenServer:Aliases Start
    }
    process
    {
        if ($_.is_a_template -or $_.is_control_domain)
        {
            return
        }
        if ($_.allowed_operations -notcontains "start")
        {
            Write-Warning("{0} cannot be started" -f $_.name_label)
            return
        }

        Write-Verbose("Starting {0}..." -f $_.name_label)
        Start-VM $_

        for ($count = 0; $count -le $timeout / 500; $count += 1)
        {
            $metrics = Get-VM.GuestMetrics $_
            if ($metrics -ne $null -and $metrics.networks.Count -gt 0)
            {
                Write-Verbose("VM {0} started" -f $_.name_label)
                return
            }
            Start-Sleep -m 500
        }

        Write-Warning("Timeout starting {0}" -f $_.name_label)
   }
}



Using it


Using this script is now very simple:

  1. Dot-source the script, to load the function.
  2. Set $VerbosePreference to "Continue", just for this demo.
  3. Connect to your master server.
  4. Choose the VM's that you want to start (in the example, all those tagged as "Production").
  5. Pipe those VM's into Start-VM.Wait.
  6. Watch the magic!
  7. Log out from your server afterwards.
PS> . .\Start-VM.Wait.ps1
PS> $VerbosePreference = "Continue"
PS> Connect-XenServer -url https://<servername>
PS> Get-XenServer:VM -Tags Production | Start-VM.Wait
...
PS> Disconnect-XenServer

This is a simple example, and no doubt you would want to tweak it to match your deployment, but I hope that it's enough of an example for you to get started.

Downloads


Start-VM.Wait.ps1

Labels

xenserver xenserver Delete
xenserver xenserver Delete
powershell powershell Delete
xenserverpssnapin xenserverpssnapin Delete
xs-ps xs-ps Delete
lang-eng lang-eng Delete
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Oct 13, 2008

    John Crawford says:

    Ewan I currently have a .cmd script (I am a glutton for punishment) that reads ...

    Ewan

    I currently have a .cmd script (I am a glutton for punishment) that reads a list of VMs from a file, and for each of those VMs:-

    1.       Run a few checks (e.g. is there a Template/Snapshot with a similar name to the VM)

    2.       Close the VM

    3.       Destroy the VM

    It then re-reads the file and for each of the VMs:-

    1.       Recreate the VM from the similarly named Template/Snapshot

    2.       Start the VM

    3.        Wait for a period of time before starting the next VM

    What I would like to do now is to re-implement my .cmd script as a PowerShell script, and your Start-VM.Wait example looks like a useful starting point. I particularly like the idea of driving the script with Tag information from XenServer.

    However, something that gets lost with your approach is the order in which the VMs should be started. Currently my file contains a list of VMs with the router VM in position 1, followed by the AD domain controller VM, and then other servers and workstation VMs, whereas the Tag approach would present them in some other order.

     I was thinking that "Custom Fields" be a way of controlling this? If I were to create a "Custom Field" called StartOrder then I might be able sort my VMs on that. Unfortunately, I don't seem to be clever enough to extract/use "Custom Field/StartOrder"  in the Get-XenServer:VM line. Can you suggest how I could do this, or am I barking up the wrong end of the stick?

    John (PowerShell novice)

    1. Oct 13, 2008

      Ewan Mellor says:

      Good question John! XenCenter stores the custom field values in the VM.other_co...

      Good question John!

      XenCenter stores the custom field values in the VM.other_config dictionary, using the key XenCenter.CustomFields.Name_of_field.

      You can certainly sort on these values with PowerShell – here's an example, using "Sort Order" as the custom field's column header:

      PS> $SO = "XenCenter.CustomFields.Sort Order"
      PS> Get-XenServer:VM |
      >>>   where { $_.other_config.ContainsKey($SO) } |
      >>>   sort @{ expression={ [int]$_.other_config[$SO] } }
      >>>
  2. Jan 26, 2009

    Anonymous says:

    Where does one get the ps-snapin from? is this on the install cd?

    Where does one get the ps-snapin from? is this on the install cd?

    1. Jan 26, 2009

      Ewan Mellor says:

      It's available at http://community.citrix.com/cdn/xs/sdks; I've updated the text...

      It's available at http://community.citrix.com/cdn/xs/sdks; I've updated the text above to reflect this. This is now the homepage for all the XenServer SDKs, so check back later for updates.

  3. Mar 15, 2009

    Anonymous says:

    PowerShell integration into the IT world was meant to make our job simple. ...

    PowerShell integration into the IT world was meant to make our job simple.  Now, we know how powerful this .NET scripting technology is, then we seen people getting away from the simple Verb-Noun concept.  Maybe not knowing is not the right direction.

     Why creating a pssnapin with cmdlets such as:

    Create-XenServer:VM

    Get-XenServer:VM 

    Get-XenServer:VM.NameLabel

    Set-XenServer:VM.NameLabel

    Invoke-XenServer:VM.Start 
    Instead of  using Verb-Noun -Parameter

    Create-XenServer  -VM

    Destroy-XenServer -VM

    Get-XenServer   -VM   -Namelabel

    Invoke-XenServer  -VM  -Start 
    You are getting out of the standard PowerShell structure and add complexity to it.  It has to be kept simple enough or people are going to get intimidated by it.

  4. Mar 15, 2009

    Maximo Trinidad says:

    PowerShell integration into the IT world was meant to make our job simple. ...

    PowerShell integration into the IT world was meant to make our job simple.  Now, we know how powerful this .NET scripting technology is, then we seen people getting away from the simple Verb-Noun concept.  Maybe not knowing is not the right direction.

     Why creating a pssnapin with cmdlets such as:

    Create-XenServer:VM

    Get-XenServer:VM 

    Get-XenServer:VM.NameLabel

    Set-XenServer:VM.NameLabel

    Invoke-XenServer:VM.Start 

    Instead of  using Verb-Noun -Parameter

    Create-XenServer  -VM

    Destroy-XenServer -VM

    Get-XenServer   -VM   -Namelabel

    Invoke-XenServer  -VM  -Start

    You are getting out of the standard PowerShell structure and add complexity to it.  It has to be kept simple enough or people are going to get intimidated by it.

    1. Mar 16, 2009

      Ewan Mellor says:

      Take a look at the Initialize-XenServer:Aliases section. If you use that, you c...

      Take a look at the Initialize-XenServer:Aliases section. If you use that, you can have names like

      Create-VM
      Destroy-VM
      Get-VM
      Start-VM

      The long names (with XenServer: ) are really only intended for people who have to deal with multiple hypervisors (VMware's names would clash with ours, for example).

Add Comment