3 API Documentation
Introduction
The Moab® Web Services (MWS) provide a set of RESTful resources that can be used to create, read, update, and delete various objects in the Moab® Workload Manager.3.1 RESTful Web Services
In order to understand how to use Moab Web Services, it is first necessary to give a brief introduction to REST. REST (Representational State Transfer) is a set of guidelines which utilizes the full HTTP (Hypertext Transfer Protocol) specification along with endpoint URLs that describe resources. The HTTP methods used in REST are composed of the following:Method | Description |
---|---|
GET | Query for a list or a single resource. |
POST | Creating a resource. |
PUT | Modifying a resource. |
DELETE | Deleting a resource. |
1
represents a unique identifier for books in each case.Method | URL | Description |
---|---|---|
GET | /books | Retrieves a list of all books in the library. |
POST | /books | Creates a new book. |
GET | /books/1 | Retrieves a single book. |
PUT | /books/1 | Modifies a single book. |
DELETE | /books/1 | Deletes a single book. |
Note that in the cases of the POST and PUT operations, additional information may be needed to describe the resource to be created or the fields that should be modified.Moab Web Services provides RESTful web services for many resources. The methods and URLs available are documented in the Resources section.
3.2 Data Format
JSON (JavaScript Object Notation) is the data format used for all communication with MWS. This format makes use of two main structures: collections of key/value pairs called objects and ordered lists of values called arrays . Objects are defined by using curly braces ({}
), and arrays are defined by using square brackets ([]
). A JSON
object or array may contain several different types of values including numbers, booleans (true/false), strings,
objects, arrays, or the keyword 'null' representing no value.
For
example, a simple JSON object might be defined as:{ "number": 1, "decimalNumber": 1.2, "boolean": true, "string": "Any string", "dateString": "2013-05-23 17:32:02 UTC", "object": { "key": "value" }, "array": [ "value1", "value2" ], "nullValue": null }
"yyyy-MM-dd HH:mm:ss ZZZ"
. For more details on that pattern, see
Joda-Time DateTimeFormat.
For a list of valid time zone IDs, see
Joda-Time Available Time Zones.For more information on JSON, see json.org.The data format of MWS is defined as follows:
- Input for a POST or PUT must be in JSON format. Set the
Content-Type
header toapplication/json
. - Output is in JSON format and always consists of an object with zero or more key/value pairs.
- The output may also be "pretty-printed" or formatted for human viewing by sending a URL parameter. See Global URL Parameters for more information.
3.3 Global URL Parameters
All URL parameters are optional.
Parameter | Valid Values | Description |
---|---|---|
api-version | Integer | Requests a specific API version |
pretty | true | Controls pretty printing of output |
fields | Comma-Separated String | Includes only specified fields in output |
exclude-fields | Comma-Separated String | Excludes specified fields from output |
max | Integer | The maximum number of items to return |
offset | Integer | The index of the first item to return |
API Version (api-version)
See Requesting Specific API Versions for information on this parameter and how it should be used.Pretty (pretty)
By default, the output is easy for a machine to read but difficult for humans to read. The pretty parameter formats the output so that it is easier to read.Field Selection (fields)
The fields parameter will include only the specified fields in the output. For list queries, the field selection acts on the objects in results and not on the totalCount or results properties themselves.The format of the fields parameter is a comma-separated list of properties that should be included, as inid,state
. Using periods, sub-objects may also be specified, and fields of these objects may be
included as well. This is done with the same syntax for both single sub-objects and lists of sub-objects,
as in id,requirements.requiredNodeCountMinimum,blockReason.message
.Example for a job query
Request
GET /rest/jobs?api-version=2&fields=name,flags,requirements.taskCount,dates.createdDate
Response
{ "totalCount": 1, "resultCount": 1, "results": [ { "dates": {"createdDate": "2012-10-17 01:11:54 UTC"}, "flags": ["GLOBALQUEUE"], "name": "Moab.24", "requirements": [{"taskCount": 1}] }] }
Field Exclusion (exclude-fields)
The exclude-fields parameter is the opposite of the fields parameter. All fields will be included in the output except those that are specified. For list queries, the field exclusion acts on the objects in results and not on the totalCount or results properties themselves.The format of the exclude-fields parameter is a comma-separated list of properties that should be excluded from the output, as inid,state
. Using periods, sub-objects may also be specified, and fields of these
objects may be excluded as well. This is done with the same syntax for both single sub-objects and lists of sub-objects,
as in id,requirements.requiredNodeCountMinimum,blockReason.message
.Example
Suppose a query returns the following JSON:Request with No Field Exclusion
GET /objects
Response
{ "id": "1", "listOfStrings": [ "string1", "string2" ], "listOfObjects": [ { "item1": "value1", "item2": "value2" }], "singleObject": { "id": "obj1", "field1": "value1" } }
Request with Field Exclusion
GET /objects?exclude-fields=id,listOfObjects.item2,singleObject.field1,listOfStrings
Response
{ "listOfObjects": [{"item1": "value1"}], "singleObject": {"id": "obj1"} }
Sorting (sort)
Services, Service Templates, Images, and Events support sorting based on MongoDB syntax by using the sort parameter. To sort in ascending order, specify a1
for the sorting field.
To sort in descending order, specify a -1
. Objects can also be sorted on nested fields by using
dot notation to separate the sub-fields, such as field.subfield1.subfield2
.Examples
To sort services in ascending order by account:http://localhost/mws/rest/services?sort={"account":1}
http://localhost/mws/rest/services?sort={"account":-1}
http://localhost/mws/rest/services?sort={"attributes.moab.job.resources.procs":-1}
http://localhost/mws/rest/service-templates?sort={"name":1}
http://localhost/mws/rest/service-templates?sort={"name":-1}
http://localhost/mws/rest/service-templates?sort={"attributes.moab.job.template":1}
3.4 Requesting Specific API Versions
Because of significant changes in the API introduced in 7.2, MWS possesses a versioned API. Theapi-version
URL parameter may be used to change the requested API version for any call to MWS. The current valid API versions
with their corresponding MWS versions are shown in the table below:API Version | MWS Version | Documentation |
---|---|---|
1 | 7.0 and 7.1 | MWS 7.1.1 Documentation |
2 | 7.2 | Contained within this document |
latest | Latest | Contained within this document |
- If no API version is requested, it will default to version
1
. - The Resources documentation contains information for the latest API version. For documentation of previous API versions, please see the table above.
- When the
latest
API version is requested, it resolves to the latest API version of MWS, such as2
for MWS 7.2.
Examples
GET http://localhost:8080/mws/rest/nodes // Data returned uses API version 1GET http://localhost:8080/mws/rest/nodes?api-version=1 // Data returned uses API version 1GET http://localhost:8080/mws/rest/nodes?api-version=2 // Data returned uses API version 2GET http://localhost:8080/mws/rest/nodes?api-version=latest // Data returned uses API version 2
3.5 Responses and Return Codes
Various HTTP responses and return codes are generated from MWS operations. These are documented below according to the operation that they are associated with.Listing and Showing Resources
For any successful list or show operation (GET
), a 200 OK
response code is always returned.
No additional headers beyond those typical of a HTTP response are given in the response.The body of this response consists of the results of the list or show operation. For a list operation,
the results are wrapped in metadata giving total and result counts. The result count represents
the number of resource records returned in the current request, and the total count represents the
number of all records available. These differ when querying or the max
and offset
parameters are
used. The following is an example of a list operation response:JSON List Response Body
{ "resultCount":1, "totalCount":5, "results":[ { "id":"Moab.1", … } ] }
JSON Show Response Body
{ "id":"Moab.1", … }
Creating Resources
A successful creation (POST
) of a resource has two potential response codes:
- If the resource was created immediately, a
201 Created
response code is returned. - If the resource is still being created, a
202 Accepted
response code is returned.
Location
header is added to the response with the full URL which
can be used to get more information about the newly created resource or the task
associated with creating the resource (if a 202
is returned).Additionally, the body of the response will contain the unique identifier of the
newly created resource or the unique identifier for the task associated with creating
the resource (if a 202
is returned).For example, during creation or submission of a job, a 201
response code is returned
with the following response headers and body:Job Creation Response Headers
HTTP/1.1 201 Created
Server: Apache-Coyote/1.1
Location: /mws/rest/jobs/Moab.21
X-Moab-Status: Success
X-Moab-Code: 000
Content-Type: application/json;charset=utf-8
Content-Length: 16
Date: Wed, 21 Dec 2011 23:04:47 GMT
Job Creation Response Body
{"id":"Moab.21"}
VM Creation Response Headers
HTTP/1.1 202 Accepted
Server: Apache-Coyote/1.1
Location: /mws/rest/jobs/vmcreate-1
X-Moab-Status: Success
X-Moab-Code: 000
Content-Type: application/json;charset=utf-8
Content-Length: 23
Date: Wed, 21 Dec 2011 23:12:50 GMT
VM Creation Response Body
{"jobId":"vmcreate-1"}
Modifying Resources
For any successful resource modification operation (PUT
), a 200 OK
or
202 Accepted
response code is returned. A 200
response code signifies
that the modification was immediately completed. No additional headers are
returned in this case. A 202
response code is used again to signify that the
modification is not yet complete and additional actions are taking place. In this case,
a Location
header is also returned with the full URL of the resource describing
the additional actions.In the case of a 200
response code, the body of this response typically consists of
an object with a single messages
property containing a list of statuses or results
of the modification(s). However, a few exceptions to this rule exist as documented in the
Resources section. In the case of a 202
response code, the format is
the same as for a 202
during a creation operation, in that the body consists of an object
with the unique identifier for the task associated with the additional action(s).For example, when modifying a job, several messages may be returned as follows with the
associated 200
response code.Job Modification Response Headers
HTTP/1.1 200 OK Server: Apache-Coyote/1.1 X-Moab-Status: Success X-Moab-Code: 000 X-Moab-Message: Content-Type: application/json;charset=utf-8 Content-Length: … Date: Thu, 22 Dec 2011 16:49:43 GMT
JSON Modify Response Body
{ "messages":[ "gevent processed", "variables successfully modified" ] }
VM Modification Response Headers
HTTP/1.1 202 Accepted
Server: Apache-Coyote/1.1
Location: /mws/rest/jobs/vmmigrate-1
X-Moab-Status: Success
X-Moab-Code: 000
Content-Type: application/json;charset=utf-8
Content-Length: 22
Date: Wed, 21 Dec 2011 23:12:50 GMT
VM Modification Response Body
{"jobId":"vmmigrate-1"}
Deleting Resources
For any successful resource deletion operation (DELETE
), a 200 OK
or
202 Accepted
response code is returned. A 200
response code signifies
that the deletion was immediately completed. No additional headers are
returned in this case. A 202
response code is used again to signify that the
deletion is not yet complete and additional actions are taking place. In this case,
a Location
header is also returned with the full URL of the resource describing
the additional actions.In the case of a 200
response code, the body of this response is empty. In the
case of a 202
response code, the format is the same as for a 202
during a
creation operation, in that the body consists of an object with the unique
identifier for the task associated with the additional action(s).For example, when deleting a job, a 200
response code is returned with an empty
body as shown below.Job Deletion Response
HTTP/1.1 200 OK Server: Apache-Coyote/1.1 X-Moab-Status: Success X-Moab-Code: 000 X-Moab-Message: Content-Type: application/json;charset=utf-8 Content-Length: 0 Date: Thu, 22 Dec 2011 16:49:43 GMT
VM Deletion Response Headers
HTTP/1.1 202 Accepted
Server: Apache-Coyote/1.1
Location: /mws/rest/jobs/vmdestroy-1
X-Moab-Status: Success
X-Moab-Code: 000
Content-Type: application/json;charset=utf-8
Content-Length: 22
Date: Wed, 21 Dec 2011 23:12:50 GMT
VM Deletion Response Body
{"jobId":"vmdestroy-1"}
Moab Response Headers
In addition to the typical HTTP headers and theLocation
header described above,
several headers are returned if the operations directly interact with
Moab. These headers are described in the following table:Name | Description |
---|---|
X-Moab-Status | One of Success , Warning , or Failure . Describes the overall status of the Moab request. |
X-Moab-Code | A three digit code specifying the exact error encountered, used only in debugging. |
X-Moab-Message | An optional message returned by Moab during the request. |
3.6 Error Messages
Below is an explanation of what error message format to expect when an HTTP status code other than 20x is returned. All error codes have a response code of 400 or greater.400 Bad Request
This response code is returned when the request itself is at fault, such as when trying to modify a resource with an emptyPUT
request body or when
trying to create a new resource with invalid parameters. The response body is as
follows:{ "messages":[ "Message describing error", "Possible prompt to take action" ] }
401 Unauthorized
This response code is returned when authentication credentials are not supplied or are invalid. The response body is as follows:{ "messages":[ "You must be authenticated to access this area" ] }
403 Forbidden
This response code is returned when the credentials supplied are valid, but the permissions granted are insufficient for the operation. This occurs when using Application Accounts with limited access.{ "messages":[ "You are not authorized to access this area" ] }
404 Not Found
This response code is returned when the request specifies a resource that does not exist. The response body is as follows:{ "messages":[ "The resource with id 'uniqueId' was not found" ] }
405 Method Not Allowed
This response code is returned when a resource does not support the specified HTTP method as an operation. The response body is as follows:{ "messages":[ "The specified HTTP method is not allowed for the requested resource" ] }
500 Internal Server Error
This indicates that there was an internal server error while performing the request, or that an operation failed in an unexpected manner. These are the most serious errors returned by MWS. If additional information is needed, the MWS log may contain further error data. The response body is as follows:{ "messages":[ "A problem occurred while processing the request", "A message describing the error" ] }
3.7 Pre and Post-Processing Hooks
MWS provides functionality to intercept and modify data sent to and returned from web services for all available resources. This is done by creating hooks in Groovy files located in a sub-directory of theMWS_HOME
directory (/opt/mws/hooks
by default).The full reference for available hooks and methods available to them can be found on the Hooks page in the reference guide.
Configuring Hooks
The directory of the hooks folder may be changed by providing a value formws.hooks.location
in the configuration file.
If the directory starts with a path separator (ie /path/to/hooks
), it will be treated as an absolute path. Otherwise, it
will be used relative to the location of the MWS home directory.For example, if the MWS home directory is set to /opt/mws
, the hooks directory by default
would be in /opt/mws/hooks
. Changing the mws.hooks.location
property to myhooks
would result in the hooks directory
being located at /opt/mws/myhooks
. Due to the default location of the MWS home directory, the default directory
of the hooks directory is /opt/mws/hooks
.On startup, if the hooks directory does not exist, it will be created with a simple README.txt
file with instructions
on how to create hooks, the objects available, and the hooks available. If the folder or file is unable to be created,
a message will be printed on the log with the full location of a README file, copied into a temporary directory.Defining Hooks for a Resource
Hooks are defined for resources by creating groovy class files in the hooks directory (MWS_HOME/hooks
by default).
Each groovy file must be named by the resource URL it is associated with and end in ".groovy". The following table shows
some possible hook files that may be created. Notice that the virtual machines hook file is abbreviated as vms
, just
as the URL for virtual machines is /rest/vms
. In all cases, the hook file names will match the URLs.Resource | Hook Filename |
---|---|
Jobs | jobs.groovy |
Nodes | nodes.groovy |
Virtual Machines | vms.groovy |
Pending Actions | pending-actions.groovy |
url | url.groovy |
Complete Hook File
// Example before hook def beforeList = { // Perform actions here // Return true to allow the API call to execute normally return true }def beforeShow = { // Perform actions here // Render messages to the user with a 405 Method Not Allowed // HTTP response code renderMessages("Custom message here", 405) // Return false to stop normal execution of the API call return false }// Example after hook def afterList = { o -> if (!isSuccess()) { // Handle error here return false } // Perform actions here return o }
before
and after
are different, each will be explained separately.Before Hooks
As shown above,before
hooks require no arguments. They can directly act on several properties, objects, and methods
as described in the Hooks reference guide. The return value is one of the most important aspects of
a before
hook. If it is false
, a renderMessages
, renderObject
, renderList
, render
, or redirect
method must
first be called. This signifies that the API call should be interrupted and the render or redirect action specified within
the hook is to be completed immediately.A return value of true
signifies that the API call should continue normally. Parameters, session variables, request and
response variables may all be modified within a before
hook.If no return value is explicitly given, the result of the last statement in theFor all methods available tobefore
hook to be executed will be returned. This may cause unexpected behavior if the last statement resolves tofalse
.
before
hooks as well as specific examples, see the Hooks page in the reference guide.After Hooks
After
hooks are always passed one argument: the object or list that is to be rendered as JSON. This may be modified as
desired, but note that the object or list value is either a
JSONArray or
JSONObject. Therefore, it may not be accessed and modified as a typical groovy Map.Unlike before
hooks, after
hooks should not call the render*
methods directly. This method will automatically be called on the
resulting object or list returned. The redirect
and render
methods should also not be called at this point. Instead, if a custom object
or list is desired to be used, the serializeObject
and serializeList
methods are available to create suitable results to return.The return value of an after
hook may be one of two possibilities:
- The potentially modified object or list passed as the first argument to the hook. In this case, this value will override the output object or list unless it is null.
- Null or false. In this case, the original, unmodified object or list will be used in the output.
The return value of theFor all methods available toafter
hook, if not null or false, must be the modified object passed into the hook or an object or list created with theserialize*
methods.
after
hooks as well as specific examples, see the Hooks page in the reference guide.Error Handling
After
hooks, unlike the before
hooks, have the possibility of handling errors encountered during the course of the request.
Handling errors is as simple as adding a one-line check to the hook as shown above or in the following code:if (!isSuccess()) { // Handle error return false }
after
hook contain at least these lines of code to prevent confusion on what the input object or list represents
or should look like.The isSuccess()
function is false if and only if the HTTP response code is 400 or higher, such as a 404 Not Found, 400 Bad Request, or
500 Internal Server Error and the cause of the error state was not in the associated before
hook. In other words, objects and lists
rendered in the before
hook with any HTTP response code will never run the associated after
hook.When handling errors, the passed in object will always contain a messages
property containing a list of Strings describing
the error(s) encountered.Defining Common Hooks
Sometimes it is beneficial to create hooks which are executed for all calls of a certain type, such as abeforeList
hook that is
executed during the course of listing any resource. These are possible using an all.groovy
file. The format of this file
is exactly the same as other hook files. The order of execution is as follows:
Before
common hook executedBefore
resource-specific hook executed- Normal API call executed
After
resource-specific hook executedAfter
common hook executed
3.8 Authentication
MWS uses Basic Authentication for all REST API requests. This means that a username and password must be provided for each call to resources. There are two types of accounts that can be granted access: Users and Applications.- For insructions on how to set the credentials for the default User account, see the "Client Connections to MWS" section in Security.
- For insructions on how to manage Application accounts, see Application Accounts.
Authorization: Basic YWRhcHRpdmU6YzNVU3R1bkU=
Basic
is the base64 encoding of
username : password . In the example above, YWRhcHRpdmU6YzNVU3R1bkU=
is the base64 encoding of adaptive:c3UStunE
. See section 2 of
RFC 2617 for more details.The username and password in the Basic Authentication header are encoded but not encrypted. Therefore, it is strongly recommended that MWS be run behind a proxy (like Apache) with SSL enabled. See the section "Encrypting Client Connections using Apache and SSL" under Security.