API Reference¶
This document describes the Application Programming Interface (API) for interacting with Scyld ClusterWare.
Overview¶
The Scyld ClusterWare API enables cluster management, monitoring, and provisioning using a series of HTTP requests. While this web API is typically accessed by using the provided web portal and command line tools, users can also create their own customized tools by calling the web API in their own scripts.
Aside from a couple of endpoints related to long-running background jobs, the ClusterWare API is stateless, meaning there is no need for the client to remember any previous state information.
The API is organized around the major ClusterWare objects:
Nodes -
/nodes
Attribute Groups -
/attribs
Admins -
/admins
Login/Authentication endpoints
Boot Configurations -
/bootconfigs
Images -
/images
Networks -
/nets
Hostnames -
/hosts
Dynamic Groups -
/dyngroups
Naming Pools -
/namingpools
Head nodes -
/heads
,/database
Software Repositories -
/repos
Software Distributions -
/distros
Git Repositories -
/gitrepos
Cluster-wide information -
/cluster
Each ClusterWare object type has several method endpoints for getting or setting data that
can be accessed using an HTTP call to the correct endpoint. For example, an HTTP GET call
to the /nodes
endpoint will return a list of all known nodes.
Some method endpoints also accept a unique identifier (UID) as part of the URL. For
example, an HTTP GET call to /node/<UID>
will return details about the node with the
matching UID. A UID is a 32-character string of lower-case letters and digits,
such as bf0f61d24ce84064a8c7c7e872332c07
or e54e420c42214101918584e27382e8f5
.
Many method endpoints that accept a UID will also accept other identifiers in place of a
UID. For example, calls to Admins
endpoints can use a username in place of the UID and
calls to the Nodes
endpoints can accept a node name, MAC address, or IP address in place
of the UID.
Data being sent to web API endpoints is expected to be encoded in JSON format. Usually this data will be an JSON object (hash-table or dictionary), though some endpoints accept a list or string instead.
The HTTP response from the server will usually be a JSON object. When an HTTP request is
successful, the response will have an HTTP status code of 200, the JSON object will contain
a "success"
entry with a value of true
, and any additional data can be found in the "data"
entry. For example:
{ "success": true, "data": "4e75fa48…0f005bd" }
If the HTTP response fails, then a 400-series status code will be returned (e.g. 401 for
invalid credentials; 403 for denied access; 404 for object not found, etc.), the "success"
entry will have a value of false
, and a "reason"
entry will have a description of why the
action failed. For example:
{ “success": false, "reason": "No node found for ID=n123" }
Authentication¶
The majority of ClusterWare API endpoints require that an authentication token is included in
the request. This authentication token will usually come from a call to the login
or
token refresh
endpoints. There are several authentication options for logging in:
Username / Password authentication. This leverages the operating system's login credentials.
SSH key authentication. This uses a public / private key pair. The private keys must be set inside ClusterWare.
Local-socket authentication service. This only works if a user is logged in to the head node where the request is made.
When the login is successful, two JSON Web Tokens (JWTs; see https://jwt.io/) will be returned: an access token and a refresh token. The refresh token can be presented to the token-refresh endpoint to make a new access token.
Note
The ClusterWare command-line tools use the access token when possible and will automatically use the refresh token when the access token has expired. Admins writing their own tools will have to detect errors due to token expiration and manually initiate a refresh.
While there are ways to unpack and interpret the data inside a JWT, the tokens can be considered opaque. A client simply receives a JWT upon login, and then sends that same JWT inside an authorization header on future requests:
Header: “Authorization: Bearer eyJhbGciOiJIUzI1Ni…”
The access token has an embedded expiration time (which is also sent by ClusterWare during the login process) and after that time, the token will be rejected by the head node. The refresh token has its own expiration time, usually much longer than the access token. So the expectation is that when the access token expires, the refresh token will still be valid and can be used to make a new access token.
Note
While the refresh token is ONLY usable for making a new access token, it cannot be used to interact with the other endpoints.
In a multi-head cluster, every head node may be configured to use different underlying “secrets” that are used when making new tokens. Thus, after authenticating to one head node, the tokens that are returned may not be usable on other head nodes. In the rare case that a client needs to interact with multiple head nodes, it should login to each one separately and ensure that future requests use the correct token with each corresponding head node.
Where authentication asserts that “this user is who they say they are”, ClusterWare uses role-based access control (RBAC) to limit what specific actions a given user can take. For more information on ClusterWare’s RBAC roles, see sections in the ClusterWare Admin and Reference Guides.
Note
As with other token-based authentication systems, if anyone intercepts or acquires a copy of a token, they can fully impersonate the user who created it. Care must be taken to protect the tokens from other users. Consider using OS or file-system based access control mechanisms.
Username/Password Authentication¶
The traditional username/password process is provided through a PAM connector. When a login request is made, the system is queried to see if the given username and password are valid. If they are, ClusterWare will make a new token and return it to the caller.
The data is sent as a JSON object with "user"
and "pass"
keys:
curl -X POST https://head1.cluster.local/api/v1/login --data '{"user":"admin1", \
"pass":"password"}'
Note that these example curl commands are interacting with an HTTP endpoint, but they are also available using HTTPS. Further, the examples may show passwords on the command line, but putting a password on the command line is not recommended as it may be visible to other users via ps or similar commands.
The returned value will include the access and refresh tokens, as well as expiration values for both:
{"success": true, "data": {"user": "admin1", "token": {"access_token": \
"eyJhbGciOiJIUzI1Ni…", "expires_in": 1200, "refresh_token": \
"eyJhbGciOiJIUzI1Ni…", "refresh_expires_in": 2592000}}}
The expiration times are in seconds from when the server issued the token. For long-running actions or scripts, admins may want to err on the side of caution and refresh prior to the actual expiration of the access token.
Note
While the head nodes synchronize data amongst themselves, the underlying operating systems do not synchronize unless configured to do so via some other mechanism. The head nodes could have their /etc/passwd and /etc/shadow files synchronized through scp or sftp, or through an external directory system (LDAP, NIS), but that is outside the scope of this document.
Token Refresh¶
The access token can be used in subsequent requests up until the expiration time. Once it has expired, the refresh token can be used to acquire a new access token through the token-refresh endpoint:
curl -X GET https://head1.cluster.local/api/v1/newtoken -H "Authorization: \
Bearer eyJhbGciOiJIUzI1Ni…"
Again, note that this should be the refresh token that is sent to this endpoint – sending an access token will result in a failure.
Upon success, a new set of tokens will be returned:
{"success": true, "data": {"authorized_by": "admin1", "userid": "admin1", "uid": \
"735367a122664db8ae8ba3ec113f1643", "token": {"access_token": \
"eyJhbGciOiJIUzI1Ni…", "expires_in": 1200, "refresh_token": \
"eyJhbGciOiJIUzI1Ni…", "refresh_expires_in": 2592000}}}
If the authentication fails, the "success"
field will be false and a "reason"
field will contain
more information.
Note
The default access token duration is 20 minutes; the default refresh token duration is 30 days.
Alternate Authentication Methods¶
There are two other authentication methods that can be used during login – a one-time password (OTP) sent to a local socket, and SSH-key authentication. For more information, please contact Penguin Solutions.
Since head nodes are assumed to be “locked down” and protected from end-user access, when a client
is running on the head node, they can send an OTP to a known Unix socket and then re-send that OTP
during the login process. The same POST /login
endpoint is used, but with “user” and “secret” keys.
If successful, ClusterWare will return a set of access and refresh tokens.
For information on the SSH-key login process, please contact Penguin Solutions.
Basic Operations¶
For most ClusterWare objects, standard HTTP actions are supported for manipulating the entries. Using the Node objects as an example:
List objects -
GET /nodes
Create new object -
POST /nodes
Get object info -
GET /node/<UID>
Update some info -
PATCH /node/<UID>
Update all info -
PUT /node/<UID>
Delete object -
DELETE /node/<UID>
Metadata -
GET /nodes/meta
Endpoints that refer to a whole class of objects are pluralized (end with ‘s’), such as
/nodes
or /images
. Endpoints that refer to one specific object are singular and include a UID,
such as /node/<UID>
or /image/<UID>
.
List Objects¶
Issuing an HTTP GET to an object-class (pluralized) endpoint will return information about all the objects of that class. Since this endpoint will only return a list of UIDs for the objects, any detailed information will have to be found with a subsequent call to the GET endpoint.
The return value will be a JSON object with two main fields: success and data. The data field will also be a JSON object, with the keys being set to object UIDs:
{ “success": true, "data": { "7ad57…73e4a1f4": {… first object’s data …}, \
"ab89c…2501817": {… second object’s data …}}}
If the request is unsuccessful, then a reason field will be returned with more information on why the request failed.
{ "success": false, "reason": "No node found for ID=n123" }
Create New Object¶
To create a new object, a POST is issued to the object-class (pluralized) endpoint with the relevant
data. Most object types accept a name
and "description"
field, but most fields are object-specific
(see below for details).
To create a new compute-node object:
curl -X POST https://head1.cluster.local/api/v1/nodes --data \
'{"mac":"11:22:33:44:55:66"}' -H "Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
On success, ClusterWare will return a UID for the newly create node:
{ “success": true, "data": "4e75fa48…0f005bd" }
Upon failure, the returned data will include a "reason"
field with more information on why the request
failed:
{ “success": false, "reason": "Node with MAC=52:54:00:00:00:03 already exists." }
Get Object Info¶
Issuing an HTTP GET
to an endpoint will return information about a specific object. Depending on the
object type, the UID
may be the true UID for the object, the name of the object, or some other
object-specific unique identifier such as MAC address (for nodes).
The return value will be a JSON object with two main fields, success and data. The data field will also be a JSON object with a single key-value pair. The key will usually be the object’s UID, but if the request was made with the object’s name, then the key will also be the name.
{ "success": true, "data": { "7ad57…73e4a1f4": { … object data … }}}
By default, GET
operations will return all of the object’s information: the UID, the name, and all
object-specific fields and sub-fields. The client is expected to provide any filtering of data that
might be needed.
If the request is unsuccessful, then a reason field will be returned with more information on why the request failed.
{ "success": false, "reason": "No node found for ID=n123" }
Update Object¶
There are two related update methods: PATCH
and PUT
. When using the PATCH
method, the
request is assumed to modify only those fields that are sent in the request – any other fields in
the object will be left as-is. The PUT
method assumes that the entire object should be overwritten
by the new data – any fields in the request will be overwritten, and any fields not in the request will
be removed or set to default values. Not all object-types allow for PUT
operations, and note that
a bad PUT
call could irreversibly damage the object if some fields are wiped out.
To update the "description"
field of a node with PATCH
:
curl -X PATCH https://head1.cluster.local/api/v1/node/UID --data \
'{"description":"this is a new description"}' -H "Authorization: Bearer \
eyJhbGciOiJIUzI1Ni…"
The return value will simply indicate success or failure:
{"success": true}
In this example, success would indicate that ONLY the "description"
field has been modified.
On failure, a "reason"
field will give more information on why the request failed:
{"success": false, "reason": "Unhandled parameter(s): ..."}
Delete Object¶
The DELETE
method will permanently remove an object from ClusterWare – there is no way to recover
the object’s data once it has been deleted.
To delete an Image from the system:
curl -X DELETE https://head1.cluster.local/api/v1/image/DefaultImage -H \
"Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
The return value will simply indicate success or failure:
{"success": true}
On failure, a “reason” field will give more information on why the request failed:
{"success": false, "reason": "No image found for ID=DefaultImage"}
Metadata Information¶
All objects have a metadata endpoint off of their object-class (pluralized) endpoint
(for example, /nodes/meta
). This endpoint will return more detailed information about the fields available
in that object-class.
Note that this is a public endpoint and does not need any authentication token to be accessed.
curl -X GET https://head1.cluster.local/api/v1/nodes/meta
It will return a JSON object that includes a list of fields. Each field in the list will include a
path
field (the chain of keys to get to that field), summary
, source
(where the data
comes from), and a format
(what kind of data it is).
Admin Objects¶
Admin objects are used to give explicitly specified users access to ClusterWare functionality. Regular HPC users do not need to have Admin objects created for them - this is solely for those who will do administrative or managerial tasks on the cluster.
To create an Admin, the only required data is a name. This must match the username of the user
on the underlying operating system. If additional user-data is required, like a full name or
department affiliation, it should be stored inside the "description"
field.
When issuing requests, the UID
field in the URL can be either the actual UID of the object or
the name of the object as given in the "name"
field. Thus, once a user, user1
, has been created,
it can be referenced through /admin/user1
or /admin/<UID>
.
Data Fields¶
Admin objects have several fields:
name
Required: The name of the user on the underlying system description
Optional: A text string with descriptive information
roles
Optional: A comma-separated list of ClusterWare roles; while optional, if a user
does not have any roles assigned, they will not be able to take any
actions; note that PATCH operations on the “roles” field will
overwrite the entire field, there is no way to append or extend the
list of roles
keys
Optional: A list of one or more ssh keys
gui_settings
Optional: Used internally by the ClusterWare GUI; it should not be modified
by end-users
Additional Endpoints¶
Several endpoints can be used to modify the gui_settings
field. Where the standard PATCH
actions can update just the gui_settings
field, it must update the entire object; these
actions allow finer-grained updating of individual keys in that object. Note that this field is
used internally by the ClusterWare GUI and admins should not need to modify it directly.
GET /admin/<UID>/gui_settings
PATCH /admin/<UID>/gui_settings
DELETE /admin/<UID>/gui_settings
Several endpoints can be used to update or delete the list of SSH keys that have been stored for the admin.
POST /admin/<UID>/keys
PUT /admin/<UID>/keys
DELETE /admin/<UID>/keys
Similar to the token-refresh process, there is an endpoint that allows an admin to make a new token for use by other tools or automated processes; optional fields can be included in the request:
POST /admin/<UID>/newtoken timeout: integer; duration for the newly made token
Example¶
First, create a new admin:
curl -X POST https://head1.cluster.local/api/v1/admins --data '{"name":"admin2"}' \
-H "Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": "d763705495c3423083ae35f0850da018"}
Get the details on that Admin record:
curl -X GET https://head1.cluster.local/api/v1/admin/d763705495c3423083ae35f0850da018 \
-H "Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": {"name": "admin2", "roles": ["role.authuser", \
"role.fulladmin"], "last_modified": 1721850600.3619504, "last_modified_on": \
"head23.cluster.local", "last_modified_by": "admin1", "uid": \
"d763705495c3423083ae35f0850da018"}}
Update the record to include a description (switching to “admin2” in the URL):
curl -X PATCH https://head1.cluster.local/api/v1/admin/admin2 --data \
'{"description":"John Doe, HPC admin"}' -H "Authorization: Bearer \
eyJhbGciOiJIUzI1Ni…"
{"success": true}
Update the list of roles to be just “role.authuser”:
curl -X PATCH https://head1.cluster.local/api/v1/admin/admin2 --data \
'{"roles":["role.authuser"]}' -H "Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true}
While the PATCH
request only updates that one field, leaving other fields as-is, the update to
that field will overwrite the old data. There is no way to append or add to the list of roles.
Verify the new data:
curl -X GET https://head1.cluster.local/api/v1/admin/admin2 -H \
"Authorization: Bearer eyJhbGciOiJIUzI1Ni…”
{"success": true, "data": {"name": "admin2", "roles": ["role.authuser"], \
"last_modified": 1721851033.3245502, "last_modified_on": "head23.cluster.local", \
"last_modified_by": "admin1", "description": "John Doe, HPC admin", "uid": \
"d763705495c3423083ae35f0850da018"}}
Finally, delete the account:
curl -X DELETE https://head1.cluster.local/api/v1/admin/admin2 -H \
"Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true}
Node Objects¶
Node objects represent the computational nodes and other controllable entities inside the cluster (switches, PDUs, etc.).
When issuing requests, the UID
field in the URL can be either the actual UID of the object,
the name of the object as given in the "name"
field, the MAC address, or the IP address. Thus,
once a user, user1
, has been created, it can be referenced through /admin/user1
or
/admin/<UID>
.
Data Fields¶
Node objects can have several fields:
name
Assigned by ClusterWare; the name is computed from the naming pool pattern and
the node’s index (which is also computed based on that pool’s membership)
description
Optional: A text string with descriptive information
type
Optional: Defaults to ‘compute’, can be one of ('unknown','compute','head',
'simulated')
mac
Required: Every node must have a MAC address
attributes
Optional: A set of key-value pairs that are assigned to the node and may be used
when configuring the node at boot-time
groups
Optional: An ordered list of Attribute Groups that this node belongs to;
attributes from each group will be applied (overwritten) based on the
order of the groups
naming_pool
Optional: A naming pool may be assigned and used to calculate the
name, index, and IP address of the node
index
Assigned by ClusterWare; the index (integer) is computed by ClusterWare based on
the naming pool
ip
Assigned by ClusterWare; the IP address is computed by ClusterWare based on the
naming pool
power_uri
Optional: The URI of the node’s BMC or IPMI controller; the power_uri can be a
template with bracketed fields that are substituted with the node’s
attribute, status, or hardware values (see examples below)
redfish_uri
Optional
Additional Endpoints¶
Several endpoints provide finer-grained access to the list of Attribute Groups that the node belongs
to. For example, POST /node/<UID>/groups
allows appending one or more groups to the current list.
To completely replace the list of groups, use the PATCH /node/<UID>
action with the groups
key.
GET /node/<UID>/groups
Returns a list of Attribute Groups (UIDs) that the node belongs to
POST /node/<UID>/groups
Accepts one key or a list of keys representing Attribute Groups that will be
appended to the current list
DELETE /node/<UID>/groups
Accepts one key or a list of keys representing Attribute Groups that will be
removed from the current list of Attribute Groups
Several endpoints provide finer-grained access to the list of attributes assigned to this specific node.
Issuing a POST /node/<UID>/attributes
action will append one or more groups to the current list.
To completely replace the attributes, use the PATCH /node/<UID>
action with the attributes
key.
Note that nodes will inherit attributes from all groups that they belong to, and will then overwrite
them with any node-specific attributes.
GET /node/<UID>/attributes
Returns a JSON object for all of the attributes (key-value pairs) for this node;
these may have assigned specifically to this node or may have been inherited from
any of the Attribute Groups that it belongs to
PUT /node/<UID>/attributes
Replaces the current set of node-specific attributes with the sent data; note
that if a key is removed from the current set, it may still be inherited from a
joined Attribute Group
PATCH /node/<UID>/attributes
Updates the current set of node-specific attributes with the sent data; these
values will take precedence over any joined Attribute Groups
DELETE /node/<UID>/attributes
Accepts one key or a list of keys to be removed from the node-specific attributes;
note that if an attribute is set by an Attribute Group, it will still be present
in the node’s overall list of attributes (until it is removed from that Attribute
Group or the node leaves that group)
Several endpoints are designed for power control functionality. The power_uri
field is needed for
deeper power control functions. For example, a power-off action will attempt to execute a graceful shutdown,
but if that fails it will fallback to an IPMI or BMC power-off.
GET /node/<UID>/power_uri
Returns a JSON object with “parsed” and “unparsed” keys; the “unparsed” key
contains a single URI that can be used to connect to the power control unit; the
“parsed” key contains an object with fields representing the server, path, etc.
that have been parsed from the URI
GET /node/<UID>/power_state
Returns the power state of the node: on, off, unknown
PUT /node/<UID>/power_state
Accepts an object with “state” and “force” fields (all optional); “state” is one
of: power on, power off; “force” is True or False. There is an advanced option,
“steps”, which allows for more control over the sequence of power-control attempts
(for example, hard versus soft power-off) – contact Penguin Solutions for more
information.
Several endpoints are used for the node status and hardware reporting system. Note that this is separate from the ClusterWare Monitoring and Alerting system; this data is kept inside the ClusterWare database and can be used in various templates and node-selectors. The specific values to be found in status and hardware can be configured using a plugin system. More information on monitoring and the plugin system can be found in the ClusterWare Admin and Reference Guides.
GET /node/<UID>/status
Returns a JSON object with the node’s status information – this can be a sizeable
set of data (several KB); with default plugins, status will include things like
load average (load_avg) and memory usage (ram_free) as well as a list of the
loaded packages and modules and many more.
POST /node/putstatus
Accepts a JSON object with a “uid” field (required) and “status” and/or “hardware”
keys; the “status” or “hardware” keys are JSON objects containing the actual data.
This endpoint is intended to be used by ClusterWare tools to update node status
information.
POST /node/putattribs
Accepts a JSON object with a “uid” field (required) and a set of key-value pairs;
the key-value pairs will be added to the node’s current attributes. This endpoint
is intended to be used by ClusterWare tools to update node attribute information.
Related to the above, the following two endpoints are used by the compute nodes to update information on the ClusterWare head nodes. These endpoints do not use token-based authentication, but instead look at the IP-address of the incoming connection to determine which node is being updated.
Caution
Improper use of these endpoints could corrupt the ClusterWare node information, which could lead to improper functioning of Dynamic Groups, node selectors, and the Publish-Subscribe system. Contact Penguin Solutions for more information.
PUT /node/putstatus
Accepts a JSON object with “status” and/or “hardware” keys, each of which is a
JSON object containing the actual data; unlike the POST version of this endpoint,
there is no “uid” key needed with the PUT operation
PUT /node/putattribs
Accepts a JSON object with key-value pairs; these key-value pairs will be added
to the node’s attributes; unlike the POST version of this endpoint, there is no
“uid” key needed with the PUT operation
To interact with the nodes, including running commands on them, several endpoints can be used:
PUT /node/<UID>/exec
Accepts a JSON object with “cmd” (required) and an optional “stdin” key; if
“stdin” is sent, it will be used as the standard input for an interactive command;
the output will be an octet-stream with the output from the command. Note that
this output format is different from other ClusterWare commands – there are no
“success” or “data” keys, just the raw data from the command.
Example¶
Create a new node:
curl -X POST https://head1.cluster.local/api/v1/nodes --data \
'{"mac":"11:22:33:44:55:66"}' -H "Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": "341b9947f6e644b78f6d88f5d7f898f4"}
Verify the node’s data using the returned UID:
curl -X GET https://head1.cluster.local/api/v1/node/341b9947f6e644b78f6d88f5d7f898f4 \
-H "Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": {"mac": "11:22:33:44:55:66", "attributes": \
{"_boot_config": "DefaultBoot"}, "index": 3, "ip": "192.168.122.103", \
"type": "compute", "last_modified": 1721997178.5100713, "last_modified_on": \
"head23.cluster.local", "last_modified_by": "admin1", "uid": \
"341b9947f6e644b78f6d88f5d7f898f4", "groups": [], "hardware": {}, \
"power_uri": null, "name": "n3", "hostname": "n3", "domain": "cluster.local"}}
Since Nodes can be referenced by name or MAC address, the same information can be found using:
curl -X GET https://head1.cluster.local/api/v1/node/11:22:33:44:55:66 -H \
"Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
And now that the node name is known, the same information can be found with:
curl -X GET https://head1.cluster.local/api/v1/node/n3 -H "Authorization: Bearer \
eyJhbGciOiJIUzI1Ni…"
Set attributes on the node itself (not through an Attribute Group):
curl -X PATCH https://head1.cluster.local/api/v1/node/n3/attributes --data \
'{"ipmi_user":"service", "ipmi_pass":"servicepass"}' -H "Authorization: \
Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true}
Verify the new data, grabbing just the attributes (not the whole node record):
curl -X GET https://head1.cluster.local/api/v1/node/n3/attributes -H \
"Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": {"_boot_config": "DefaultBoot","ipmi_user": "service", \
"ipmi_pass": "servicepass"}}
Setting the power_uri using the attributes in the template
curl -X PATCH https://head1.cluster.local/api/v1/node/n3 --data \
'{"power_uri":"ipmi://<ipmi_user>:<ipmi_pass>@10.10.1.3/ipmi"}' \
-H "Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true}
Verify the power_uri and its substitutions
curl -X GET https://head1.cluster.local/api/v1/node/n3/power_uri -H \
"Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": {"unparsed": "ipmi://service:servicepass@10.10.1.3/ipmi", \
"parsed": {"scheme": "ipmi", "schemes": "", "server": "10.10.1.3", "path": \
"ipmi", "server_username": "service:servicepass", "username": null, \
"password": null, "host": "ipmi"}}}
Notice that the text strings “<ipmi_user>” and “<ipmi_password>” have been substituted for the values
from the node’s attributes. To get the un-substituted value for the power_uri, simply use the
GET /node/<UID>
endpoint.
To determine the power state of the node:
curl -X GET https://head1.cluster.local/api/v1/node/n3/power_state -H \
"Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": "on"}
Note that if the node is unreachable via its primary or management network, it may take a while for the system to determine that the node is down just due to standard network timeouts.
To power off the node:
curl -X PUT https://head1.cluster.local/api/v1/node/n3/power_state --data \
'{"state":"power off"}' -H "Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true}
Attribute-Group Objects¶
An Attribute Group object represents a set of attributes that will be attached to a node based on its membership in the group. A node can be a member of several groups, arranged in a hierarchical list. For example, a node that is a member of group1 and group2 will inherit group1’s attributes, which may then be overwritten by group2’s attributes.
When issuing requests, the UID
field in the URL can be either the actual UID of the object or the
name of the object as given in the “name” field.
Data Fields¶
The Attribute Group fields are:
name
Required: The name for the group
description
Optional: A text string with descriptive information
attributes
Optional: A JSON-object containing key-value pairs of attributes
While the attributes
field accepts a generic JSON object, it can only reference one level into that
key-value store.
Additional Endpoints¶
Several endpoints can be used to directly manipulate the attribute key-value store instead of going
through the Attribute object first. The PATCH /attribs/<UID>
command allows for overwriting the
entire attributes
field, but cannot be used to add or append attributes one at a time.
The PATCH /attribs/<UID>/attributes
endpoint allows for that kind of direct update.
GET /attrib/<UID>/attributes
Returns a JSON object containing the key-value pairs
PUT /attrib/<UID>/attributes
Replaces the current set of key-value pairs with the sent data; any keys not in
the sent data will be removed from the Attribute Group
PATCH /attrib/<UID>/attributes
Updates the current set of key-value pairs with the sent data; only the keys that
are sent will be modified in the Attribute Group’s data; any other keys will be
left as-is
DELETE /attrib/<UID>/attributes
Accepts one key or a list of keys to be removed from the Attribute Group’s data;
note that a node can still show that attribute key as present if a node-specific
attribute has been set, or if the node is joined to another Attribute Group where
it is set
Example¶
Create a new Attribute Group:
curl -X POST https://head1.cluster.local/api/v1/attribs --data '{"name":"MyAttribs"}' \
-H "Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": "5997e993e0bb49568bef18536614b733"}
Read the basic information:
curl -X GET https://head1.cluster.local/api/v1/attrib/MyAttribs -H \
"Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": {"name": "MyAttribs", "last_modified": 1721852251.1698143, \
"last_modified_on": "head23.cluster.local", "last_modified_by": "admin1", \
"uid": "5997e993e0bb49568bef18536614b733", "attributes": {}}}
Update the attributes key-value store through the main record:
curl -X PATCH https://head1.cluster.local/api/v1/attrib/MyAttribs --data \
'{"attributes":{"foo":"bar"}}' -H "Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true}
Verify that the update worked:
curl -X GET https://head1.cluster.local/api/v1/attrib/MyAttribs -H \
"Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": {"name": "MyAttribs", "last_modified": 1721852433.4113355, \
"last_modified_on": "head23.cluster.local", "last_modified_by": "admin1", \
"attributes": {"foo": "bar"}, "uid": "5997e993e0bb49568bef18536614b733"}}
To get just the attributes and not the whole record:
curl -X GET https://head1.cluster.local/api/v1/attrib/MyAttribs/attributes -H \
"Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": {"foo": "bar"}}
Directly manipulate the attributes key-value store to add new data:
curl -X PATCH https://head1.cluster.local/api/v1/attrib/MyAttribs/attributes --data \
'{"abc":"def"}' -H "Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true}
Verify the new data:
curl -X GET https://head1.cluster.local/api/v1/attrib/MyAttribs/attributes -H \
"Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": {"foo": "bar", "abc": "def", "last_modified": \
1721852648.6145608, "last_modified_on": "533a8c21fd5642c38138214d7ad783ae", \
"last_modified_by": "admin1"}}
Directly delete one key out of the key-value store (send a list of keys to delete):
curl -X DELETE https://head1.cluster.local/api/v1/attrib/MyAttribs/attributes --data \
'["abc"]' -H "Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true}
And verify that the key is gone:
curl -X GET https://head1.cluster.local/api/v1/attrib/MyAttribs/attributes -H \
"Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": {"foo": "bar", "last_modified": 1721852648.6145608, \
last_modified_on": "533a8c21fd5642c38138214d7ad783ae", "last_modified_by": \
"admin1"}}
To delete the object entirely:
curl -X DELETE https://head1.cluster.local/api/v1/attrib/MyAttribs -H \
"Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true}
Boot Config Objects¶
A Boot Config object represents a set of information used to boot up a node from power-on to a running OS image on the node. It may include specific command-line parameters for the booting node, a “boot style” (for example, ram-based image or disked image), kickstart files, etc.
When issuing requests, the UID
field in the URL can be either the actual UID of the object or the
name of the object as given in the “name” field.
Data Fields¶
The Attribute Group fields are:
name
Required: The name for the Boot Config
kernel
Required: This is the kernel (file) being used by the Boot Config; note that since
this requires a large file to be uploaded, the standard POST/PATCH endpoints will
not work to update the kernel - additional endpoints are provided for handling
these files
initramfs
Required: This is the initramfs (file) being used during the early boot phases;
note that since this requires a large file to be uploaded, the standard POST/PATCH
endpoints will not work to update the initramfs - additional endpoints are provided
for handling these filesdescription
Optional: A text string with descriptive information
frozen
Optional: A True/False indicator that allows admins to block changes to the boot
config; note that is intended as a protection against accidents, not
against malicious attacks, since one can simply set frozen=False and
then make changes.
cmdline
Optional: Command-line to be used when booting the operating system; this may
include options for SELinux enforcement or power-control
image
Optional: A UID or name for a ClusterWare Image object (see below); note that
ClusterWare stores this as a UID, but will accept a UID or name when
creating or updating the Boot Config
boot_style
Optional: A string representation of the type of boot-up process being used, one
of: ('rwram','roram','iscsi','next','disked','sanboot','live'); the
default is “rwram” and indicates a node that will be booted into a
ram-based image that readable and writable
repo
Optional
kickstart
Optional: Indicates the kickstart file to be used for disk-based installations
that are using Kickstart; this should be a file that has been copied
or created in the /opt/scyld/clusterware/kickstarts directory.
Additional Endpoints¶
Additional object-class endpoints are available:
GET /bootconfigs/errors
Will check all Boot Config entries that they have valid data, that any referenced
images or files are present, etc.; returns a JSON object with a “success” field;
if an error occurs, a “reason” field will give more information on why it failed
GET /bootconfigs/mkiso
Accepts a JSON object with “uid” and “image” keys, and will create and download a
bootable ISO image. This is an advanced feature, please contact Penguin Solutions
for more information.
As mentioned earlier, the kernel and initramfs may be large files and thus must be uploaded separately – they cannot be “updated” with the standard POST/PATCH actions. To interact with these files, use the following endpoints:
GET /bootconfig/<UID>/kernel
Returns a file containing the kernel being used by this Boot Config. Note that
the output format is different from other ClusterWare commands – there are no
“success” or “data” keys, just the binary data of the file being requested.
PUT /bootconfig/<UID>/kernel
Replaces the current kernel file with the uploaded file
DELETE /bootconfig/<UID>/kernel
Deletes the kernel file associated with this Boot Config; in multi-head
configurations, the file will be deleted from all heads automatically
GET /bootconfig/<UID>/initramfs
Returns a file containing the initramfs being used by this Boot Config. Note that
the output format is different from other ClusterWare commands – there are no
“success” or “data” keys, just the binary data of the file being requested
PUT /bootconfig/<UID>/initramfs
Replaces the current initramfs file with the uploaded file
DELETE /bootconfig/<UID>/initramfs
Deletes the initramfs file associated with this Boot Config; in multi-head
configurations, the file will be deleted from all head nodes automatically
For kickstart-based deployments, the kickstart file can be a template that uses “<variable>” syntax to substitute values from the node. To retrieve the parsed and substituted kickstart file, use the following endpoint. Unlike kernel and initramfs files, kickstart files are NOT automatically synchronized across head nodes – admins must manually copy the file from one head node to the others.
GET /bootconfig/<UID>/kickstart
Returns the parsed and substituted kickstart file; the output format is
different from other ClusterWare commands – there are no “success” or “data”
keys, just the (text) data of the file being requested.
Since Boot Configs are critical to the operation of the cluster, an endpoint can be used to check that the required data is available and valid. For example, to check that the image file being used is actually present:
GET /bootconfig/<UID>/errors
Checks that entries in the boot config are valid and return a JSON object
with a “success” field; if an error occurs, a “reason” field will give more
information on why it failed
An endpoint is provided to export a Boot Config for backup or sharing:
GET /bootconfig/<UID>/export
This is an advanced feature, please contact Penguin Solutions for more
information
Example¶
Create a new Boot Config, using an existing DefaultImage
as the base image:
curl -X POST https://head1.cluster.local/api/v1/bootconfigs --data \
'{"name":"NewBoot","image":"DefaultImage"}' -H \
"Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": "ed31013d670745139681c46cf657ed40"}
Note that the image can be referenced by UID or, as shown here, by name. Verify the data:
curl -X GET https://head1.cluster.local/api/v1/bootconfig/NewBoot -H \
"Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": {"name": "NewBoot", "image": "DefaultImage", \
"last_modified": \1721921837.5399132, "last_modified_on": "head23.cluster.local", \
"last_modified_by": "admin1", "uid": "ed31013d670745139681c46cf657ed40"}}
Set it to be "frozen"
so that future changes cannot be made:
curl -X PATCH https://head1.cluster.local/api/v1/bootconfig/NewBoot --data \
'{"frozen":true}' -H "Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true}
Now that it is frozen, attempt to modify the "description"
field:
curl -X PATCH https://head1.cluster.local/api/v1/bootconfig/NewBoot --data
'{"description":"new description"}' -H "Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": false, "reason": "Cannot modify frozen boot configuration."}
This Boot Config does not yet have a kernel or initramfs and thus would not be able to actually boot
any nodes yet. Using the existing DefaultBoot
(created during installation), download its kernel
and initramfs:
curl -X GET https://head1.cluster.local/api/v1/bootconfig/DefaultBoot/kernel -o \
defaultboot_kernel -H "Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
curl -X GET https://head1.cluster.local/api/v1/bootconfig/DefaultBoot/initramfs -o \
defaultboot_initramfs -H "Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
Image Objects¶
An Image object represents a file system that will be deployed onto a compute node. It is not intended to have absolutely all software that an end-user might want, but rather, a somewhat minimal set of drivers, configuration files, tools, and middleware to bring up the node. Network-mounted file systems may be used to provide additional software and libraries for end-users.
When issuing requests, the UID
field in the URL can be either the actual UID of the object or the name
of the object as given in the "name"
field.
Data Fields¶
The Attribute Group fields are:
name
Required: The name for the image
content
Required: This is the content of the file system that will be used in this Image;
since this requires a large file to be uploaded, the standard
POST/PATCH endpoints will not work to update the content - additional
endpoints are provided for handling it below
description
Optional: A text string with descriptive information
frozen
Optional: A True/False indicator that allows admins to block changes to the boot
config; this is intended as a protection against accidents, not
against malicious attacks, since one can simply set frozen=False and
then make changes.
parent
Optional: A UID or name of a “parent” Image object that the current object was
derived from; this field is for informational purposes only and is not
used during any actions (for example, changes to a parent Image are not
propagated into its children); ClusterWare stores this as a
UID, but will accept a UID or name when creating or updating the Image
distro
Optional: A UID of a distro (a Software Distribution object)
Additional Endpoints¶
As mentioned earlier, the content of an Image is a large file and thus must be uploaded separately – it cannot be “updated” with the standard POST/PATCH actions. To interact with the content file, use the following endpoints:
GET /image/<UID>/content
Returns a file containing the file system image being used by this Image object.
The output format is different from other ClusterWare commands – there
are no “success” or “data” keys, just the binary data of the file being requested
PUT /image/<UID>/content
Replaces the current content file with the uploaded file
DELETE /image/<UID>/content
Deletes the content file associated with this Image; in multi-head configurations,
the file will be deleted from all heads automatically
GET /image/<UID>/content/stat
Returns a JSON object containing statistics on the image: the file’s size (“size”)
and last modification time (“mtime”)
GET /image/<UID>/content/info
Returns a JSON object containing more detailed statistics on the image: the file’s
size (“size”), last modification time (“mtime”), checksum ("chksum"), a reference
count (“refcnt”), and the file format (“fmt”, currently “cwsquash”)
There is one additional endpoint that is used when capturing an image from a running compute node. This is an advanced feature; please contact Penguin Solutions for more information.
GET /image/{uid}/capture
Accepts a JSON object with “uid” key (required), and one or more optional keys:
“exclude”, “credentials”, “compress”.
Example¶
Create an empty image:
curl -X POST https://head1.cluster.local/api/v1/images --data '{"name":"NewImage"}' \
-H "Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": "d16d9eb8786c408ba32780ee6b722a50"}
Look at an existing Image (DefaultImage will be created at installation):
curl -X GET https://head1.cluster.local/api/v1/image/DefaultImage -H \
"Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": {"name": "DefaultImage", "distro": "CentOS", "parent": null, \
"description": "Default image generated by scyld-add-boot-config", "exports": \
{"head23.cluster.local": {"targetcli": {"category": "iscsi", "location": \
"iqn.1998-04.com.penguincomputing:cb2eeba6fe3748febbb15c7cc1cfb165"}, \
"last_modified": 1721928167.775344, "last_modified_on": "head23.cluster.local"}}, \
"content": {"cwsquash": {"size": 1222410240, "mtime": 1721919588.6732733, \
"chksum": "sha1:7e24ac56d109394755302377c9226fa111aae45d", "filename": \
"486c1857bd214d3fad56dea1399b6440", "uid": "486c1857bd214d3fad56dea1399b6440"}, \
"last_modified": 1721919589.1442792, "last_modified_on": "head23.cluster.local", \
"last_modified_by": "admin1"}, "last_modified": 1721919581.66072, \
"last_modified_on": "head23.cluster.local", "last_modified_by": "admin1", \
"uid": "cb2eeba6fe3748febbb15c7cc1cfb165"}}
Look into the details statistics for the image:
curl -X GET https://head1.cluster.local/api/v1/image/DefaultImage/content/info \
-H "Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": {"size": 1222410240, "mtime": 1721919588.6732733, "chksum": \
"sha1:7e24ac56d109394755302377c9226fa111aae45d", "refcnt": 1, "fmt": "cwsquash"}}
Dynamic Group Objects¶
Where Attribute Groups require intentional effort to join or leave, Dynamic Groups (DynGroups) are a way to group nodes based on shared or common attributes, status, or hardware information. DynGroups also do not alter a node’s attributes, so they are most useful in targeting an action at a group of similar nodes.
When issuing requests, the UID
field in the URL can be either the actual UID of the object or the name
of the object as given in the "name"
field.
Data Fields¶
The DynGroups fields are:
name
Required: The name for the Dynamic Group
selector
Required: A string representing a node-selector function (see below)
description
Optional: A text string with descriptive information
A node-selector function is a logical function that is computed based on a given node’s information.
Since a node’s boot configuration is set in the _boot_config
attribute, the following will select all
nodes that using DefaultBoot
:
a[_boot_config]=="DefaultBoot"
the a[..]
means to look up a nodes attribute, similarly h[..]
can be used for hardware and s[..]
for
status. The amount of total memory on a node is given in the hardware information, under the ram_total
key:
h[ram_total] > 100000
will give the set of nodes with more than 1000000 bytes of memory.
More information on the node-selector language can be found in the ClusterWare Admin and Reference Guides.
Additional Endpoints¶
To find the set of nodes that are currently in a given DynGroup, use the following endpoint:
GET /dyngroup/<UID>/nodes
Returns a JSON object with a list of node UIDs; if no nodes are currently in the
dynamic group, an empty list will be returned
Example¶
Create a dynamic group:
curl -X POST https://head1.cluster.local/api/v1/dyngroups --data \
'{"name":"BigMemory","selector":"h[ram_total] > 100GB"}'
-H "Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": "b30886d9c8ca40d99d66b668074811b1"}
Verify the group’s information:
curl -X GET https://head1.cluster.local/api/v1/dyngroup/BigMemory -H \
"Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": {"name": "BigMemory", "selector": "h[ram_total] > 100GB", \
"parsed": "(hardware[\"ram_total\"] > 100GB)", "last_modified": 1721930148.843629, \
"last_modified_on": "head23.cluster.local", "last_modified_by": "admin1", \
"uid": "b30886d9c8ca40d99d66b668074811b1"}}
Get the list of nodes currently in this DynGroup:
curl -X GET https://head1.cluster.local/api/v1/dyngroup/BigMemory/nodes -H \
"Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": ["199eadbea2084b80a4efcf445538efc5", \
"d3b59618750e4957bc3139a0a29cb1a8", "4343fc9a431d49e89639b8cf3644db9a", \
"9e831349cbcf484f8db075e12ef4dd9d", "35d6faece6a7411cb26a7c7b02fda708"]}
Delete the DynGroup:
curl -X DELETE https://head1.cluster.local/api/v1/dyngroup/BigMemory -H \
"Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true}
Naming Pool Objects¶
Naming Pools provide a mechanism to tie groups of nodes together through a common naming scheme, like n001 through n100. There is a default naming scheme that nodes will be assigned into; alternatively, when creating a node, it can be directly inserted into an existing Naming Pool.
In addition to naming the nodes according to a pattern, the Naming Pool can also provide offsets to IP addresses or include nodes into specified network segments.
When issuing requests, the UID
field in the URL can be either the actual UID of the object or the name
of the object as given in the "name"
field.
Data Fields¶
The Naming Pool fields are:
name
Required: The name for the Dynamic Group
pattern
Required: A string representing a naming pattern; a pattern may have one or more
letters followed by a set of curly-braces followed by another one or
more letters (see below)
description
Optional: A text string with descriptive information
first_index
Optional: Sets the first index for nodes added to this pool; default is 0
ip_base
Optional: Sets a base IP address for the first node in the pool; default is empty
(use the next available address in the default network)
ip_offset
Optional: Sets an offset for the IP address of the first node in the pool; default
is empty (use the next available address in the default network)
network
Optional: Sets the Network to use when setting IP addresses
group
Optional: Sets an Attribute Group object that all nodes in this pool will inherit
from; any node added to the pool will automatically be assigned the
attributes of this group (unless other Attribute Groups are assigned)
parent
Optional: Sets a parent Naming Pool for nested pools
There are several options for how naming pool patterns may be constructed:
pattern=”n{}”
This is the default, and indicates that nodes will be named “n0” and up; note
that in such a pattern, the name length is not constant which may lead to output
formatting errors (i.e. “n0” versus “n100” will lead to a 2 character offset)
pattern=”gpu{:03d}”
Will give names like gpu000, gpu001, gpu002, etc.; the “:03d” is formatted,
zero-padded, 3 digits
Additional Endpoints¶
Several additional endpoints are available:
GET /namingpools/info/<NODE>
For a given node, NODE, the system will reply with the naming pool information
used when naming that node
PUT /namingpool/<UID>/push
Used to push node names to be updated; this is an advanced feature, please contact
Penguin Solutions for more information.
Example¶
Create a naming pool:
curl -X POST https://head1.cluster.local/api/v1/namingpools --data \
'{"name":"gpu","pattern":"gpu{}"}' -H "Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": "1049f3b2f2d744f088a4ee6cc3ecfc91"}
Check on a node’s naming pool:
curl -X GET https://head1.cluster.local/api/v1/namingpools/info/gpu0 \
-H "Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": {"index": 0, "pattern": "gpu{}"}}
Software Repository Objects¶
Software Repository objects (repos) are used to collect information about an upstream or local repository for software packages.
When issuing requests, the UID
field in the URL can be either the actual UID of the object or the name of
the object as given in the "name"
field.
Data Fields¶
Admin objects have several fields:
name
Required: The name of the user on the underlying system
description
Optional: A text string with descriptive information
full_name
Optional: A text string for identifying the repos
urls
Optional: A list of URLs for the repos
mirrors
Optional: A list of mirror URLs for the repos
disable
Optional: A list of True/False flags for the URLs
keys
Optional: A list of keys for the URLs
check
Optional
rhel_entitlement
Optional: RedHat license entitlement key
Additional Endpoints¶
For locally hosted repos, several endpoints can be used to investigate the ISO:
GET /repo/<UID>/iso
Downloads the ISO image for this repo. Note that the output format is different
from other ClusterWare commands – there are no “success” or “data” keys, just the
binary data of the ISO file being requested
PUT /repo/<UID>/iso
Uploads an ISO for this repo
DELETE /repo/<UID>/iso
Deletes the ISO for this repo; note that the repo's object itself will remain,
just the ISO will be deleted
GET /repo/<UID>/iso/stat
Returns basic statistics about the ISO file
Software Distribution Objects¶
Software Distribution objects (distros) are used to collect information about a software distribution. For example, which repos hold packages and what packaging scheme is used.
When issuing requests, the UID
field in the URL can be either the actual UID of the object or the name of the
object as given in the "name"
field.
Data Fields¶
Admin objects have several fields:
name
Required: the name of the user on the underlying system
description
Optional: A text string with descriptive information
repos
Optional: A list of one or more Software Repository objects
packaging
Optional: A string representing the packaging scheme: rpm, deb, apk; if it cannot
be inferred from other data, “rpm” will be assumed
release
Optional: A string representing the name of the release
Additional Endpoints¶
There are no additional endpoints for distros; the basic operations all function as expected.
For example, GET /distro/<UID>
will return information about the distro.
Network Objects¶
Network objects are used to collect information about network subnets that can be used for deploying compute nodes.
When issuing requests, the UID
field in the URL can be either the actual UID of the object or the name of the
object as given in the "name"
field. For Networks the name field is optional, so using the UID may
be the most reliable approach.
Data Fields¶
Network objects have several fields:
first_ip
Required: The starting IP address for this network
ip_count
Required: (Integer) number of IP addresses that may be assigned on this subnet
mask_bits
Required: (Integer) number of bits for the network mask
name
Optional: The name of the user on the underlying system
description
Optional: A text string with descriptive information
first_index
Optional: (Integer) number for the first index of the nodes in this network
router_ip
Optional: The IP address for the router on this network
gateway_ip
Optional: The IP address for the gateway on this network
domain
Optional: The domain name to be set for this network
node_iface
Optional: Network interface used during booting
Additional Endpoints¶
There are several additional endpoints for networks:
GET /nets/byiface/<PART>
This endpoint is deprecated and will be removed in a future release; returns a
JSON object with a list of networks that reference the interface name, NAME;
full or partial matches are returned
GET /nets/byname/<NAME>
Returns a JSON object with a list of networks that reference the network name, NAME;
full or partial matches are returned
GET /nets/byip/<IPADDR>
Returns a JSON object with a list of networks that reference the partial or full
IP address, IPADDR
GET /nets/bykey/<PART>
Returns a JSON object with a list of networks that reference the partial or full
UID, PART
Git Repository Objects¶
Git Repository objects (gitrepos) are used to create and manage locally hosted Git repositories, which may be useful for automated configuration systems.
When issuing requests, the UID
field in the URL can be either the actual UID of the object or the name of the
object as given in the "name"
field.
Data Fields¶
Admin objects have several fields:
name
Required: The name of the user on the underlying system
description
Optional: A text string with descriptive information
public
Optional
url
Optional: A URL for the git repos that will be used for synchronization; note that
either “url” or “upstream” can be defined, but not both
upstream
Optional: A URL for an upstream git repos that will be used for synchronization;
note that either “url” or “upstream” can be defined, but not both
branch_map
Optional: A list of local-to-remote branch mappings
sync_period
Optional: Time between synchronization events for this gitrepos; can be a number
(seconds) or a string of the form “10m”, “2h”, “1d” for minutes, hours,
or days, respectively
Additional Endpoints¶
For gitrepos, several endpoints are available:
GET /gitrepo/{uid}/url
Returns a URL string that can be used to clone the gitrepo. The output
format is different from other ClusterWare commands – there are no “success” or
“data” keys, just the URL string. This endpoint is public and does not require an
authentication token
GET /gitrepo/{uid}/repo
Returns the top-level file in the repo. The output format is different
from other ClusterWare commands – there are no “success” or “data” keys, just the
(text) file. This endpoint is public and does not require an authentication token
GET /gitrepo/{uid}/repo/<PATH>
Returns the file in the repo at location PATH. The output format is
different from other ClusterWare commands – there are no “success” or “data” keys,
just the (text) file. This endpoint is public and does not require an
authentication token
GET /gitrepo/{uid}/content
Returns the top-level file in the repo. The output format is different
from other ClusterWare commands – there are no “success” or “data” keys, just the
(text) file. This endpoint is public and does not require an authentication token
GET /gitrepo/{uid}/content/<PATH>
Returns the file in the repo at location PATH. The output format is
different from other ClusterWare commands – there are no “success” or “data” keys,
just the (text) file. This endpoint is public and does not require an
authentication token
GET /gitrepo/{uid}/sync
While this is a GET operation, it accepts a JSON object payload with an “action”
key (required) and “branchmap” key (optional); action should be one of: 'status',
'checkout', 'reset', 'pull', 'rebase'
POST /gitrepo/{uid}/sync
Accepts a JSON object with an “action” key (required) and a “branchmap” key
(optional); action should be one of: 'status', 'checkout', 'reset', 'pull',
'rebase'
GET /gitrepo/{uid}/branches
While this is a GET operation, it accepts a JSON object with optional keys:
branchmap, all, filter; the branchmap is a list of branches to get information
about, the all parameter is True/False, and filter allows for more arbitrary
filtering of the gitrepos list
DELETE /gitrepo/{uid}/branches
Accepts a JSON object with one or more optional keys: “branches” (a list of
branches to delete) or “all” (True/False, delete all branches in the gitrepos)
Hostname Objects¶
ClusterWare runs an DNS service to handle the name records needed for compute nodes and that service can be
extended to provide other hostname records as well. If a hostname record
includes a MAC address, then
lusterWare will include it in its DHCP service.
When issuing requests, the UID
field in the URL can be either the actual UID of the object or the name of the
object as given in the "name"
field.
Data Fields¶
name
Required: the name for the host
type
Required: a string representing the type of DNS record this will be: arec (IPv4),
aaaarec (IPv6), or srvrec (service)
description
Optional: a text string with descriptive information
ip
Required for arec and aaaarec: the IP address associated with this name
mac
Optional for arec and aaaarec: the MAC address associated with this name; if no
mac is given, then DHCP will not be configured for this host
target
Required for srvrec: the target server that is running this service
port
Required for srvrec: the port that the service is running on
service
Optional for srvrec: the service name for this SRV record, defaults to the name
of the record
proto
Optional for srvrec: the protocol that the service uses: tcp or udp
weight
Optional for srvrec: the “weight” given to this SRV record; if multiple SRV records
exist for the same target, the higher weight will be preferred
priority
Optional for srvrec: the “priority” given to this SRV record; if multiple SRV
records exist for the same target, the higher priority will be preferred
domain
Optional for srvrec: the domain portion of the FQDN; if not specified, it will
default to whatever the ClusterWare head node is configured with
Additional Endpoints¶
An additional endpoint is provided to search the hostnames by UID:
GET /hostnames/bypart/<PART>
A partial UID can be sent in <PART> and the system will return a list of all
hostname UIDs that match that partial UID
Example¶
Create a hostname record:
curl -X POST https://head1.cluster.local/api/v1/hostnames --data \
'{"name":"nfsserver","ip":"10.1.1.10"}' \
-H "Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": "e921725181c741fba6f4ec8a027a432f"}
Verify the record’s contents:
curl -X GET https://head1.cluster.local/api/v1/hostname/nfsserver -H \
"Authorization: Bearer eyJhbGciOiJIUzI1Ni…"
{"success": true, "data": {"type": "arec", "name": "nfsserver", "ip": "10.1.1.10", \
"last_modified": 1721931565.353962, "last_modified_on": "head23.cluster.local", \
"last_modified_by": "admin1", "uid": "e921725181c741fba6f4ec8a027a432f"}}
Cluster-wide Endpoints¶
There are a number of endpoints dedicated to cluster-wide information, or ClusterWare configuration information:
GET /cluster
Returns a JSON object with detailed information about the cluster, including the
current time on the cluster, the monitoring and authentication configuration,
image formats, plugins, etc.
PATCH /cluster
Accepts a JSON object with one or more key-value pairs; for each key, the
corresponding entry in the cluster database is overwritten; keys may be:
- default_group (change the default group that nodes are assigned to)
- naming (change the default naming scheme)
- accept_new_nodes (whether the cluster will attempt to boot nodes that have
not be previously defined)
- default_distro (change the default distro)
- influx_token (change the token used by InfluxDB and Grafana, parts of the
ClusterWare monitoring and alerting system)
- cluster_name (change the name of the cluster)
- cluster_id (change the Penguin Solutions cluster ID number)
- auth_config (change settings needed by the authentication system)
GET /cluster/database
Returns a JSON object with information about the underlying ClusterWare database.
This endpoint is public and does not require an authentication token.
GET /cluster/summary
Returns a JSON object with a list of all object UIDs for all ClusterWare object
types.
GET /cluster/usage
Returns a JSON object with cluster-wide usage information; this requires that a
cluster accounting system be configured
GET /cluster/time
Returns a JSON object with the current time on the head node. This endpoint is
public and does not require an authentication token.
GET /cluster/accountant
Returns a JSON object with the current cluster accounting configuration
PUT /cluster/accountant
Used to set the cluster accounting configuration; this is an advanced topic,
please contact Penguin Solutions for more information.
GET /cluster/head/{uid}
Returns a JSON object with information about the specified head node.
GET /cluster/head/{uid}/log
Returns a JSON object with information about logs from the specified head node.
GET /cluster/hosts
Returns a JSON object with hostname-ipaddress pairs for all known nodes in the
cluster. This endpoint is public and does not require an authentication token.
GET /cluster/sshkeys
Returns a JSON object with information about the authorized keys for the cluster.
This endpoint is public and does not require an authentication token.
GET /cluster/cabundle
Returns a JSON object with information about the CA certificates for the cluster.
This endpoint is public and does not require an authentication token.
GET /cluster/license
Returns a JSON object with information about the ClusterWare license for this
cluster.
GET /whoami
Returns a JSON object identifying the current user
GET /whereami
Returns a JSON object identifying where (what node) the current user is attaching
from; this assumes that ClusterWare knows the server (that is, it’s a compute node
registered in the system)
Head Node Endpoints¶
ClusterWare stores head nodes objects in the database to assist with management and maintenance.
Data Fields¶
Head nodes have several fields:
uid
Required: A unique ID usually configured via a file on disk (base.ini)
ssh_public
Required: The SSH public key for this head node
description
Optional: A text string with descriptive information
ca_pem
Optional: A CA certificate
Additional Endpoints¶
Several endpoints can be used to interact with the head nodes:
GET /heads/down
Returns a JSON object with a list of all currently down head nodes
DELETE /heads/down
Deletes any currently down head nodes, removing them from the cluster; returns a
JSON object with a list of head nodes that were removed
GET /head/services
Returns a list of all ClusterWare services and their current status (up or down).
This endpoint does not require an authentication token, but requires that the
connection come from another known head node
POST /head/services
accepts a JSON object with “status” and “services” keys (both required); status
must be a comma-separated list of: 'start', 'stop', 'restart', 'enable', 'disable',
'reload'; and services must be a list of one or more head node services (e.g.
from a call to GET /head/services). This endpoint does not require an
authentication token, but requires that the connection come from another known
head node
GET /head/peerurl
Returns a JSON object with the peer URL for attaching a new head to the cluster.
This endpoint is public and does not require an authentication token
GET /head/files/unused
Returns a list of all ClusterWare-managed files (images, ISOs, etc.) that are
currently unused. This endpoint does not require an authentication token, but
requires that the connection come from another known head node
DELETE /head/files/unused
Deletes any currently unused files, removing them from the cluster; returns a
JSON object with a list of files that were removed. This endpoint does not require
an authentication token, but requires that the connection come from another known
head node
GET /database/clean
Returns a JSON object with information about what a database “cleaning” would do
(but does not perform the cleaning)
POST /database/clean
Performs database cleaning on the head node and returns a JSON object with
information about what was performed
POST /database/leave
Requests that this head node leave the cluster. This endpoint does not require
an authentication token, but requires that the connection come from another known
head node
Caution
This action may cause significant disruption to a running cluster; contact Penguin Solutions for additional information or assistance.
Boot-time Support Endpoints¶
Several endpoints are designed to support low-level boot-time processes like kickstart, ztp, and ignition:
GET /kickstart/<NAME>
Returns the kickstart file with the given name; the file must already exist and
be located in the /opt/scyld/clusterware/kickstarts directory. The
output format is different from other ClusterWare commands – there are no
“success” or “data” keys, just the (text) file. This endpoint is public and does
not require an authentication token
GET /ztp/script
Returns a ZTP script or config file for a given node; the node is determined by
the incoming connection’s IP address and the node must have its “_boot_config”
attribute set to "ztp:<ZTP_SCRIPTNAME>“. The script must already exist and be
located in the /opt/scyld/clusterware/kickstarts directory. The output
format is different from other ClusterWare commands – there are no “success” or
“data” keys, just the (text) file. This endpoint is public and does not require
an authentication token
GET /ignition/bin
Returns the ignition binary for use by the booting node. The output
format is different from other ClusterWare commands – there are no “success” or
“data” keys, just the (text) file. This endpoint is public and does not require
an authentication token
GET /ignition/<UID>
Returns the ignition configuration file for the node identified by UID; the node
must have its “_ignition” attribute set to the configuration to use. That
configuration may be a URL, a git repo URL, or a locally hosted config file. The
file must already exist and be located in the /opt/scyld/clusterware/kickstarts
directory. The output format is different from other ClusterWare
commands – there are no “success” or “data” keys, just the (text) file. This
endpoint is public and does not require an authentication token
GET /install/head/scyld-install
Returns a `scyld-install` script that can be used to join a server to the current
head node. This may be useful when automating the creation of multi-head clusters.
The output format is different from other ClusterWare commands – there
are no “success” or “data” keys, just the (text) file. This endpoint is public
and does not require an authentication token
POST /install/password
Accepts a JSON object with an “admin_pass” key and value and verifies that
the password is correct for access to the ClusterWare database. This may be
useful when automating the creation of multi-head clusters. This endpoint is
public and does not require an authentication token
GET /install/repo
Returns a JSON object with a data field containing a repository configuration
suitable for another head node. This may be useful when automating the creation
of multi-head clusters. This endpoint is public and does not require an
authentication token
GET /install/client/installer
Returns a shell script that can be used to install a system with the ClusterWare
node package and related monitoring packages. If requested with no parameters,
a “pre-installation” script will be returned that will attempt to find out the CPU
architecture, OS name, and software packaging system. Alternatively, send the
following HTTP parameters and get a more customized installer script: ::
cpu=x86_64
specify the CPU architecture; one of x86_64 or aarm64
os=rhel8
specify the OS; one of rhel, debian, cumulus, or sonic
pkg=tar
specify the software packaging system; one of tar, rpm, or deb
If one or more parameters are omitted, then the system will select the installer
that best matches the set of parameters that were sent. Clients must be aware
that a different packaging system may be returned; for example, requesting the
rpm installer may return a tar-based installer instead.
GET /install/client/download/<PKGSYS>/<NAME>
Downloads the package named NAME from the head node, where the packaging
system is determined by PKGSYS. PKGSYS is one of tar, rpm, or deb. Note that
this simply downloads the package and does not install it.