Monday 11 November 2013

How to automate Citrix XenServer PowerShell scripts

Using the XenServer PowerShell cmdlets, it's now easy to automate tasks in XenServer using PowerShell scripts.

This script is based on XenServer 6.2 PSSnapIn, but with few changes, you can adapt to previous version. Cmdlets have different names from previous version (for example, Get-XenServer:VM is now Get-XenVM...).

First, you need to download the XenServer SDK from Citrix website, and the install the XenServerPSSnapIn.

First thing you have to do before you can call any method is to load the PSSnapIn. The command to do it is:
Add-PSSnapIn XenServerPSSnapIn

If you use it in a script, you need to ensure that it's not throwing an error if it's already loaded and terminating your script, so we check before adding:
if ( (Get-PSSnapIn -Name "XenServerPSSnapIn" -ErrorAction SilentlyContinue) -eq $Null ) {Add-PSSnapIn XenServerPSSnapIn}

Then, you need to declare the XenServer host you're connecting to; you need to point at the poolmaster.

So, below you create an array in case you have several pools to look after:
[array]$xenserver_poolmaster = @("mypoolmaster1","mypoolmaster2","mypoolmaster3")

Next, we'll make a loop through the array (% stand for "foreach"):
# Loop through list of hosts (poolmaster)
$xenserver_poolmaster | % {
  ... do things ...
}

To connect, you need to authenticate. You could mention the password in clear text, but it's safer to use a stored encrypted password as described in the following post.

To connect to a XenServer host, we'll use the following command line:
Connect-XenServer -Server $_ -Creds $xenserver_credential -SetDefaultSession

Once connected, as an example, we'll retrieve the list of VMs:
Get-XenVM | ? {$_.is_a_snapshot -eq $false -and $_.is_a_template -eq $false -and $_.is_control_domain -eq $false -and $_.power_state -eq 'running'} | Select-Object name_label

Then, we'll disconnect from the pool:
Get-XenSession -Server $_ | Disconnect-XenServer

So, see below the complete script:
[array]$xenserver_poolmaster = @("poolmaster1","poolmaster2")
[string]$xenserver_username = "root"
[string]$xenserver_credential_path = "c:\temp\xenserver_pool.pwd"

# If Password file does not exist, create it
if ((Test-Path -Path $xenserver_credential_path) -eq $False) {
    (Get-Credential).Password | ConvertFrom-SecureString | Out-File $xenserver_credential_path
}

# Read the password
$xenserver_password = cat $xenserver_credential_path | ConvertTo-SecureString

# Create the PSCredential Object
$xenserver_credential = New-Object -Typename System.Management.Automation.PSCredential -ArgumentList $xenserver_username, $xenserver_password

# Import the XenServer PSSnapIn
if ( (Get-PSSnapIn -Name "XenServerPSSnapIn" -ErrorAction SilentlyContinue) -eq $Null ) {Add-PSSnapIn XenServerPSSnapIn}

# Loop through list of hosts (poolmaster)
$xenserver_poolmaster | % {

  # Connect to XenServer pool
  Connect-XenServer -Server $_ -Creds $xenserver_credential -SetDefaultSession

  # Retrieve the information
  Get-XenVM | ? {$_.is_a_snapshot -eq $false -and $_.is_a_template -eq $false -and $_.is_control_domain -eq $false -and $_.power_state -eq 'running'} | Select-Object name_label

  # Disconnect from the XenServer pool
  Get-XenSession -Server $_ | Disconnect-XenServer

}

3 comments:

  1. has anybody had success with connecting to multiple pools and gathering properties? I've tried above with no success. It always connects to just the last pool and not any before that pool??

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. I'm sure that this is due to the fact how your loop is getting constructed. If you serve your objects properly, you should be able to get the values which you are interested with, instead of them being overwritten with lat entry in your loop.

    ReplyDelete