ODATA uses the Open Data Protocol (ODATA) to expose and consume data over the Web or Intranet.
It is primarily designed to expose resources manipulated by PowerShell cmdlets and scripts as
schematized ODATA entities using the semantics of representational state transfer (REST).
The philosophy of REST ODATA limits the verbs that can be supported on resources to only the basic
operations: Create, Read, Update and Delete.
In this topic I will talk about Management ODATA being able to expose resources that model PowerShell
pipelines that return unstructured data. This is an optional feature and is called “PowerShell
pipeline invocation” or “Invoke”. A single Management ODATA endpoint can expose schematized resources,
or the arbitrary cmdlet resources or both.
In this blog I will show how to write a windows client built on WCF client to create a PowerShell pipeline invocation.
Any client can be used that supports ODATA. WCF Data Services includes a set of client libraries
for general .NET Framework client applications that is used in this example.
You can read more about WCF at: http://msdn.microsoft.com/en-us/library/cc668792.aspx.
If you are building a WCF client, the only requirement is to use WCF Data Services 5.0 libraries
to be compatible. In this topic I will assume you already have a MODATA endpoint configured
and up and running. For more information on MODATA in general and how to create an endpoint
please refer to msdn documentation at http://msdn.microsoft.com/en-us/library/windows/desktop/hh880865(v=vs.85).aspx
Since “Invoke” feature is an optional feature and is disabled by default, you will need to enable it by
adding the following configuration to your MODATA endpoint web.config:
<commandInvocation enabled="true"/> |
Table 1.1 – Enable Command Invocation
To make sure “Invoke” is enabled, you will need to send a GET http://endpoint_service_URI/$metadata
query to MODATA endpoint and should see a similar response in return:
<Schema> |
Table 1.2 - Command Invocation Schema Definition
Management ODATA defines two ODATA resource sets related to PowerShell pipeline execution: CommandDescriptions and
CommandInvocations. The CommandDescriptions resource set represents the collection of commands available on the server.
By enumerating the resource set, a client can discover the commands that it is allowed to execute and their parameters.
The client must be authorized to execute Get-Command cmdlet for the CommandDescriptions query to succeed.
At a high level, if a client sends the following request:
Table 1.3 – Command Invocation Query Sample
…then the server might reply with the following information:
<entry> |
Table 1.4 – Command Response Sample
This indicates that the client is allowed to execute the Get-Process command.
The CommandInvocations resource set represents the collection of commands or pipelines
that have been invoked on the server. Each entity in the collection represents a single
invocation of some pipeline. To invoke a pipeline, the client sends a POST request containing
a new entity. The contents of the entity include the PowerShell pipeline itself (as a string),
the desired output format (typically “xml” or “json”), and the length of time to wait
synchronously for the command to complete. A pipeline string is a sequence of one or
more commands, optionally with parameters and delimited by a vertical bar character.
For example, if the server receives the pipeline string “Get-Process –Name iexplore”,
with output type specified as “xml” then it will execute the Get-Process command
(with optional parameter Name set to “iexplore”), and send its output to “ConvertTo-XML”.
The server begins executing the pipeline when it receives the request. If the pipeline
completes quickly (within the synchronous-wait time) then the server stores the output
in the entity’s Output property, marks the invocation status as “Complete”, and returns
the completed entity to the client.
If the synchronous-wait time expires while the command is executing, then the server marks
the entity as “Executing” and returns it to the client. In this case, the client must
periodically request the updated entity from the server; once the retrieved entity’s status
is “Complete”, then the pipeline has completed and the client can inspect its output.
The client should then send an ODATA DeleteEntity request, allowing the server to
delete resources associated with the pipeline.
There are some important restrictions on the types of commands that can be executed.
Specifically, requests that use the following features will not execute successfully:
1. script blocks
2. parameters using environment variables such as "Get-Item -path $env:HOMEDRIVE\\Temp"
3. interactive parameters such as –Paging (Get-Process | Out-Host –Paging )
Authorization and PowerShell initial session state are handled by the same CLR interfaces
as for other Management ODATA resources. Note that every invocation calls some ConvertTo-XX cmdlet,
controlled by the OutputFormat property of the invocation. The client must be authorized to
execute this cmdlet in order for the invocation to succeed.
Here is the code snippet that shows how to send a request to create a PowerShell pipeline
invocation and how to get the cmdlet execution result:
public class CommandInvocationResource public string Command { get; set; } public string OutputFormat { get; set; } public int WaitMsec { get; set; } public string Status { get; set; } public string Output { get; set; } public List<ErrorRecordResource> Errors { get; set; } public DateTime ExpirationTime { get; set; } public CommandInvocationResource() public class ErrorRecordResource public ErrorCategoryInfoResource CategoryInfo { get; set; } public ErrorDetailsResource ErrorDetails { get; set; } public string Exception { get; set; } public class ErrorCategoryInfoResource public string Category { get; set; } public string Reason { get; set; } public string TargetName { get; set; } public string TargetType { get; set; } public class ErrorDetailsResource public string RecommendedAction { get; set; } |
Table 2.1 – Helper class definitions
// user need to specify the endpoint service URI as well as pass user name, password and domain //create data service context with protocol version 3 to connect to your endpoint // Expect returned data to be xml formatted. You can set it to “json” for the returned data to be in json //Powershell pipeline invocation command sample //Create an invocation instance on the endpoint }; // Ask for the invocation instance we just created Assert.IsNotNull(afterInvokeInstance, "instance was not found!"); if (afterInvokeInstance.Status == "Completed") //Delete the invocation instance on the endpoint |
Table 2.2 – Client Code Implementation
Narine Mossikyan
Software Engineer in Test
Standards Based Management