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


(shutdownScript.ps1)




(StartupScript.ps1)




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:



(ImportCred.ps1)


The updated script


(Set-LabPowerState.ps1)




The Shell Thing



12-script-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:


(TheScriptThing.ps1)



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.

Cheers

Tore

Comments

Popular posts from this blog

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:
Export-CliXmlConvertTo-JSON
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:


(Hashdata.Object.ps1)

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 …

Build your local powershell module repository - ProGet

So Windows Powershell Blog released a blog a couple of days ago (link). Not too long after, a discussion emerged about it being to complicated to setup. Even though the required software is open source (nugetgalleryserver), it looks like you need to have Visual Studio Installed to compile it. I looked into doing it without visual stuidio, however I have been unable to come up with a solution. I even tweeted about it since I am not an developer. Maybe someone how is familiar with “msbuild” could do a post on how to do it without VS.

Anyhow one of my twitter-friends (@sstranger) came to the rescue and pointed me in the direction of ProGet, hence the title of this post. ProGet comes in 2 different licensing modes
Free (reduced functionality)Enterprise (paid version with extra features)The good news is that the free version supports hosting a local PowershellGet repository which was my intention anyway. So off we go and create a Configration that can install ProGet for us. This is the conf…

Monitoring Orchestrator runbook events from Operations Manager

Today I will follow up on my colleague’s post Mr ITblog (Knut Huglen) about monitoring Orchestrator Runbook events.  He has build a nice double up SNMP loopback feature that does self monitoring in Orchestrator resulting in entries written to a special Windows Eventlog. Now we need to raise alerts in SCOM when one of his runbooks fails or sends a platform event, who knows there could be trouble lurking in his paradise.

We are not going to do anything fancy, however these are the steps we will be focusing on today:
Create a Management Pack for our customizations Create rules that collects the events from the orchestrator serverOff we go then and fire up the SCOM console and a powershell window. First we create a MP, I am going to use powershell to do this, however you may use the SCOM console as well (Administration – ManagementPacks – Action: Create Management Pack):



Import the Management Pack into SCOM and move on to the Authoring section in the SCOM console. Create a new rule:



Give the…