Saturday, 5. December 2009 19:55
Welcome to the second part of my series of blog posts dealing with the PowerShell SnapIn called McliPSSnapIn that Citrix provides as an programming interface for the Citrix Provisioning Services (PVS).
The first part only covered the installation/registration of the SnapIn and furthermore it introduced a function called Test-PSSnapIn to add the SnapIn to the current PowerShell session (respectively to test if it could added successfully).
This time I want to point out more clearly how the McliPSSnapIn’s cmdlets vary from PowerShell standard. It’s just that the SnapIn has its own standard after all. A general approach to test if a given PVS object exists (like a vDisk, Device, or Collection) will top off part II.
McliPSSnapIn Standards
As mentioned in the prologue of part I, the cmdlets of McliPSSnapIn are not 100% PowerShell-compliant meaning that…
- the cmdlet names don’t meet PowerShell’s “Verb-Noun” naming schema,
- the cmdlet’s syntax doesn’t match with PowerShell’s standards, and
- the cmdlets don’t return objects but arrays of pure text elements.
Instead, the McliPSSnapIn introduces its own standards – anything is better than nothing.
Cmdlet Naming
Overall there are only nine cmdlets or “command types” (Citrix-terminology):
Mcli-Add, Mcli-Delete, Mcli-Get, Mcli-Help, Mcli-Info, Mcli-Run, Mcli-RunWithReturn, Mcli-Set, and Mcli-SetList
You see, the cmdlet naming doesn’t follow PowerShell’s “Verb-Noun” principle but rather its own standard that is “Mcli-Verb” or “Mcli-Action” (according Citrix-terminology). Ah, did I already mention that Mcli stands for Management Command Line Interface?
Cmdlet Syntax
No worries! I won’t write down a boring command reference now. If you need a reference look at Citrix’ PVS Programmer’s Guide, and there’s the Mcli-Help cmdlet by the way. This section just outlines the things in common concerning the syntax of all Mcli cmdlets.
Mcli-Help left out, the general syntax may be summarized as follows:
Mcli-<Action> <ObjectType> <Arguments>
Basically, in terms of PowerShell standard you can take “Action” for “Verb” and “ObjectType” for “Noun” – not so bad after all.
Actions
Besides “Help” there are eight Actions:
| Mcli-Add |
Add an object and return the object’s unique Id |
| Mcli-Delete |
Remove an object |
| Mcli-Get |
Get one or more objects and return according information as array of strings |
| Mcli-Info |
Get information about objects and return them as array of strings |
| Mcli-Run |
Run an action without return value |
| Mcli-RunWithReturn |
Run an action and return information as array of strings. |
| Mcli-Set |
Set property values for one or more objects without return value |
| Mcli-SetList |
Set a list of property values for an object without return value |
ObjectTypes
Depending on the action there are more or less object types. To name but the most common only:
Collection, Device, DiskLocator, Server, Site, and Store
But as said before there are many more.
Arguments
There are four types of arguments indicated by “-f”, “-r”, “-p”, and “-s”:
| -f |
Indicates a field (object property name) or a list of fields, separated by comma, to be returned. |
| -p |
Indicates a single or a comma-separated list of name=value pair parameters to identify an object. |
| -r |
Indicates a single or a comma-separated list of name=value pair records to be set on an object. |
| -s |
Indicates a field to sort on. |
Syntax Examples
Some examples dealing with the Device object will certainly help to to clarify so much theory:
# Set the className to "Collection Class" in all of the Device objects of the Site
Mcli-Set Device -p collectionName=Collection, siteName=Site -r className="Collection Class"
# Add a Device
Mcli-Add Device -r deviceName=Device1, deviceMac=1a-2b-3c-4d-5e-6f, description="A description"
# And delete the Device
Mcli-Delete Device -p deviceName=Device1
# Get all Devices in the System you have access to
Mcli-Get Device
# Get a list of Devices in the Collection of Site. The only fields that will be returned
# are deviceName and description and the sort order will be deviceName decending.
# It is decending because of the - appended to the -s deviceName
Mcli-Get Device -p collectionName=Collection, siteName=Site -f deviceName,
description -s deviceName-
# Reboot all of the devices in the Collection of the Site
Mcli-Run Reboot -p collectionName=Collection, siteName=Site
# Return the count of Devices in the Collection of the Site
Mcli-Run DeviceCount -p collectionName=Collection, siteName=Site
# Return the count of Devices in the Collection of the Site
mcli-Run DeviceCount -p collectionName=Collection, siteName=Site
These samples are taken from the PVS Programmer’s Guide. I don’t know if they really work but it is good enough to show how the Mcli cmdlet syntax concept differs from PowerShell standards.
Cmdlet Return Values
The real annoyance about the Mcli SnapIn is the fact that their cmdlets return simple text, more precisely: arrays of strings. Practically the return values don’t differ from the return values of an external console utility like ipconfig.exe.
For example, it is well established that PowerShell’s most awesome feature is the Object Pipeline and it is a pity that you can’t use this extremely resourceful feature with the Mcli cmdlets. (Well, you can use the Object Pipeline in order to apply it to the string objects the cmdlets return though.)
Consequently, you need to inspect returning data using string operation methods like Substring() or Trim(). And PowerShell wouldn’t be PowerShell without its great Regular Expression support that helps tokenize strings to identify requested data (which is an easy task once you have played with regular expressions and understand how they’re working).
If you’re willing to put more effort in development time you can write your own PowerShell function library to encapsulate the Mcli cmdlet’s functionality completely and create your “homebrew” Collection, Device, Store, and Site objects with scripted methods. Maybe – it depends on your comments, folks! – I will provide some examples how to create your own object in a future part of this series about the PVS’ PowerShell SnapIn.
Hey, wake up! We’re back in example mode.
The cmdlet Mcli-Add returns a unique Id of the object added. Look at this example output:
PS C:\> $rv = Mcli-Add Device -r siteName=Site, collectionName=Collection, deviceName=Device1, deviceMac=1a-2b-3c-4d-5e-6f
PS C:\> $rv
Executing: Add Device
Add succeeded. resultId = 27ce63d7-c469-42ed-b828-82bad1d3c616
PS C:\>
So, besides the interesting data (meaning the Add succeeded and the resultId) there’s virtually gross information. Now, let’s inspect the return value stored in the $rv variable….
PS C:\> $rv.Count
3
PS C:\> $rv[0]
PS C:\> $rv[1]
Executing: Add Device
PS C:\> $rv[2]
Add succeeded. resultId = 27cd63d7-c469-24ed-b828-82bad1d3c616
PS C:\>
You see, Mcli-Add didn’t return a Device object with all its properties and methods. Actually, it returned an array of three strings (the first is empty). Therefore, if you want to process the new Device – let’s say you need to set a property value (Citrix-terminology: record value) – you can’t just do it the way you might expect by typing this:
PS C:\> # Does not work!
PS C:\> $rv.description = "A description"
Property 'description' cannot be found on this object; make sure it exists and is settable.
At line:1 char:5
+ $rv.d <<<< escription = "A description"
PS C:\>
No, instead you need to fire up another cmdlet, Mcli-Set, to apply the desired property value:
PS C:\> Mcli-Set Device -p deviceName=Device1 -r description="A description"
Executing: Set Device
Set succeeded.
PS C:\>
So far, so good. The cmdlets work, but hopefully you’re getting the picture now why I consider the concept how Mcli works annoying. It’s not that ingenious PowerShell way, it’s just old school (meaning text based) scripting.
Test Object Existence
In this chapter I want to share a set of functions that test for existence of a given object, let’s say a Device.
For example the function PVS\Test-Device returns either “True” or “False” depending on the text information returned by Mcli-RunWithReturn. Let’s take a look at the function first:
function PVS\Test-Device ($Name)
{
(Mcli-RunWithReturn Exists -p deviceName=$Name)[2] -match 1
}
Actually, the function returns “True” or “False” based on a regular expression comparison applied to the third line of Mcli-RunWithReturn’s text output. What matters is that the text of the third line matches the character “1”, meaning if there’s no “1” the given Device name doesn’t exist. Let’s have a look at the Mcli-RunWithReturn’s complete output:
PS C:\> #Test with an existing Device name
PS C:\> Mcli-RunWithReturn Exists -p deviceName=Device1
Executing: RunWithReturn Exists
RunWithReturn succeeded. returnValue = 1
PS C:\> #Test with an non-existin Device name
PS C:\> Mcli-RunWithReturn Exists -p deviceName=Device2
Executing: RunWithReturn Exists
RunWithReturn succeeded. returnValue = 0
PS C:\>
You see, Mcli-RunWithReturn’s output differs only at the position where the cmdlet displays the return value. To prove that the function is working:
PS C:\> function PVS\Test-Device ($Name) {
>> (Mcli-RunWithReturn Exists -p deviceName=$Name)[2] -match 1
>> }
>>
PS C:\> #Test with an existing Device name
PS C:\> pvs\test-device Device1
True
PS C:\> #Test with a non-existing Device name
PS C:\> pvs\test-device Device2
False
PS C:\>
Taking the PVS\Test-Device function as a reference it is easy to build more functions to test for example the existence of a Site, Store, or Disk:
function PVS\Test-Site ($Name)
{
(Mcli-RunWithReturn Exists -p siteName=$Name)[2] -match 1
}
function PVS\Test-Store ($Name)
{
(Mcli-RunWithReturn Exists -p storeName=$Name)[2] -match 1
}
function PVS\Test-Disk ($Name, $SiteName, $StoreName)
{
(Mcli-RunWithReturn Exists -p diskLocatorName=$Name, siteName=$SiteName, storeName=$StoreName)[2] -match 1
}
The PVS\Test-Disk function needs some more parameters due to the fact that Mcli-RunWithReturn needs also the name of the Site and the Store to determine if a given Device name there exists.
You’ve reached the end of part II. Next part I will dive deeper into scripting tasks finally. So stay tuned and don’t miss the chance to write comments meanwhile…