Skip to main content

Giving a helping hand - Community power

PowerShell is getting increasing attention and gaining followers each day. That is a good thing in my book. I saw a tweet about Citrix OctoBlu automation where Dave Brett (@dbretty) was using it to save money with a PowerShell script (full post here) to power on and off VMs. I reached out to him and asked if he would like a little help with his PowerShell script. To my delight, he happily accepted and this post is about how I transformed his scripts to take advantage of the full power of The Shell. Fair warning is in order, since I have never used or touched a OctoBlu solution.

Starting scripts



What we would like to change

First of, a PowerShell function should do one thing and do it well. My first goal was to split the function into two parts where we have one function that handles both the startup and the shutdown of the VM-guests. Secondly I would like to move the mail notification out of the function and either put it in a separate function or use the built in cmdlet Send-MailMessage which has been available since PowerShell version 3.0. Nothing wrong with using the .net class, however I like to use cmdlets if they provide similar functionality.

Secondly I changed the function to an advanced function to leverage WhatIf and all the streams (debug, verbose, information etc). I also added some Write-Verbose statements. The difference between a regular function and an advanced function can be as simple as adding [cmdletbinding()] to your function. If you do, you have to use a Param() section to define your parameters.

Third I added parameters to the function. From the scripts I decided to create the following parameters:

  • Credential as [PScredential]
  • XenServerUrl as [string]
  • VMname as [string[]]
  • Shutdown as [switch]

Forth I added Begin, Process and End blocks to enable PipeLineInput for the VMname parameter. Also to take advantage of configuring the requirements like Import-Module and Connect-XenServer in the Begin-block.

Fifth I added an output object to the function in which I output the VMname and the action taken with the VM (startup or shutdown). The reason for that becomes clear when we start to setup notification.

Those are the 5 big changes I have made to the initial scripts. Other than that I added some personal features related to the use of Write-Verbose and other minor stuff.

How to handle credentials

Every time you add a parameter to your function called username or password you should stop and think. You should most likely use a PScredential object instead. So how do you access those credentials at runtime? This script needs credentials and you cannot prompt the OctoBlu automation engine to provide those. Perhaps OctoBlu have a credential store, however I do not know. 

An secure and easy solution to this problem is to use the DAPI built-in encrypting API. The same logic can be applied to any service or service automation solutio that need specific credentials to execute your scripts included scheduled tasks. We will leverage tree cmdlets to accomplish this:

  • Get-Credential
  • Export-CliXml
  • Import-CliXml

First you need to start a PowerShell host as the user that need to use your credentials. Then we need to run these commands:

This will create a PScredential object and the Export-CliXml will protect the password with DAPI when you create the XenCred.xml file. That file can only be decrypted with Import-CliXml running under the account it was created with. So when you need to access those credentials you run:


The updated script


The Shell Thing


(Screenshot of OctoBlu, image by Dave Brett)

Dave Brett uses the profiles.ps1 script to make functions available in OctoBlu. That is fine, however it makes it hard for people that don’t know PowerShell to figure out where the function (Lab-Shutdown) comes from. I would suggest to add something like this in the script box:


This is just a suggestion which in my opinion makes it easier to follow what is happening. Since the Set-LabPowerState and the parameter VMName takes an array of strings, we could take the content of the file holding the names of the VMs and use that. I decided to use a foreach loop for readability reasons. 

I probably need to say something about a technique called splatting in PowerShell. Have a look at this line:

Set-LabPowerState @setLabPower -VMname $vm

A few lines up, you can see I create a variable $SetLabPower which is a hashtable. The keys in the hashtable match the name of the parameters of the function Set-LabPowerState. This makes it easier to read when you call functions or cmdlets that have many parameters. We can then provide those keyvalue-pairs to the function using a @ in front of the variable name.

The other thing to note is that I am using dotsourcing to make the Set-LabPowerState function available in the Script Thing session. I am assuming that the content of my new function is saved in the c:\scripts\Set-LabPowerState.ps1 file. 

Since my function outputs an object for each VM it processes, we can leverage that in the email notification setting and provide feedback on the VMs we have messed with. The output for the foreach loop is saved in the $results object. We convert this object to a string representation with the Out-String cmdlet and use that string object as the body of the email.

A note about ErrorAction

Since this script needs access to the XenServerPSModule module and you need to connect to an XenServer, I am using ErrorAction Stop on the Import-Module and the Connect-XenServer statements. This will prevent the script to continue if both prerequisites are not met. In addition the user is presented with a nice message explaining what the issue is.

Benefits of the new script

  1. We have a function that does a single task even if it can start and shutdown VMs.
  2. The functions accepts parameters so we can reuse it later
  3. The function is discoverable by the PowerShell help engine since we have added help in the function
  4. The automation task in OctoBlu is easier to understand. Think of the next guy
  5. We can execute the function without actually making changes since it is an advanced function and we have implemented ShouldProcess (WhatIf)
  6. The function outputs an object which we can reuse in the email notification scenario

So the only thing that is needed is someone to test my improved solution on an OctoBlu server. I have no idea if it works or if you think this is a better solution. I think it is.




Popular posts from this blog

Developing PowerShell modules for REST APIs – Part1

Over the years I have developed different PowerShell modules for different web APIs. I thought it would be a good idea to write a 2 series post about how you could go about to do this. This will be a 2 part blog series where we will run through the entire process of building a module for a REST API. I will try my best to keep this as simple as possible and leave more advanced stuff for a follow up post if the interest is there.What you needDepending on your experience with source control and PowerShell in general, you might want to use GIT or some other software repro for the code. In addition we are going to create a test REST API using the splendid UniversalDashboard PowerShell module created by Adam Driscoll. It is available on the PowershellGallery. Other prerequisites are built-in to Powershell. I will assume that you will be following along using at least PowerShell version 5 or greater.
What is HTTP metods for REST API.The primary or most common HTTP verbs used are POST, GET, PU…

Serialize data with PowerShell

Currently I am working on a big new module. In this module, I need to persist data to disk and reprocess them at some point even if the module/PowerShell session was closed. I needed to serialize objects and save them to disk. It needed to be very efficient to be able to support a high volume of objects. Hence I decided to turn this serializer into a module called HashData.

Other Serializing methods

In PowerShell we have several possibilities to serialize objects. There are two cmdlets you can use which are built in:
Both are excellent options if you do not care about the size of the file. In my case I needed something lean and mean in terms of the size on disk for the serialized object. Lets do some tests to compare the different types:


You might be curious why I do not use the Export-CliXML cmdlet and just use the [System.Management.Automation.PSSerializer]::Serialize static method. The static method will generate the same xml, however we …

Developing PowerShell modules for REST APIs – Part2

This is part 2 of the REST API blogpost. In part1 we successfully setup two REST API endpoints using the UniversalDashboard PowerShell module. In this part we are going to create a simple module that support some CRUD operation against our API. As we are trying to keep things as simple as possible, we will not use any fancy framework (like Plaster) to build our module. We are also going to skip a very important step you should familiarize yourself with, Pester tests. Lets get to it.

The moduleWe will build a module called FilesAPI. The module folder will look like this:

In the functions folder I have already added the 2 helper functions from part 1, Get-AuthorizationHeader and ConvertTo-Base64. The other folders are just placeholders for important stuff like classes, private functions that you do not want to make available for the module consumer and tests for Pester tests. For such a small module that we are going to create, one could argue that it is much easier to just add the functi…