The Spectrum Virtualize Representational State Transfer (REST) model Application Programming Interface (API) consists of command targets that are used to retrieve system information and to create, modify, and delete system resources. These command targets allow command parameters to pass through unedited to the Spectrum Virtualize command line interface, which handles parsing parameter specifications for validity and error reporting. Use Hypertext Transfer Protocol Secure (HTTPS) to successfully communicate with the RESTful API server.
The RESTful API server does not consider transport security (such as SSL), but instead assumes that requests are initiated from a local, secured server. The HTTPS protocol provides privacy through data encryption. The RESTful API provides more security by requiring command authentication, which persists for two hours of activity, or 30 minutes of inactivity, whichever occurs first.
Uniform Resource Locators (URLs) target different node objects on the system. The HTTPS POST method acts on command targets that are specified in the URL. For more information, see RESTful API command targets and characteristics. To make changes or view information about different objects on the system, you must create and send a request to the system. You are required to provide certain elements for the RESTful API server to receive and translate the request into a command, as described in the next section.
https://system_node_ip:7443/rest/commandWhere:
command_name,method="POST",headers={'parameter_name': 'parameter_value', 'parameter_name': 'parameter_value',...}
All commands, including LS commands, accept at least one named parameter. Because the Spectrum Virtualize RESTful API is POST method only, it implements a convention of appending positional parameters to the URI, and packing named parameters into the request body as JavaScript Object Notation (JSON) strings.
The more elegant method for the command targets was to adopt POST exclusively.
As mentioned, in addition to the URL and the name of the command target, other information is required in the request line and in the body of the HTTP request that regards the action to take on the specified object. In the request line, include the POST HTTP method. Include any required parameters (such as RAID level or IP address) in the body of the request.
{'X-Auth-Username': 'superuser'}
HTTP/1.1 200 OK Server: lighttpd/1.4.31 Date: date Content-type: application/json; charset=UTF-8 Content-length: content_length Connection: close {“attribute”: “value”}To view API command targets and their characteristics, see RESTful API command targets and characteristics. To see an example of how to get started, see Getting started. See rest_api_http_errors.html for a complete list of HTTP error codes that you might encounter.
POST method, authentication requirements, and whether to run on the configuration node stresses the POST method for all commands, including /auth. It also shows that you must use the authentication token that is returned by the /auth command target to authenticate every other command you run. Except for the /auth command target, you run commands against the system IP address so that they are run by the configuration node.
Command targets | Method | Authentication required | Run in Configuration Node / Cluster |
---|---|---|---|
/auth | POST | No | No |
All other command targets | POST | Yes | Yes |
Supported RESTful API commands for Spectrum Virtualize software shows the command target names of commonly used commands for this release of the RESTful API. Following convention, the svcinfo and svctask executable commands are defaults and do not require listing within your RESTful API command targets.
Descriptions of the command targets and their parameters, and descriptions of other less frequently used commands are available in the CLI command section of the product documentation.
Command targets | ||
/addhostclustermember | /addhostiogrp | /addhostport |
/addvdiskaccess | /addvdiskcopy | /addvolumecopy |
/auth | /chhost | /chnode |
/chnodecanister | /chrcconsistgrp | /chrcrelationship |
/chvdisk | /expandvdisksize | /lscurrentuser |
/lseventlog | /lsfcconsistgrp | /lsfcmap |
/lsfcmapcandidate | /lsfcmapdependentmaps | /lsfcmapprogress |
/lshost | /lshostcluster | /lshostclustermember |
/lshostclustervolumemap | /lshostiogrp | /lshostvdiskmap |
/lsiogrp | /lsiogrphost | /lsmdiskgrp |
/lsnode | /lsnodecanister | /lsnodehw |
/lsnodecanisterhw | /lsnodecanisterstats | /lsnodecanistervpd |
/lsnodehw | /lsnodestats | /lsnodevpd |
/lspartnership | /lsrcrelationshipprogress | /lssystem |
/lssystemip | /lssystemstats | /lsvdisk |
/lsvdiskaccess | /lsvdiskcopy | /lsvdiskfcmapcopies |
/lsvdiskfcmappings | /lsvdiskhostmap | /lsvdisksyncprogress |
/mkfcconsistgrp | /mkfcmap | /mkfcpartnership |
/mkhost | /mkhostcluster | /mkrcconsistgrp |
/mkrcrelationship | /mkvdisk | /mkvdiskhostmap |
/mkvolume | /mkvolumehostclustermap | /movevdisk |
/prestartfcconsistgrp | /prestartfcmap | /rmfcmap |
/rmhost | /rmhostcluster | /rmhostclustermember |
/rmhostiogrp | /rmhostport | /rmvdisk |
/rmvdiskaccess | /rmvdiskcopy | /rmvdiskhostmap |
/rmvolume | /rmvolumecopy | /rmvolumehostclustermap |
/startfcmap | /startrcconsistgrp | /startrcrelationship |
/stopfcconsistgrp | /stopfcmap | /stoprcconsistgrp |
/stoprcrelationship |
Aside from data encryption, the HTTPS server requires authentication of a valid user name and password for each API session. Use two authentication header fields to specify your credentials: X-Auth-Username and X-Auth-Password.
Initial authentication requires that you POST the authentication target (/auth) with the user name and password. The RESTful API server returns a hexadecimal token. A single session lasts a maximum of two active hours or thirty inactive minutes, whichever occurs first. When your session ends due to inactivity, or if you reach the maximum time that is allotted, error code 403 indicates the loss of authorization. Use the /auth command target to reauthenticate with the user name and password.
https://192.168.10.109:7443/rest/auth, method="POST", headers={'X-Auth-Username': 'superuser', 'X-Auth-Password': 'passw0rd'}The HTTP request that was sent to the API server looks like:
POST /auth HTTPS/HTTPS_version Host: https://192.168.10.109:7443 Content-type: application/json; charset=UTF-8 Content-length: message_size X-Auth-Token: 58cfd6acb1676e1cba78b7cb5a9a081d11d1d1cfeb0078083ef225d9c59bf4df {“attribute”: “value”,“attribute”: “value”}Where:
{ "token": "58cfd6acb1676e1cba78b7cb5a9a081d11d1d1cfeb0078083ef225d9c59bf4df" }
Command targets interact with different parts of the system. After you target a specific node in the system (usually a configuration node), target an object within that node. See Supported RESTful API commands for Spectrum Virtualize software for command targets and see the CLI commands section of this product documentation for individual command descriptions of parameters that you can specify.
The following Python 3 example shows how to complete initial setup to start interacting with the system and running commands. For examples in other languages, see RESTful API usage examples in Perl and rest_api_usage_examples.html.
import ssl import json import pprint import urllib.request import urllib.error import urllib.parse no_verify = ssl.create_default_context() no_verify.check_hostname = False no_verify.verify_mode = ssl.CERT_NONE if getattr(ssl, '_https_verify_certificates', None): ssl._https_verify_certificates(False) class HostString(str): """ Comment: Special subclass of string, for storing arbitrary host-related attributes (such as auth tokens) without losing any string behavior """ def __new__(cls, *args, **kwds): return super(HostString, cls).__new__(cls, *args, **kwds) class RESTUtil(object): show_default=False default_headers = {} port = 80 def __init__(self, show=None, catch=True): self.hosts = {} self.curr_host = None self.catch=catch self.show_default=show if show != None else self.show_default @property def host(self): return self.curr_host @host.setter def host(self, hostname): """ Comment: Retrieve the HostString object of a known host from its host name or string definition. Even if the host definition is provided, we still need to key into self.hosts in case the client classes are storing things on their HostString objects. """ try: if hostname in self.hosts: self.curr_host = self.hosts[hostname] else: self.curr_host = [h for h in self.hosts.values() if h == hostname][0] return self.curr_host except IndexError: raise KeyError("Unrecognized host/name %s" % hostname) def add_host(self, hostdef, hostname=None): hostname = hostname if hostname is None else hostdef self.hosts[hostname] = HostString(hostdef) if self.curr_host == None: self.curr_host = self.hosts[hostname] return hostname def command(self, protocol, postfix, method='POST', headers=None, show=None, **cmd_kwds): """ Comment: A fairly generic RESTful API request builder. See subclasses for examples of use. """ if show == None: show = self.show_default headers = {} if headers == None else headers url = '%s://%s:%s/%s' % ( protocol, self.curr_host, self.port, postfix ) request = urllib.request.Request( url, headers =dict(self.default_headers, **headers), data=bytes(json.dumps(cmd_kwds), encoding="utf-8") if cmd_kwds else None) request.get_method = lambda: method if show: self.request_pprint(request) try: cmd_out = urllib.request.urlopen(request, context=no_verify).read().decode('utf-8') except urllib.error.HTTPError as e: self.exception_pprint(e) if not self.catch: raise Exception("RESTful API command failed.") return try: cmd_out = json.loads(cmd_out) except ValueError: pass if show: print("\nCommand Output:") pprint.pprint(cmd_out) print("") return cmd_out @staticmethod def request_pprint(request): """ Comment: Request info print function (for self.command with show=True) """ print(request.get_method(), request.get_full_url(), 'HTTP/1.1') print('Host:', request.host) for key, value in request.headers.items(): print(key.upper() + ':', str(value)) if request.data != None: print() pprint.pprint(request.data) @staticmethod def exception_pprint(http_error): """ Comment: HTTPError info print function """ print(http_error.code, '--', http_error.reason) print(http_error.fp.read()) print("") class SVCREST(RESTUtil): """ Comment: RESTful wrapper for the SVC CLI """ def __init__(self, host, *args, **kwds): self.debug = kwds.pop('debug', False) super().__init__(*args, **kwds) self.add_host(host) @property def default_headers(self): return {'X-Auth-Token': getattr(self.curr_host, 'token', 'badtoken'), 'Content-Type': 'application/json'} @property def port(self): return getattr(self, '_port', None) or ('7665' if self.debug else '7443') @property def protocol(self): return getattr(self, '_protocol', None) or ('http' if self.debug else 'https') def command(self, cmd, *args, method="POST", headers=None, show=None, **cmd_kwds): postfix = '/'.join( ['rest'] + [cmd] + [urllib.parse.quote(str(a)) for a in args] ) return super().command( self.protocol, postfix, method=method, headers=headers, show=show, **cmd_kwds ) def authenticate(self, username='superuser', password='passw0rd', show=None): cmd_out = self.command( 'auth', show=show, method="POST", headers={'X-Auth-Username': username, 'X-Auth-Password': password} ) if cmd_out: self.curr_host.token = cmd_out['token'] """ Comment: First, set your cluster ipaddress. It's assumed superuser/passw0rd (6 lines above) is the crednetial. After the authenticate call, you can issue any command in s.command('') that is an svcinfo or svctask cmmand) """ s = SVCREST('192.168.10.109') s.authenticate() print(s.command('lssystem'))