XCAT_REST_API_Development_Guideline

Overview

This document describes the principles and practices to implement the REST API interface for xCAT. The rest api framework has been determined, the implementated resources are the good examples for new developers to implement new resources.

Add New Resource

The principles to Define a Resource

  • The resource name must be noun. If the resource name can be a collection of multiple resource, use plurals.

    e.g. Since the URI for xcat node can be requested on multiple nodes, the URI should be /nodes instead of /node.

  • Present all URI parameters inside the URI itself. Try not to use the URI parameter section (i.e. after "?") except the filter/search. Mostly, we don't need URI parameters for GET method. For example, this URI can be used to get the 'arch','groups' and 'mgt' attributes for the node 'mynode'"

    /nodes/mynode/attr/arch,groups,mgt

  • The usage of PUT and POST

    PUT - is used to create or update a resource for which you know what the resource name is (or will be), so you can include it in the URI in the http request. PUT should be used for most xCAT create operations since the URI for resource is predictable before creating it.
    POST - is used to create a resource for which the resource name (and therefore the URI) is not known yet, because it will be generated by xCAT.

Definition of Resource

The definition for all the resource is stored in the restapi.pl::%URIdef which is a perl hash that includes the resource descriptions, URI format, supported methods and the usage information for each resource.

The format and principles to define a resource in the %URIdef:

 |--node - Resource Group
 |  `--allnode - Resource Name
 |    `--desc - Description for the Resource
 |    `--desc[1..10] - Additional description for the Resource
 |    `--matcher - The matcher which is used to match the URI to the Resource
 |    `--GET - The info is used to handle the GET request
 |      `--desc - Description for the GET operation
 |      `--desc[1..10] - Additional description for the GET operation
 |      `--usage - Usage message. The format must be '|Parameters for the GET request|Returns for the GET request|'. The message in the '|' can be black, but the delimiter '|' must be kept.
 |      `--example - Example message. The format must be '|Description|GET|URI PUT/POST_data|Return Msg|'. The messages in the four sections must be completed.
 |      `--cmd - The xCAT command line coammnd which will be used to complete the request. It's not a must have attribute.
 |      `--fhandler - The call back subroutine which is used to handle the GET request. Generally, it parses the parameters from request and then call xCAT command. This subroutine can be exclusive or shared.
 |      `--outhdler - The call back subroutine which is used to handle the GET request. Generally, it parses the xml output from the 'fhandler' and then format the output to JSON. This subroutine can be exclusive or shared.
 |    `--PUT - The info is used to handle the PUT request
 |    `--POST - The info is used to handle the POST request
 |    `--DELETE - The info is used to handle the DELETE request

The Output Format of Requests

The prerequisite to implement the correct output format is that the 'error/errorcode' returned by the xcatd xml response should be valid and correct. If it's not, the xCAT team should fix it.

When an Error occurs during the operation (i.e. there's error/errorcode in the output of xcat xml response):

For all the GET/PUT/POST/DELETE methods, the output will only includes 'error' and 'errorcode' properties:

{ 
   error:[
       msg1,
       msg2,
       ...
   ], 
   errorcode:error_number 
}

When NO Error occurs during the operation (i.e. there's no error/errorcode in the output of xcat xml response):

  • For the GET method

If the output can be grouped by the object (resource) name, and the information being returned is attributes of the object, then use the object name as the hash key and make the value be a hash of its attributes/values:

{
  object1: {
     a1 : v1,
     a2 : v2,
     ...
  },
  object2: {
     a1 : v1,
     a2 : v2,
     ...
  },
}

If the output can be grouped by the object (resource) name, but the information being returned is not attributes of the object, then use the object name as the hash key and make the value be an array of strings:

{
  object1: [
     msg1,
     msg2,
     ...
  ],
  object2: [
     msg1,
     msg2
     ...
  ],
}

An example of this case is the output of reventlog:

{
  "node1" : [
     "09/07/2013 10:05:02 Event Logging Disabled, Log Area Reset/Cleared (SEL Fullness)",
     ...
  ],
}

If the output is not object related, put all the output in a list (array):

[
   msg1,
   msg2,
   ...
]
  • For the PUT/DELETE methods

There will be no output for operations that succeed. (We made this decision because the output for them is always not formatted, and no program will read it if xcat indicates the operation has succeeded.)

  • For POST methods

Since POST methods can either be creates or general actions, there is not as much consistency. In the case of a create, the rule is the same as PUT/DELETE (no output if successful). For actions that have output that matters (e.g. xdsh, xdcp, updatenode), the rules are like the GET method.

The procedure to support a new resource

  1. Think over the resource and supported methods;
  2. Name the resource and URI;
  3. Add the definition of resource in the restapi.pl::%URIdef. The definition for each resource should obey the format of %URIdef strictly;
  4. Add the implementation of 'operation handler' (fhandler) and 'output handler' (outhdler); Reuse the handler subroutine is recommended;
  5. Test the resource with the URI+GET/PUT/POST/DELETE methods
  6. Test the automation generating document;
  7. Refine the usage information in the resource definition;

Test the automation generating document

  1. log in your xCAT MN
  2. cd /opt/xcat/ws
  3. ./restapi.pl -g (generate the plain text doc)
  4. ./restapi.pl -g wiki (generate the wiki format doc. You can copy the output to a wiki page to verify the format)
  5. Try to run the curl command which is generated in the doc to make sure it works well and have the proper output.

Debug Tools

  • Use parameter 'pretty=1' - Display the readable json format in the curl command

    curl -X GET -k 'https://127.0.0.1/xcatws/node/node1?userName=root&password=cluster&pretty=1'

  • Use parameter 'debug=1' - Display debug messages like the URI which is passed to the restapi.pl, the xml request and response which communicate with xcatd. 'debug=2' will display additional information.

    curl -X GET -k 'https://127.0.0.1/xcatws/node/node1?userName=root&password=cluster&pretty=1&debug=1'

  • Use perl debug mode to track the step by step execution

    cd /opt/xcat/ws
    perl -d ./restapi.pl GET /node/node1 root:cluster

  • Use formatmsg.pl to format the GET output to be a flat text for the fourth part the example description

    curl -X GET -k 'https://127.0.0.1/xcatws/nodes/node1/vitals/fanspeed?userName=root&password=cluster&pretty=1' 2>/dev/null | ./formatmsg.pl
    {\n \"node1\":{\n \"Fan 1A Tach\":\"3219 RPM\",\n \"Fan 4B Tach\":\"2720 RPM\",\n \"Fan 3B Tach\":\"2560 RPM\",\n \"Fan 4A Tach\":\"3330 RPM\",\n \"Fan 2A Tach\":\"3256 RPM\",\n \"Fan 1B Tach\":\"2592 RPM\",\n \"Fan 3A Tach\":\"3145 RPM\",\n \"Fan 2B Tach\":\"2592 RPM\"\n }\n}

The file formatmsg.pl

# cat formatmsg.pl
  #! /usr/bin/perl
  my $out;
  while (<STDIN>) {
      $msg = $_;
      $msg =~ s/\n/\\n/g;
      $msg =~ s/"/\\"/g;
      $out .= $msg;
  }
  $out =~ s/(\\n)*$//g;
  print "$out\n";

Examples

  • Get all the nodes in the xCAT cluster

    curl -X GET -k 'https://127.0.0.1/xcatws/node?userName=root&password=cluster&pretty=1'

    "all",
    "mmnodex3650m4n01",
    "mmnodex3650m4n02",
    "node1",
    "node2",
    "node3",
    "nodexxx",
    "x346n01",
    "x3550m4n01",
    "x3550m4n02",
    "x3550m4n02k01",
    "x3550m4n02k02",
    "x3550m4n02k03",
    "x3550m4n03",
    "x3650m4n03",
    "x3650m4n04",
    "x3650m4n05",
    "x3650m4n06",
    "x3650m4n07",
    "zxnode2"

  • Get all the attributes for node1

    curl -X GET -k 'https://127.0.0.1/xcatws/node/node1?userName=root&password=cluster&pretty=1'
    {
    "node1":{
    "profile":"compute",
    "netboot":"xnba",
    "ip":"192.168.1.10",
    "arch":"x86_64",
    "currchain":"boot",
    "os":"rhels6.4",
    "mac=mac":"6c:ae:8b:41:3f:53",
    "kernel":"xcat/osimage/rhels6.4-x86_64-install-compute/vmlinuz",
    "mgt":"ipmi",
    "bmc":"192.168.1.110",
    "groups":"111",
    "currstate":"install rhels6.4-x86_64-compute",
    "postscripts":"syslog,remoteshell,syncfiles",
    "provmethod":"rhels6.4-x86_64-install-compute",
    "updatestatustime":"03-20-2014 15:36:56",
    "updatestatus":"failed",
    "installnic":"mac",
    "kcmdline":"quiet repo=http://!myipfn!:80/install/rhels6.4/x86_64 ks=http://!myipfn!:80/install/autoinst/node1 ksdevice=mac=6c:ae:8b:41:3f:53",
    "initrd":"xcat/osimage/rhels6.4-x86_64-install-compute/initrd.img",
    "statustime":"03-19-2014 10:51:53",
    "postbootscripts":"otherpkgs"
    }
    }

  • Change the 'mgt' attribute for node1

    curl -k -X PUT -H Content-Type:application/json 'https://127.0.0.1/xcatws/node/node1?userName=root&password=cluster&pretty=1' --data '{"mgt":"ipmi"}'


Related

Wiki: HowTos

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.