Luna2 REST API

Design decisions

  • No implementation of 300 (redirects)

  • Not all errors are implemented

  • Not all methods are supported, only GET and POST

  • All POST request body are required to have valid JSON (RFC 8259). The server will not validate for the client, simply reject any malformed request. There are ways to format and validate it in Linux / python.

  • Monitoring end-points are provided on /monitor.

  • HTTP codes must also be passed back

Changelog

Removals:

  • Removal of lweb (replaced by REST API), same port (7050)

  • auto creation of nodes is removed (Create=True), also removing the nodeprefix and nodedigits configuration items

Changes:

  • newfieldname can be used for cloning ({name}/_clone) and renaming ({name})

  • dhcp configuration has been removed from cluster level and moved to network (now enables/disables per network)

New features:

General:

  • Templating jinja2

  • Standardized jinja2 variables available in the LUNA installer for further customization

  • Full URI is also required in the request body and response body

  • URI is consistent with request and response body

Authentication

  • Role based authentication, default group: admin

Provisioning

  • Provisioning default is torrent

  • Fallback via /files/{tarball} via webservice

  • Configurable via the cluster endpoint, override possible on group or node level

  • Configurable provisioning allows for future provisioning methods such as rsync, kickstart or anything scriptable

Group configuration:

  • Netboot (offering PXE menu or minimized boot menu -> LOCALDISK)

  • Localinstall (triggers Grub2 installation)

Network:

  • API to get next available IP (can be called manually) /config/network/_nextfreeip

  • Renumbering will not be done if:

  • the new group has the same network interfaces and networks

  • the IP is still valid in the new group

NTP configuration (cluster/network):

  • Can be configured cluster wide

  • Override possible on network level

BMC setup

  • Added gateway configuration (taken from network configuration)

  • Added NTP configuration (taken from network configuration)

Secrets

  • Secrets can be configured on group or node level. These are placed inside the OSimage, preventing placement of sensitive information in images.

OSimage:

  • Changing kernel can be done with (/config/osimage/{osimage}/kernel) automatic packing or without (/config/osimage/{osimage}

  • Cloning includes copying of the files, done by ZFS so it should be very quick

  • Distribution flag (default redhat) which should trigger different dracut/packing in future releases

Monitor

  • Added monitoring endpoints for nodes

  • Self-monitoring daemon (/monitor/service/luna2)

Service control via daemon API

  • Monitoring & control of dhcp and dns

Rest resources

Note: There is no cluster configuration. This is to be done by the ini files to prevent breaking installations

Examples

http://host:port/config/node/{node}

Structure of the URI

  • host and port define the host and port where the application lives

  • config is the context for updating or deleting the node at {node}

All POST Method(s) requires a valid token to get the response. Except /token

All Get Method will get the minimal response if the token isn’t set in the headers.

the ** key will hold the token against the apis.

Initially, Tokens are sha256 encoded.

URI Structure

See Luna2 REST API URI Structure

Fields

See Luna2 REST API Fields

API Usage

Authenticate against the API (POST /token)

When talking to the API, a token is required. The token can be obtained from the token endpoint.

Request

POST /token

Request header


Request body

{
  "username": "luna",
  "password": "luna"
}

Response body

{
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"
}

Response header

HTTP 201 Created will be expected to be returned.

HTTP 401 Unauthorized is mandatory if the credentials are invalid

HTTP 400 Bad request when the request is invalid (field definitions)

HTTP 503 Service unavailable is returned when the backend is unavailable.

Who am I (GET /whoami)

Returns the Luna user the token belongs to: name, id, authentication source, whether it is an admin user, the usergroups it is a member of with the role held in each, and the usergroups among those that carry the hardware flag. Any valid token may ask. The account from the configuration file has id 0, is always an admin user and is a member of no usergroup.

Request

GET /whoami

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "user": "jdoe",
  "id": 3,
  "source": "ldap",
  "admin": false,
  "usergroups": {
    "physics": "manager",
    "chemistry": "reader"
  },
  "hardware": [
    "physics"
  ]
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled.

HTTP 403 Forbidden is returned for the token of a delegate user, which may only obtain tokens for others, and for a node token.

Version

A very simple endpoint. No auth required and no modifications allowed.

Returned:

  • Luna version

  • API version it supports (this document)

  • Commit (from Git)

Get version (GET /version)

Request

GET /version

Response body

{
  "version": {
    "luna": "2.0.0001",
    "api": 1,
    "commit": "hex(commit)"
  }
}

Request header


Response header

HTTP 200 OK will be expected to be returned.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Booting

The boot menu entry will give out one of several templates (see the Boot process page):

  • templ_boot_ipxe.cfg (default)

  • templ_boot_disk.cfg

  • templ_boot_ipxe_short.cfg

The controller writes out the DHCP configuration. The normal iPXE menu is served when the bootmenu and netboot flags have been set to True.

Node is known

Bootmenu

Netboot

Template

1

Yes

False

True

Short

2

Yes

True

True

Normal

3

Yes

Any

False

Disk

4

No

-

-

Normal

The DHCP configuration is changed to reflect booting off different templates.

2 + 4:

host node001  {
    hardware ethernet 18:c0:4d:45:00:eb;
    fixed-address 10.141.0.1;
}

1:

host node001  {
    hardware ethernet 18:c0:4d:45:00:eb;
    fixed-address 10.141.0.1;
    filename "http://10.141.255.254:7050/boot/short"
}

3:

host node001  {
    hardware ethernet 18:c0:4d:45:00:eb;
    fixed-address 10.141.0.1;
    filename "http://10.141.255.254:7050/boot/disk"
}

Boot by MAC (or port detection)

The node will do a discovery (auto menu selection)

Request

GET /boot/search/mac/18:c0:4d:45:00:eb

Response

The response is an iPXE script which can be booted from.

#!ipxe

imgfetch -n kernel http://10.141.255.254:7050/boot/compute-vmlinuz-4.18.0-372.26.1.el8_6.x86_64
imgload kernel
imgargs kernel root=luna luna.bootproto=static luna.mac=18:c0:4d:45:00:eb luna.ip=10.141.0.1/16 luna.url=http://10.141.255.254:7050/luna luna.node=node001 luna.hostname=node001.cluster luna.service=0  initrd=initrd.img
imgfetch --name initrd.img http://10.141.255.254:7050/boot/compute-initramfs-4.18.0-372.26.1.el8_6.x86_64
imgexec kernel

Manual boot

Request

GET /boot/manual/hostname/node002/18:c0:4d:45:00:eb

Response

The controller will immediately change the hostname in the backend to reflect the change, removing the previous settings for the entry.

The response will allow booting from an alternative hostname. Note the changed luna.node and luna.hostname parameter.

#!ipxe

imgfetch -n kernel http://10.141.255.254:7050/boot/compute-vmlinuz-4.18.0-372.26.1.el8_6.x86_64
imgload kernel
imgargs kernel root=luna luna.bootproto=static luna.mac=18:c0:4d:45:00:eb luna.ip=10.141.0.1/16 luna.url=http://10.141.255.254:7050/luna luna.node=node002 luna.hostname=node002.cluster luna.service=0  initrd=initrd.img
imgfetch --name initrd.img http://10.141.255.254:7050/boot/compute-initramfs-4.18.0-372.26.1.el8_6.x86_64
imgexec kernel

iPXE boot menu (GET /boot)

This endpoint is requested by the node's iPXE bootloader and is served without a token.

Request

GET /boot

Response body A rendered iPXE script (the main boot menu) is returned. The Luna controller fills in the available nodes, groups and controller details before serving it.

#!ipxe
[...]

Response header

HTTP 200 OK will be expected to be returned.

Shortened iPXE boot menu (GET /boot/short)

This endpoint is requested by the node's iPXE bootloader and is served without a token.

Request

GET /boot/short

Response body A rendered iPXE script is returned. This is a shortened variant of the main boot menu that omits the per-node and per-group listings.

#!ipxe
[...]

Response header

HTTP 200 OK will be expected to be returned.

Boot from local disk (GET /boot/disk)

This endpoint is requested by the node's iPXE bootloader and is served without a token.

Request

GET /boot/disk

Response body A rendered iPXE script that instructs the node to boot from its local disk is returned.

#!ipxe
[...]
sanboot --no-describe --drive 0x80
[...]

Response header

HTTP 200 OK will be expected to be returned.

Boot lookup by MAC address (GET /boot/search/mac/{macaddress})

This endpoint is requested by the node's iPXE bootloader and is served without a token.

Request

GET /boot/search/mac/aa:bb:cc:dd:ee:ff

Response body The server performs discovery on the supplied MAC address (looking the MAC up via SNMP port-detection if that has been enabled) and returns a rendered iPXE script populated with the matched node's image, kernel, initrd, kernel options and network details.

#!ipxe
[...]

Response header

HTTP 200 OK will be expected to be returned.

Manual boot by group (GET /boot/manual/group/{groupname}/{macaddress})

This endpoint is requested by the node's iPXE bootloader and is served without a token.

Request

GET /boot/manual/group/compute/aa:bb:cc:dd:ee:ff

Response body The server picks the first available node in the chosen group (creating one if none is available), assigns the supplied MAC address to it, and returns a rendered iPXE script populated with that node's image, kernel, initrd, kernel options and network details.

#!ipxe
[...]

Response header

HTTP 200 OK will be expected to be returned.

Manual boot by hostname (GET /boot/manual/hostname/{hostname}/{macaddress})

This endpoint is requested by the node's iPXE bootloader and is served without a token.

Request

GET /boot/manual/hostname/node001/aa:bb:cc:dd:ee:ff

Response body The server performs discovery on the supplied hostname (looking the MAC up via SNMP port-detection if that has been enabled), assigns the supplied MAC address to the matched node, and returns a rendered iPXE script populated with that node's image, kernel, initrd, kernel options and network details.

#!ipxe
[...]

Response header

HTTP 200 OK will be expected to be returned.

Boot role (GET /boot/roles/{role})

Request

GET /boot/roles/<role>

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body Unlike the other boot endpoints, this returns a JSON payload containing the role's target and its base64-encoded script data.

{
    "target": "[...]",
    "script": "[...]"
}

Response header

HTTP 200 OK will be expected to be returned.

Boot script (GET /boot/scripts/{script})

Request

GET /boot/scripts/<script>

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body Like the role endpoint, this returns a JSON payload containing the script's target and its base64-encoded script data.

{
    "target": "[...]",
    "script": "[...]"
}

Response header

HTTP 200 OK will be expected to be returned.

Boot profile (GET /boot/profiles/{profile})

Returns what the installer needs to apply one profile: its files with content, path, owner and mode, and its service with the action. Called by the node during installation.

Token is required: a node's provision token (for any profile), or the token of the controller account or an admin user. Unset owners and modes are filled in with root:root and 644, and resolved_owner carries the owner as numeric ids, resolved on the controller. File content is base64 encoded.

Request

GET /boot/profiles/sysctl-hpc

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "profile": {
    "sysctl-hpc": {
      "scope": "static",
      "service": "systemd-sysctl",
      "action": "restart",
      "enabled": true,
      "files": [
        {
          "name": "90-hpc.conf",
          "content": "dm0uc3dhcHBpbmVzcyA9IDEK",
          "path": "/etc/sysctl.d/90-hpc.conf",
          "owner": "root:root",
          "mode": "644",
          "resolved_owner": "0:0"
        }
      ]
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the token belongs to a user other than the controller account or an admin user.

HTTP 404 Not found is returned when the profile does not exist.

Kickstart installation template (GET /kickstart/install/{node})

This endpoint is requested by the node during provisioning and is served without a token.

Request

GET /kickstart/install/node001

Response body A rendered kickstart installation template for the named node is returned, populated with the node's group, OS image, distribution, partitioning, BMC setup, interfaces, pre/part/post scripts, provisioning method and related values.

[...]
%post
[...]
%end

Response header

HTTP 200 OK will be expected to be returned.

Switch ZTP recipe (GET /boot/switch/{name})

This endpoint is requested by the switch during zero-touch provisioning (ZTP) and is served without a token.

Returns the ZTP recipe for the switch as JSON (Content-Type: application/json). The image step is present only when the switch has a default_url. The second step points at the switch's command list; it is a startup file when the switch carries its own ZTP configuration in YAML format, otherwise a command list. URLs use the controller's API endpoint, or the web server's protocol and port when the switch's url_protocol is plain; the switch's url_server replaces the controller address when set.

Request

GET /boot/switch/switch01

Response body A ZTP recipe in JSON is returned:

{
  "ztp": {
    "01-image": {
      "image": {
        "install": {
          "url": "https://10.141.255.254:7050/files/switch-os.bin",
          "skip-reboot": false
        }
      },
      "halt-on-failure": true,
      "description": "switch01: ensure correct OS version, reboot, then continue"
    },
    "02-commands-list": {
      "url": "https://10.141.255.254:7050/boot/switch/switch01/commands",
      "clear-config": "true",
      "save-config": "true",
      "halt-on-failure": true,
      "description": "switch01: apply identity + services, persist, disable ZTP"
    },
    "03-connectivity-check": {
      "connectivity-check": {
        "ping-hosts": [
          "10.141.255.254"
        ],
        "ping-count": 5,
        "ignore-result": true
      },
      "description": "switch01: sanity-check mgmt reachability"
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 404 Not found is returned when the switch does not exist or the ZTP template is missing. The body is JSON with the reason in message:

{
  "message": "switch switch01 does not exist",
  "ipaddress": "10.141.255.254",
  "webserver_protocol": "https",
  "webserver_port": "7050",
  "template": "templ_boot_failed.cfg"
}

Switch ZTP command list (GET /boot/switch/{name}/commands)

This endpoint is requested by the switch during zero-touch provisioning and is served without a token.

Returns plain text (Content-Type: text/plain): the switch's own ZTP configuration (ztpconfig, stored base64 encoded and served decoded) when one is set, otherwise a minimal default that sets the host name and enables SSH.

Request

GET /boot/switch/switch01/commands

Response body The default command list is returned when the switch has no ZTP configuration of its own:

# generated by Luna for switch01
nv set system hostname switch01
nv set system ssh-server state enabled
nv config apply -y

Response header

HTTP 200 OK will be expected to be returned.

HTTP 404 Not found is returned when the switch does not exist. The body is JSON with the reason in message.

Luna installation template (GET boot/install/{node})

The luna.node and luna.hostname are passed through the boot parameters and are used to retrieve the installation template. Note that the API must verify that the request is originating from the node itself by checking the IP address (i.e. 10.141.0.1 can only request a template belonging to node001).

Request

GET /boot/install/node001

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response

The response would be a tailored installation script for this node (See #pre, #part, #postscripts) in plain text.

export LUNA_IMAGEFILE=''
export LUNA_OSIMAGE=''
export LUNA_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MCwiZXhwIjoxNzM5MjcxNzA2fQ.2HUmy8sL5oFtzayjWBfUeK0huezEk6rA9qt41_VixCU"
export DECODE=""
## ----------- useful variable exports -----------
export _HOSTNAME="node001"
export _SYSTEMROOT="/sysroot"
export _BOOTIF=${LUNA_BOOTIF}
## -----------------------------------------------

export INSECURE='--insecure'

if [ -n "${LUNA_BOOTIF}" ]; then
    export INTERFACE="--interface ${LUNA_BOOTIF}"
fi
if [ "$(echo LUNA_API_PROTOCOL | grep ':')" ]; then
    export LUNA_URL="http://[10.141.255.254]:7050"
else
    export LUNA_URL="http://10.141.255.254:7050"
fi

base64 --help &> /dev/null
if [ "$?" == "0" ]; then
    DECODE=1
fi
if [ ! "$DECODE" ]; then
    echo "Luna2: --WARNING-- base64 decoder not available. This will impair the installer"
fi

function update_status {
    json='{"monitor": { "status": { "node001": { "state": "'$1'" } } } }'
    curl $INTERFACE $INSECURE -X POST -H "x-access-tokens: $LUNA_TOKEN" -H "Content-Type: application/json" -d "$json" -s "${LUNA_URL}/monitor/node/node001"
}

function update_system_info {
    dmidecode --help &> /dev/null
    ret=$?
    if [ "$ret" == "0" ]; then
        vendor=$(dmidecode -s system-manufacturer)
        assettag=$(dmidecode -s system-serial-number)
        json='{"config": {"node": { "node001": { "vendor": "'$vendor'", "assettag": "'$assettag'" } } } }'
        curl $INTERFACE $INSECURE -X POST -H "x-access-tokens: $LUNA_TOKEN" -H "Content-Type: application/json" -d "$json" -s "${LUNA_URL}/config/node/node001"
    else
        echo "Luna2: dmidecode not found and could therefor not update system information"
    fi
}

function update_node_ip {
    json='{"config": {"node": {"node001": {"name": "node001", "interfaces": [{"interface": "BOOTIF", "force": true, "ipaddress": "'$1'"}]}}}}'
    curl $INTERFACE $INSECURE -X POST -H "x-access-tokens: $LUNA_TOKEN" -H "Content-Type: application/json" -d "$json" -s "${LUNA_URL}/config/node/node001"
}

function lunainit {
    if [ ! -d /lunatmp ]; then
        mkdir /lunatmp
    fi
    if [ ! -d //sysroot ]; then
        echo "Luna2: Warning! /sysroot did not exist! it's unexpected. I will create it and try to continue"
        mkdir //sysroot
    fi
}

function dynamic_ip_check {
    if [ "${LUNA_BOOTPROTO}" == "dhcp" ]; then
        echo "Luna2: I need to update luna to reflect my dynamic IP address"
        if [ "${LUNA_BOOTIF}" ]; then
            MY_IP=$(ip a show dev ${LUNA_BOOTIF}|grep -oE "inet [0-9\.]+"|grep -oE "[0-9\.]+")
            if [ "${MY_IP}" ]; then
                update_node_ip $MY_IP
            else
                echo "Luna2: Could not figure out my IP address"
            fi
        else
            echo "Luna2: BOOTIF is not defined"
        fi
    fi
}
...
...
...

Group configuration

Get a list of groups (GET /config/group)

Request

GET /config/group

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "group": {
      "compute": {
        "bmcsetup": true,
        "bmcsetupname": "gigabyte",
        "domain": "cluster",
        "interfaces": [
          {
            "interface": "BOOTIF",
            "network": "clusternet"
          },
          {
            "interface": "BMC",
            "network": "ipmi"
          },
          {
            "interface": "ib0",
            "network": "ib"
          }
        ],
        "osimage": "compute",
        "osimagetag": "versionx",
        "partscript": "IyEvYmluL2Jhc2gKZXhpdCAw",
        "postscript": "IyEvYmluL2Jhc2gKZXhpdCAw",
        "prescript": "IyEvYmluL2Jhc2gKZXhpdCAw",
        "provision_interface": null,
        "netboot": true,
        "bootmenu": false,
        "comment": "Default group",
        "provision_method": "torrent",
        "provision_fallback": "http"
      },
      "compute-ib": {
        "bmcsetup": true,
        "bmcsetupname": "gigabyte",
        "domain": "cluster",
        "interfaces": [
          {
            "interface": "BOOTIF",
            "network": "clusternet"
          },
          {
            "interface": "BMC",
            "network": "ipmi"
          },
          {
            "interface": "ib0",
            "network": "ib"
          }
        ],
        "osimage": "compute",
        "partscript": "IyEvYmluL2Jhc2gKZXhpdCAw",
        "postscript": "IyEvYmluL2Jhc2gKZXhpdCAw",
        "prescript": "IyEvYmluL2Jhc2gKZXhpdCAw",
        "provision_interface": null,
        "netboot": true,
        "bootmenu": false,
        "comment": "Default group",
        "provision_method": "torrent",
        "provision_fallback": "http",
        "_override": false
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get group information (GET /config/group/{group})

Request

GET /config/group/compute

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "group": {
      "compute": {
        "bmcsetup": true,
        "bmcsetupname": "gigabyte",
        "domain": "cluster",
        "interfaces": [
          {
            "interface": "BOOTIF",
            "network": "clusternet"
          },
          {
            "interface": "BMC",
            "network": "ipmi"
          },
          {
            "interface": "ib0",
            "network": "ib"
          }
        ],
        "osimage": "compute",
        "osimagetag": "versionx",
        "partscript": "IyEvYmluL2Jhc2gKZXhpdCAw",
        "postscript": "IyEvYmluL2Jhc2gKZXhpdCAw",
        "prescript": "IyEvYmluL2Jhc2gKZXhpdCAw",
        "provision_interface": null,
        "netboot": true,
        "bootmenu": false,
        "comment": "Default group",
        "provision_method": "torrent",
        "provision_fallback": "http",
        "_override": false
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get a list members of the groups (GET /config/group/{group}/_member)

Request

GET /config/group/{group}/_member

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "group": {
      "compute": {
        "members": [
          "node001",
          "node002",
          "node003",
          "node004"
        ]
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Create or update & Rename(By newgroupname) group information (POST /config/group/{group})

Request

POST /config/group/compute

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "group": {
      "compute": {
        "newgroupname": "compute-gpu",
        "bmcsetup": true,
        "bmcsetupname": "gigabyte",
        "domain": "cluster",
        "interfaces": [
          {
            "interface": "BOOTIF",
            "network": "clusternet"
          },
          {
            "interface": "BMC",
            "network": "ipmi"
          },
          {
            "interface": "ib0",
            "network": "ib"
          }
        ],
        "osimage": "compute",
        "osimagetag": "versionx",
        "partscript": "IyEvYmluL2Jhc2gKZXhpdCAw",
        "postscript": "IyEvYmluL2Jhc2gKZXhpdCAw",
        "prescript": "IyEvYmluL2Jhc2gKZXhpdCAw",
        "provision_interface": null,
        "netboot": true,
        "bootmenu": false,
        "comment": "Default group",
        "provision_method": "torrent",
        "provision_fallback": "http",
        "_override": false
      }
    }
  }
}

Response header

HTTP 204 No content will be expected to be returned.

HTTP 201 Created will be expected to be returned when a new object is created.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Clone (By newgroupname) a group (POST /config/group/{group}/_clone)

Request

POST /config/group/compute/_clone

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "group": {
      "compute": {
        "newgroupname": "compute-gpu",
        "bmcsetup": true,
        "bmcsetupname": "gigabyte",
        "domain": "cluster",
        "interfaces": [
          {
            "interface": "BOOTIF",
            "network": "clusternet"
          },
          {
            "interface": "BMC",
            "network": "ipmi"
          },
          {
            "interface": "ib0",
            "network": "ib"
          }
        ],
        "osimage": "compute",
        "osimagetag": "versionx",
        "partscript": "IyEvYmluL2Jhc2gKZXhpdCAw",
        "postscript": "IyEvYmluL2Jhc2gKZXhpdCAw",
        "prescript": "IyEvYmluL2Jhc2gKZXhpdCAw",
        "provision_interface": null,
        "netboot": true,
        "bootmenu": false,
        "comment": "Default group",
        "provision_method": "torrent",
        "provision_fallback": "http"
      }
    }
  }
}

Response header

HTTP 204 No content will be expected to be returned.

HTTP 201 Created will be expected to be returned when a new object is created.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Deleting a group (GET /config/group/{group}/_delete)

Request

GET /config/group/compute/_delete

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get group interface information (GET /config/group/{group}/interfaces)

Request

GET /config/group/compute/interfaces

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "group": {
      "compute": {
        "interfaces": [
          {
            "interface": "BOOTIF",
            "network": "clusternet"
          },
          {
            "interface": "BMC",
            "network": "ipmi"
          },
          {
            "interface": "ib0",
            "network": "ib"
          }
        ]
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Create or update group interface information (POST /config/group/{group}/interfaces)

The interfaces can accept updates to one or more interfaces.

Request

POST /config/group/compute/interfaces

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "group": {
      "compute": {
        "interfaces": [
          {
            "interface": "BOOTIF",
            "network": "clusternet"
          },
          {
            "interface": "BMC",
            "network": "ipmi"
          },
          {
            "interface": "ib0",
            "network": "ib"
          }
        ]
      }
    }
  }
}

Response body


Response header

HTTP 204 No content will be expected to be returned.

HTTP 201 Created will be expected to be returned when created

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist (group)

HTTP 503 Service unavailable is returned when the backend is unavailable.

Retrieve group interface information (GET /config/group/{group}/interfaces/{interface})

Request

GET /config/group/compute/interfaces/BOOTIF

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "group": {
      "compute": {
        "interfaces": [
          {
            "interface": "BOOTIF",
            "network": "clusternet"
          }
        ]
      }
    }
  }
}

Response body


Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist (group)

HTTP 503 Service unavailable is returned when the backend is unavailable.

Delete group interface (GET /config/group/{group}/interfaces/{interface}/_delete)

Request

GET /config/group/compute/interfaces/BOOTIF/_delete

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body


Response body


Response header

HTTP 204 No Content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist (group)

HTTP 503 Service unavailable is returned when the backend is unavailable.

Push the osimage to all nodes in the group (POST /config/group/{name}/_ospush)

Request

POST /config/group/compute/_ospush

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "group": {
      "compute": {
        "osimage": "compute-image"
      }
    }
  }
}

Response body

This is an asynchronous operation. The push is queued and a request_id is returned that can be polled for progress (see Tracking asynchronous requests).

{
  "message": "queued",
  "request_id": "1781082941.3238328347230542"
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not Found is returned when the push could not be started.

Get the group disk layout (GET /config/group/{name}/disklayout)

Returns only the disk layout of the group, in the same shape the full group information uses. The value is base64-encoded JSON; _disklayout_source says where it comes from: group or default (empty).

Request

GET /config/group/compute/disklayout

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "group": {
      "compute": {
        "disklayout": "eyJ2ZXJzaW9uIjogMiwgInNldHMiOiBbLi4uXX0=",
        "_disklayout_source": "group"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when a node's provision token is used; this endpoint takes a user token.

HTTP 404 Not Found is returned when the group does not exist or is not visible to the token's user.

Get the group mounts document (GET /config/group/{name}/mounts)

Returns only the resolved network mounts document of the group (cluster, group; the most specific level that holds a document wins outright). The value is base64-encoded JSON; _mounts_source says where it comes from: group, cluster or default (empty).

Request

GET /config/group/compute/mounts

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "group": {
      "compute": {
        "mounts": "eyJ2ZXJzaW9uIjogMSwgIm1vdW50cyI6IFt7InBhdGgiOiAiL2RhdGEiLCAidHlwZSI6ICJuZnMiLCAic2VydmVyIjogImNvbnRyb2xsZXIiLCAic291cmNlIjogIi9leHBvcnQvZGF0YSIsICJvcHRpb25zIjogInJ3LGhhcmQifV19",
        "_mounts_source": "cluster"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when a node's provision token is used; this endpoint takes a user token.

HTTP 404 Not Found is returned when the group does not exist or is not visible to the token's user.

Add or update a group mount (POST /config/group/{name}/mounts)

Adds one entry to the group's network mounts document, or updates the entry with the same path: the fields given replace those stored, the others stay. mount is a single entry as base64-encoded JSON, with the fields described under Add or update a cluster mount. A group without a document of its own first receives a copy of the document it currently resolves to, and the message then says so; from then on the group keeps its own document.

Request

POST /config/group/compute/mounts

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "group": {
      "compute": {
        "mount": "eyJwYXRoIjogIi9kYXRhIiwgInR5cGUiOiAibmZzIiwgInNlcnZlciI6ICJjb250cm9sbGVyIiwgInNvdXJjZSI6ICIvZXhwb3J0L2RhdGEiLCAib3B0aW9ucyI6ICJydyxoYXJkIn0="
      }
    }
  }
}

Response body

{
  "message": "Mount /data added to group compute."
}

Response header

HTTP 201 Created will be expected to be returned when the entry was added or updated, or the document was already as requested.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 400 Bad Request is returned when no mount is given, the entry has no path, or the resulting document is invalid.

HTTP 403 Forbidden is returned when the token's user may not change the group, and when a node's provision token is used.

HTTP 404 Not Found is returned when the group does not exist or the token's user may not read it, or, on a high-availability setup, when this controller is not yet in sync with its peer.

Remove a group mount (POST /config/group/{name}/mounts/_remove)

Removes the entry with the given path from the group's network mounts document. A group without a document of its own first receives a copy of the document it resolves to, so the entry is removed for this group only. An emptied document stays in place and still overrides the levels above it.

Request

POST /config/group/compute/mounts/_remove

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "group": {
      "compute": {
        "path": "/data"
      }
    }
  }
}

Response body


Response header

HTTP 204 No Content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 400 Bad Request is returned when no path is given or the document the group sees holds no entry at that path.

HTTP 403 Forbidden is returned when the token's user may not change the group, and when a node's provision token is used.

HTTP 404 Not Found is returned when the group does not exist or the token's user may not read it, or, on a high-availability setup, when this controller is not yet in sync with its peer.

Assign a profile to a group (POST /config/group/{name}/profiles)

Adds one profile to the group's own profile assignments, beside the ones it already has. Profiles assigned at a higher level are not touched.

Request

POST /config/group/compute/profiles

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "group": {
      "compute": {
        "profile": "gpu"
      }
    }
  }
}

Response body

{
  "message": "Profile gpu assigned to group compute."
}

Response header

HTTP 201 Created will be expected to be returned when the profile was assigned, or was already assigned to the group.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 400 Bad Request is returned when no profile is given or the profile does not exist.

HTTP 403 Forbidden is returned when the token's user may not change the group, and when a node's provision token is used.

HTTP 404 Not Found is returned when the group does not exist or the token's user may not read it, or, on a high-availability setup, when this controller is not yet in sync with its peer.

Unassign a profile from a group (POST /config/group/{name}/profiles/_unassign)

Removes one profile from the group's own profile assignments.

Request

POST /config/group/compute/profiles/_unassign

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "group": {
      "compute": {
        "profile": "gpu"
      }
    }
  }
}

Response body


Response header

HTTP 204 No Content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 400 Bad Request is returned when no profile is given or the profile is not assigned to the group.

HTTP 403 Forbidden is returned when the token's user may not change the group, and when a node's provision token is used.

HTTP 404 Not Found is returned when the group does not exist or the token's user may not read it, or, on a high-availability setup, when this controller is not yet in sync with its peer.

Preview a firmware push to a group (GET /config/group/{name}/firmware/_preview)

Answers what a firmware push to the group would do, per node, without doing any of it. No BMC is contacted: the answer comes from the stored inventory and the firmware catalogue, so it also works for powered-off nodes. Nodes that would be updated or are already up to date are listed under ready; nodes that cannot be updated are grouped by reason under skipped; summary gives the counts.

Request

GET /config/group/compute/firmware/_preview

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "firmware": {
      "preview": {
        "ready": [
          {
            "node": "node001",
            "hardware": [
              "Supermicro",
              "X12DPT-B6"
            ],
            "components": [
              {
                "component": "BMC",
                "entry": "x12-bmc",
                "wanted": "01.04.08",
                "running": "01.03.12",
                "updateable": true,
                "imagefile": "x12-bmc-010408.bin"
              }
            ],
            "differs": [
              {
                "component": "BMC",
                "entry": "x12-bmc",
                "wanted": "01.04.08",
                "running": "01.03.12",
                "updateable": true,
                "imagefile": "x12-bmc-010408.bin"
              }
            ]
          }
        ],
        "skipped": {
          "no inventory; has this node booted?": [
            "node004"
          ]
        },
        "summary": [
          "1 node(s) would change, 0 already as the catalogue asks",
          "1 skipped: no inventory; has this node booted?"
        ]
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when a node's provision token is used; this endpoint takes a user token.

HTTP 404 Not Found is returned when the group does not exist, the token's user may not read it, or it has no nodes.

Push firmware to all nodes in the group (POST /config/group/{name}/_firmwarepush)

Queues a firmware update for every node of the group whose running versions differ from the firmware catalogue. Members are read when the request is made. Nodes already on the catalogue version, and nodes that cannot be updated (for example without inventory), are counted in the message rather than queued. The optional component limits the push to one component. This is an asynchronous operation: poll the returned request_id with GET /config/status/{request_id}; the outcome per node is also available from the firmware catalogue status.

Request

POST /config/group/compute/_firmwarepush

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "group": {
      "compute": {
        "component": "BMC"
      }
    }
  }
}

Response body

{
  "message": "firmware update queued for 3 node(s), 1 skipped: no inventory; has this node booted?",
  "request_id": "1761738420.5531207630414211"
}

Response header

HTTP 200 OK will be expected to be returned with the request_id in the body.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 400 Bad Request is returned when the name or the request body is malformed.

HTTP 403 Forbidden is returned when the token's user may not operate the group or change a catalogue entry the push would apply.

HTTP 404 Not Found is returned when the group does not exist or has no nodes, or no node has anything to update.

Push a BIOS configuration to all nodes in the group (POST /config/group/{name}/_biospush)

Queues a stored BIOS configuration to be applied to every node of the group; members are read when the request is made. biosconfig names the configuration; when it is left out, the group must have one assigned, and each node then receives its own assignment, else the group's. version_match is optional and sets how a BIOS version difference between the configuration and a node is handled: strict refuses, warn proceeds and reports it, ignore does not compare; the default comes from the daemon configuration (warn). This is an asynchronous operation: poll the returned request_id with GET /config/status/{request_id}.

Request

POST /config/group/compute/_biospush

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "group": {
      "compute": {
        "biosconfig": "compute-bios",
        "version_match": "warn"
      }
    }
  }
}

Response body

{
  "message": "BIOS configuration compute-bios queued for 4 node(s)",
  "request_id": "1761738480.2209861712514211"
}

Response header

HTTP 200 OK will be expected to be returned with the request_id in the body.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 400 Bad Request is returned when no biosconfig is named and the group has none assigned, or the body is malformed.

HTTP 403 Forbidden is returned when the token's user may not operate the group or change the BIOS configuration.

HTTP 404 Not Found is returned when the group does not exist or has no nodes, or the configuration does not exist or holds no settings.

Node configuration

Get a list of nodes (GET /config/node)

Request

GET /config/node

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "node": {
      "node001": {
        "group": "compute",
        "interfaces": [
          {
            "interface": "BOOTIF",
            "network": "clusternet",
            "ipaddress": "10.141.0.1"
          },
          {
            "interface": "BMC",
            "network": "ipmi",
            "ipaddress": "10.148.0.1"
          },
          {
            "interface": "ib0",
            "network": "ib",
            "ipaddress": "10.149.0.1"
          }
        ],
        "switch": "switch01",
        "switchport": 1,
        "service": false,
        "setupbmc": true,
        "status": "installer.completed",
        "comment": null,
        "osimage": null,
        "osimagetag": null,
        "prescript": null,
        "postscript": null,
        "partscript": null,
        "netboot": true,
        "bootmenu": false,
        "provision_interface": null,
        "provision_method": null,
        "provision_fallback": null,
        "tpm_uuid": null,
        "tpm_pubkey": null,
        "tpm_sha256": null,
        "_override": false
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get node information (GET /config/node/{node})

Request

GET /config/node/node001

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "node": {
      "node001": {
        "group": "compute",
        "interfaces": [
          {
            "interface": "BOOTIF",
            "network": "clusternet",
            "ipaddress": "10.141.0.1"
          },
          {
            "interface": "BMC",
            "network": "ipmi",
            "ipaddress": "10.148.0.1"
          },
          {
            "interface": "ib0",
            "network": "ib",
            "ipaddress": "10.149.0.1"
          }
        ],
        "switch": "switch01",
        "switchport": 1,
        "service": false,
        "setupbmc": true,
        "status": "installer.completed",
        "comment": null,
        "osimage": null,
        "osimagetag": null,
        "prescript": null,
        "postscript": null,
        "partscript": null,
        "netboot": true,
        "bootmenu": false,
        "provision_interface": null,
        "provision_method": null,
        "provision_fallback": null,
        "tpm_uuid": null,
        "tpm_pubkey": null,
        "tpm_sha256": null,
        "_override": false
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist

HTTP 503 Service unavailable is returned when the backend is unavailable.

Create or update node information (POST /config/node/{node})

Renaming a node is done by setting the newhostname field

Interfaces can be updated in bulk via the {node}, or single items via the {node}/interfaces

Request

POST /config/node/{node}

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "node": {
      "node001": {
        "group": "compute",
        "interfaces": [
          {
            "interface": "BOOTIF",
            "network": "clusternet",
            "ipaddress": "10.141.0.1"
          },
          {
            "interface": "BMC",
            "network": "ipmi",
            "ipaddress": "10.148.0.1"
          },
          {
            "interface": "ib0",
            "network": "ib",
            "ipaddress": "10.149.0.1"
          }
        ],
        "switch": "switch01",
        "switchport": 1,
        "service": false,
        "setupbmc": true,
        "status": "installer.completed",
        "comment": null,
        "osimage": null,
        "osimagetag": null,
        "prescript": null,
        "postscript": null,
        "partscript": null,
        "netboot": true,
        "bootmenu": false,
        "provision_interface": null,
        "provision_method": null,
        "provision_fallback": null,
        "tpm_uuid": null,
        "tpm_pubkey": null,
        "tpm_sha256": null
      }
    }
  }
}

Response body


Response header

HTTP 204 No Content will be expected to be returned.

HTTP 201 Created will be expected to be returned when a new object has been created.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Clone a node (POST /config/node/{node}/_clone)

Renaming a node is done by setting the newhostname field

Interfaces can be updated in bulk via the {node}, or single items via the {node}/interfaces

Request

POST /config/node/{node}/_clone

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "node": {
      "node001": {
        "group": "compute",
        "interfaces": [
          {
            "interface": "BOOTIF",
            "network": "clusternet",
            "ipaddress": "10.141.0.1"
          },
          {
            "interface": "BMC",
            "network": "ipmi",
            "ipaddress": "10.148.0.1"
          },
          {
            "interface": "ib0",
            "network": "ib",
            "ipaddress": "10.149.0.1"
          }
        ],
        "switch": "switch01",
        "switchport": 1,
        "service": false,
        "setupbmc": true,
        "status": "installer.completed",
        "comment": null,
        "osimage": null,
        "osimagetag": null,
        "prescript": null,
        "postscript": null,
        "partscript": null,
        "netboot": true,
        "bootmenu": false,
        "provision_interface": null,
        "provision_method": null,
        "provision_fallback": null,
        "tpm_uuid": null,
        "tpm_pubkey": null,
        "tpm_sha256": null
      }
    }
  }
}

Response body


Response header

HTTP 204 No Content will be expected to be returned.

HTTP 201 Created will be expected to be returned when a new object has been created.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Deleting a node (GET /config/node/{node}/_delete)

Request

GET /config/node/node001/_delete

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No Content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 401 Not Found is mandatory if the object does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Listing node interfaces (GET /config/node/{node}/interfaces)

Request

GET /config/node/node001/interfaces

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "node": {
      "node001": {
        "interfaces": [
          {
            "interface": "BOOTIF",
            "network": "clusternet",
            "ipaddress": "10.141.0.1"
          },
          {
            "interface": "BMC",
            "network": "ipmi",
            "ipaddress": "10.148.0.1"
          },
          {
            "interface": "ib0",
            "network": "ib",
            "ipaddress": "10.149.0.1"
          }
        ]
      }
    }
  }
}

Response header

HTTP 204 No Content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 401 Not Found is mandatory if the object does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Updating node interfaces (POST /config/node/{node}/interfaces)

Request

POST /config/node/node001/interfaces

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "node": {
      "node001": {
        "interfaces": [
          {
            "interface": "BOOTIF",
            "network": "clusternet",
            "ipaddress": "10.141.0.1"
          },
          {
            "interface": "BMC",
            "network": "ipmi",
            "ipaddress": "10.148.0.1"
          },
          {
            "interface": "ib0",
            "network": "ib",
            "ipaddress": "10.149.0.1"
          }
        ]
      }
    }
  }
}

Response body


Response header

HTTP 204 No Content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not Found is mandatory if the object does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Showing node interfaces (GET /config/node/{node}/interfaces/{interface})

Request

GET /config/node/node001/interfaces/BOOTIF

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "node": {
      "node001": {
        "interfaces": [
          {
            "interface": "BOOTIF",
            "network": "clusternet",
            "ipaddress": "10.141.0.1"
          }
        ]
      }
    }
  }
}

Response header

HTTP 204 No Content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not Found is mandatory if the object does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Delete node interfaces (GET /config/node/{node}/interfaces/{interface}/_delete)

Request

GET /config/node/node001/interfaces/BOOTIF/_delete

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No Content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not Found is mandatory if the object does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Grab an osimage from a node (POST /config/node/{name}/_osgrab)

Request

POST /config/node/node001/_osgrab

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "node": {
      "node001": {
        "osimage": "compute-image",
        "dryrun": false
      }
    }
  }
}

Response body

This is an asynchronous operation. The grab is queued and a request_id is returned that can be polled for progress (see Tracking asynchronous requests). On a high-availability setup where this controller is not the master, the request is forwarded and the message reflects that.

{
  "message": "queued",
  "request_id": "1781083867.650934521872381"
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not Found is returned when the grab could not be started.

Push an osimage to a node (POST /config/node/{name}/_ospush)

Request

POST /config/node/node001/_ospush

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "node": {
      "node001": {
        "osimage": "compute-image"
      }
    }
  }
}

Response body

This is an asynchronous operation. The push is queued and a request_id is returned that can be polled for progress (see Tracking asynchronous requests).

{
  "message": "queued",
  "request_id": "1781084659.3656888195114211"
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not Found is returned when the push could not be started.

Get the node disk layout (GET /config/node/{name}/disklayout)

Returns only the resolved disk layout of the node, in the same shape the full node information uses, so a booting node can read the layout it is about to apply. The value is base64-encoded JSON; _disklayout_source says where it comes from: node, group or default (empty).

Request

GET /config/node/node001/disklayout

Request header

An administrator token, or the node's own node token (see Obtain a node token via TPM attestation), is accepted.

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "node": {
      "node001": {
        "disklayout": "eyJ2ZXJzaW9uIjogMiwgInNldHMiOiBbLi4uXX0=",
        "_disklayout_source": "group"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when a node's provision token is used for another node.

HTTP 404 Not Found is returned when the node does not exist or is not visible to the token's user.

Get the node mounts document (GET /config/node/{name}/mounts)

Returns only the resolved network mounts document of the node (cluster, group and node; the most specific level that holds a document wins outright). The value is base64-encoded JSON; _mounts_source says where it comes from: node, group, cluster or default (empty).

Request

GET /config/node/node001/mounts

Request header

An administrator token, or the node's own node token (see Obtain a node token via TPM attestation), is accepted.

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "node": {
      "node001": {
        "mounts": "eyJ2ZXJzaW9uIjogMSwgIm1vdW50cyI6IFt7InBhdGgiOiAiL2RhdGEiLCAidHlwZSI6ICJuZnMiLCAic2VydmVyIjogImNvbnRyb2xsZXIiLCAic291cmNlIjogIi9leHBvcnQvZGF0YSIsICJvcHRpb25zIjogInJ3LGhhcmQifV19",
        "_mounts_source": "cluster"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when a node's provision token is used for another node.

HTTP 404 Not Found is returned when the node does not exist or is not visible to the token's user.

Add or update a node mount (POST /config/node/{name}/mounts)

Adds one entry to the node's network mounts document, or updates the entry with the same path: the fields given replace those stored, the others stay. mount is a single entry as base64-encoded JSON, with the fields described under Add or update a cluster mount. A node without a document of its own first receives a copy of the document it currently resolves to, and the message then says so; from then on the node keeps its own document.

Request

POST /config/node/node001/mounts

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "node": {
      "node001": {
        "mount": "eyJwYXRoIjogIi9kYXRhIiwgInR5cGUiOiAibmZzIiwgInNlcnZlciI6ICJjb250cm9sbGVyIiwgInNvdXJjZSI6ICIvZXhwb3J0L2RhdGEiLCAib3B0aW9ucyI6ICJydyxoYXJkIn0="
      }
    }
  }
}

Response body

{
  "message": "Mount /data added to node node001."
}

Response header

HTTP 201 Created will be expected to be returned when the entry was added or updated, or the document was already as requested.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 400 Bad Request is returned when no mount is given, the entry has no path, or the resulting document is invalid.

HTTP 403 Forbidden is returned when the token's user may not change the node, and when a node's provision token is used.

HTTP 404 Not Found is returned when the node does not exist or the token's user may not read it, or, on a high-availability setup, when this controller is not yet in sync with its peer.

Remove a node mount (POST /config/node/{name}/mounts/_remove)

Removes the entry with the given path from the node's network mounts document. A node without a document of its own first receives a copy of the document it resolves to, so the entry is removed for this node only. An emptied document stays in place and still overrides the levels above it.

Request

POST /config/node/node001/mounts/_remove

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "node": {
      "node001": {
        "path": "/data"
      }
    }
  }
}

Response body


Response header

HTTP 204 No Content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 400 Bad Request is returned when no path is given or the document the node sees holds no entry at that path.

HTTP 403 Forbidden is returned when the token's user may not change the node, and when a node's provision token is used.

HTTP 404 Not Found is returned when the node does not exist or the token's user may not read it, or, on a high-availability setup, when this controller is not yet in sync with its peer.

Assign a profile to a node (POST /config/node/{name}/profiles)

Adds one profile to the node's own profile assignments, beside the ones it already has. Profiles assigned at a higher level are not touched.

Request

POST /config/node/node001/profiles

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "node": {
      "node001": {
        "profile": "gpu"
      }
    }
  }
}

Response body

{
  "message": "Profile gpu assigned to node node001."
}

Response header

HTTP 201 Created will be expected to be returned when the profile was assigned, or was already assigned to the node.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 400 Bad Request is returned when no profile is given or the profile does not exist.

HTTP 403 Forbidden is returned when the token's user may not change the node, and when a node's provision token is used.

HTTP 404 Not Found is returned when the node does not exist or the token's user may not read it, or, on a high-availability setup, when this controller is not yet in sync with its peer.

Unassign a profile from a node (POST /config/node/{name}/profiles/_unassign)

Removes one profile from the node's own profile assignments.

Request

POST /config/node/node001/profiles/_unassign

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "node": {
      "node001": {
        "profile": "gpu"
      }
    }
  }
}

Response body


Response header

HTTP 204 No Content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 400 Bad Request is returned when no profile is given or the profile is not assigned to the node.

HTTP 403 Forbidden is returned when the token's user may not change the node, and when a node's provision token is used.

HTTP 404 Not Found is returned when the node does not exist or the token's user may not read it, or, on a high-availability setup, when this controller is not yet in sync with its peer.

Get the inventory summary of all nodes (GET /config/node/inventory)

Returns one summary line of hardware inventory per node that has inventory and that the token's user may read. Where a node has both an in-band snapshot (collected during installation) and a Redfish snapshot, the in-band one is shown.

Request

GET /config/node/inventory

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "node": {
      "node001": {
        "source": "inband",
        "product": "SYS-120U-TNR",
        "serial": "S41234567890123",
        "cpu_count": 2,
        "memory_mb": 262144,
        "disk_count": 2,
        "disk_total_gb": 960,
        "gpu_count": 0,
        "nic_count": 2,
        "updated": "2026-10-20 09:14:02"
      },
      "node002": {
        "source": "redfish",
        "product": "SYS-120U-TNR",
        "serial": "S41234567890124",
        "cpu_count": 2,
        "memory_mb": 262144,
        "disk_count": 2,
        "disk_total_gb": 960,
        "gpu_count": 0,
        "nic_count": 2,
        "updated": "2026-10-21 11:02:45"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not Found is returned when no node has inventory.

Get node inventory (GET /config/node/{name}/inventory)

Returns the stored hardware inventory of the node: one snapshot per source (inband from installation, redfish from an out-of-band collection), each with its disks, GPUs, network interfaces and firmware components.

Request

GET /config/node/node001/inventory

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "node": {
      "node001": {
        "inventory": [
          {
            "source": "inband",
            "manufacturer": "Supermicro",
            "product": "SYS-120U-TNR",
            "serial": "S41234567890123",
            "cpu_model": "Intel(R) Xeon(R) Gold 6338 CPU @ 2.00GHz",
            "cpu_count": 2,
            "memory_mb": 262144,
            "bios_version": "1.4",
            "bios_digest": null,
            "bios_config": null,
            "bios_config_digest": null,
            "bios_config_content": null,
            "bios_writable": null,
            "disk_count": 1,
            "disk_total_gb": 480,
            "gpu_count": 0,
            "nic_count": 1,
            "updated": "2026-10-20 09:14:02",
            "disks": [
              {
                "name": "sda",
                "size_gb": 480,
                "type": "SSD",
                "model": "SAMSUNG MZ7L3480",
                "serial": "S6KMNA0R123456"
              }
            ],
            "gpus": [],
            "nics": [
              {
                "name": "eno1",
                "mac": "3c:ec:ef:00:00:01",
                "speed_mbps": 25000,
                "capabilities": ""
              }
            ],
            "firmware": []
          },
          {
            "source": "redfish",
            "manufacturer": "Supermicro",
            "product": "SYS-120U-TNR",
            "serial": "S41234567890123",
            "cpu_model": "Intel(R) Xeon(R) Gold 6338 CPU @ 2.00GHz",
            "cpu_count": 2,
            "memory_mb": 262144,
            "bios_version": "1.4",
            "bios_digest": "5d41402abc4b2a76b9719d911017c592a6b0f1e2c3d4e5f60718293a4b5c6d7e",
            "bios_config": null,
            "bios_config_digest": null,
            "bios_config_content": null,
            "bios_writable": "1",
            "disk_count": 1,
            "disk_total_gb": 480,
            "gpu_count": 0,
            "nic_count": 1,
            "updated": "2026-10-21 11:02:45",
            "disks": [
              {
                "name": "sda",
                "size_gb": 480,
                "type": "SSD",
                "model": "SAMSUNG MZ7L3480",
                "serial": "S6KMNA0R123456"
              }
            ],
            "gpus": [],
            "nics": [
              {
                "name": "eno1",
                "mac": "3c:ec:ef:00:00:01",
                "speed_mbps": 25000,
                "capabilities": ""
              }
            ],
            "firmware": [
              {
                "name": "bmc",
                "component": "X12DPT-B6",
                "version": "01.03.12",
                "updateable": 1,
                "manufacturer": "Supermicro",
                "release_date": "",
                "software_id": "",
                "related_item": "/redfish/v1/Managers/1"
              }
            ]
          }
        ]
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when a node's provision token is used; this endpoint takes a user token.

HTTP 404 Not Found is returned when the node does not exist, the token's user may not read it, or it has no inventory.

Store a node inventory snapshot (POST /config/node/{name}/inventory)

Stores a hardware inventory snapshot for the node, replacing the previous snapshot from the same source (default inband). Counts and totals are calculated from the lists sent. The node's vendor and asset tag are updated from the snapshot, the Redfish snapshot taking precedence. This is normally called by the node during installation.

Request

POST /config/node/node001/inventory

Request header

An administrator token, or the node's own node token (see Obtain a node token via TPM attestation), is accepted.

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "node": {
      "node001": {
        "inventory": {
          "source": "inband",
          "manufacturer": "Supermicro",
          "product": "SYS-120U-TNR",
          "serial": "S41234567890123",
          "cpu_model": "Intel(R) Xeon(R) Gold 6338 CPU @ 2.00GHz",
          "cpu_count": 2,
          "memory_mb": 262144,
          "bios_version": "1.4",
          "disks": [
            {
              "name": "sda",
              "size_gb": 480,
              "type": "SSD",
              "model": "SAMSUNG MZ7L3480",
              "serial": "S6KMNA0R123456"
            }
          ],
          "gpus": [],
          "nics": [
            {
              "name": "eno1",
              "mac": "3c:ec:ef:00:00:01",
              "speed_mbps": 25000,
              "capabilities": ""
            }
          ],
          "firmware": []
        }
      }
    }
  }
}

Response body


Response header

HTTP 204 No Content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 400 Bad Request is returned when the body carries no inventory or is malformed.

HTTP 403 Forbidden is returned when a node token is used for another node, or the token's user may not change the node.

HTTP 404 Not Found is returned when the node does not exist, or, on a high-availability setup, when this controller is not yet in sync with its peer.

Collect node inventory over Redfish (GET /config/node/{name}/inventory/_redfish)

Reads the node's hardware inventory from its BMC over Redfish and stores it as the node's redfish snapshot, beside the in-band one. The node needs a BMC interface with an address and a Redfish setup; it does not need to be provisioned or powered on. The request waits for the collection.

Request

GET /config/node/node001/inventory/_redfish

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No Content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the token's user may not operate the node.

HTTP 404 Not Found is returned when the node does not exist, has no BMC address or Redfish setup, or the BMC could not be read, or, on a high-availability setup, when this controller is not yet in sync with its peer.

Collect inventory over Redfish for several nodes (POST /config/node/inventory/_redfish)

Collects and stores Redfish inventory for a hostlist or for every node of a group; give one of the two. The request returns as soon as the work is scheduled, with the number of nodes queued. Collection runs in bounded batches, and the outcome per node is reported on the returned request_id, polled with GET /control/status/{request_id}.

Request

POST /config/node/inventory/_redfish

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

A group such as "compute" may be given instead of hostlist.

{
  "config": {
    "node": {
      "hostlist": "node[001-004]"
    }
  }
}

Response body

{
  "request_id": "1761730200.1234567812314211",
  "config": {
    "node": {
      "inventory": {
        "queued": 4
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 400 Bad Request is returned when neither a hostlist nor a group is given, or the hostlist is invalid.

HTTP 403 Forbidden is returned when the token's user may not operate one or more of the nodes.

HTTP 404 Not Found is returned when the group does not exist or has no nodes.

Provision Redfish accounts for several nodes (POST /config/node/redfishaccounts/_provision)

Makes the Redfish accounts on the BMCs of a hostlist, or of every node of a group, match their Redfish setup, on demand rather than at the next installation. The request returns as soon as the work is scheduled. The outcome per node is reported on the returned request_id, polled with GET /control/status/{request_id}.

Request

POST /config/node/redfishaccounts/_provision

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

A hostlist such as "node[001-004]" may be given instead of group.

{
  "config": {
    "node": {
      "group": "compute"
    }
  }
}

Response body

{
  "request_id": "1761730260.4567890112314211",
  "config": {
    "node": {
      "accounts": {
        "queued": 4
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 400 Bad Request is returned when neither a hostlist nor a group is given, or the hostlist is invalid.

HTTP 403 Forbidden is returned when the token's user may not operate one or more of the nodes.

HTTP 404 Not Found is returned when the group does not exist or has no nodes.

Grab a BIOS configuration from a node (POST /config/node/{name}/_biosgrab)

Reads the node's BIOS settings over Redfish and stores them as the named BIOS configuration, creating it when it does not exist. Only settings the machine's attribute registry marks as portable are kept, and the configuration's exclude list is applied; the message reports how many settings were stored and how many were not carried. The request waits for the BMC.

Request

POST /config/node/node001/_biosgrab

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "node": {
      "node001": {
        "biosconfig": "compute-bios"
      }
    }
  }
}

Response body

{
  "message": "BIOS configuration compute-bios grabbed from node001: 412 setting(s) stored, 37 not carried"
}

Response header

HTTP 201 Created will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 400 Bad Request is returned when no biosconfig is given or the body is malformed.

HTTP 403 Forbidden is returned when the token's user may not operate the node, or may not change or create the BIOS configuration.

HTTP 404 Not Found is returned when the node or its BMC cannot be reached or read, the machine publishes no usable BIOS attributes or registry, or, on a high-availability setup, when this controller is not yet in sync with its peer.

Push a BIOS configuration to a node (POST /config/node/{name}/_biospush)

Queues a stored BIOS configuration to be applied to the node. biosconfig names the configuration; when it is left out, the node must have a configuration assigned to it directly (an assignment inherited from its group is not enough), and that one is used. version_match is optional, as for the group push. This is an asynchronous operation: poll the returned request_id with GET /config/status/{request_id}.

Request

POST /config/node/node001/_biospush

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "node": {
      "node001": {
        "biosconfig": "compute-bios",
        "version_match": "warn"
      }
    }
  }
}

Response body

{
  "message": "BIOS configuration compute-bios queued for 1 node(s)",
  "request_id": "1761738510.9047712345614211"
}

Response header

HTTP 200 OK will be expected to be returned with the request_id in the body.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 400 Bad Request is returned when no biosconfig is named and the node has none assigned directly, or the body is malformed.

HTTP 403 Forbidden is returned when the token's user may not operate the node or change the BIOS configuration.

HTTP 404 Not Found is returned when the node does not exist, or the configuration does not exist or holds no settings.

Preview a firmware push to a node (GET /config/node/{name}/firmware/_preview)

Answers what a firmware push to the node would do, without doing any of it. No BMC is contacted: the answer comes from the stored inventory and the firmware catalogue, so it also works for a powered-off node. The response has the same shape as the group preview.

Request

GET /config/node/node001/firmware/_preview

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "firmware": {
      "preview": {
        "ready": [
          {
            "node": "node001",
            "hardware": [
              "Supermicro",
              "X12DPT-B6"
            ],
            "components": [
              {
                "component": "BMC",
                "entry": "x12-bmc",
                "wanted": "01.04.08",
                "running": "01.03.12",
                "updateable": true,
                "imagefile": "x12-bmc-010408.bin"
              }
            ],
            "differs": [
              {
                "component": "BMC",
                "entry": "x12-bmc",
                "wanted": "01.04.08",
                "running": "01.03.12",
                "updateable": true,
                "imagefile": "x12-bmc-010408.bin"
              }
            ]
          }
        ],
        "skipped": {},
        "summary": [
          "1 node(s) would change, 0 already as the catalogue asks"
        ]
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when a node's provision token is used; this endpoint takes a user token.

HTTP 404 Not Found is returned when the node does not exist or the token's user may not read it.

Push firmware to a node (POST /config/node/{name}/_firmwarepush)

Queues a firmware update for the node when its running versions differ from the firmware catalogue. The optional component limits the push to one component. This is an asynchronous operation: poll the returned request_id with GET /config/status/{request_id}.

Request

POST /config/node/node001/_firmwarepush

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "node": {
      "node001": {
        "component": "BMC"
      }
    }
  }
}

Response body

{
  "message": "firmware update queued for 1 node(s)",
  "request_id": "1761738540.3318046927714211"
}

Response header

HTTP 200 OK will be expected to be returned with the request_id in the body.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 400 Bad Request is returned when the name or the request body is malformed.

HTTP 403 Forbidden is returned when the token's user may not operate the node or change a catalogue entry the push would apply.

HTTP 404 Not Found is returned when the node does not exist or has nothing to update.

Cluster information

The cluster endpoint mostly read-only, and can not be used to modify the configuration. All the configuration is done via the ini and will require restarting the daemon.

Only configurable items are:

  • ntp_server

  • technical_contacts

  • provisioning_method

  • provision_fallback

  • debug

Get cluster information (GET /config/cluster)

Request

GET /config/cluster

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "cluster": {
      "controller1": {
        "status": "primary",
        "ipaddr": "10.141.255.254",
        "serverport": 7050,
        "luna_config": "/trinity/local/luna/config/luna-daemon.ini"
      },
      "controller2": {
        "status": "standby",
        "ipaddr": "10.141.255.253",
        "serverport": 7050,
        "luna_config": "/trinity/local/luna/config/luna-daemon.ini"
      },
      "ntp_server": "10.141.255.252",
      "debug": false,
      "technical_contacts": "root@localhost",
      "provision_method": "torrent",
      "provision_fallback": "http"
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Update cluster information (POST /config/cluster)

Request

POST /config/cluster

Request body

{
  "config": {
    "cluster": {
      "ntp_server": "10.141.255.252",
      "debug": false,
      "technical_contacts": "root@localhost",
      "provision_method": "torrent",
      "provision_fallback": "http"
    }
  }
}

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No Content will be expected to be returned.

HTTP 400 Bad request is mandatory if the controller objects are attempted to be modified

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Export the cluster configuration (GET /config/cluster/export)

Request

GET /config/cluster/export

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "cluster": { "...": "..." },
    "network": { "...": "..." },
    "group": { "...": "..." },
    "node": { "...": "..." },
    "osimage": { "...": "..." },
    "[...]": "[...]"
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not Found is returned when the configuration could not be exported.

Import a cluster configuration (POST /config/cluster/import)

Request

POST /config/cluster/import

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "cluster": { "...": "..." },
    "network": { "...": "..." },
    "group": { "...": "..." },
    "node": { "...": "..." },
    "[...]": "[...]"
  }
}

Response body

{
  "message": "Configuration imported"
}

Response header

HTTP 201 Created will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not Found is returned when the configuration could not be imported.

Get the cluster mounts document (GET /config/cluster/mounts)

Returns only the cluster's network mounts document, the top of the cluster, group and node chain, in the same shape the full cluster information uses. The value is base64-encoded JSON; _mounts_source is cluster when a document is stored and default when none is.

Request

GET /config/cluster/mounts

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "cluster": {
      "mounts": "eyJ2ZXJzaW9uIjogMSwgIm1vdW50cyI6IFt7InBhdGgiOiAiL2RhdGEiLCAidHlwZSI6ICJuZnMiLCAic2VydmVyIjogImNvbnRyb2xsZXIiLCAic291cmNlIjogIi9leHBvcnQvZGF0YSIsICJvcHRpb25zIjogInJ3LGhhcmQifV19",
      "_mounts_source": "cluster"
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when a node's provision token is used; this endpoint takes a user token.

HTTP 404 Not Found is returned when the cluster information is not available.

Add or update a cluster mount (POST /config/cluster/mounts)

Adds one entry to the cluster's network mounts document, or updates the entry with the same path: the fields given replace those stored, the others stay. mount is a single entry as base64-encoded JSON, for example {"path": "/data", "type": "nfs", "server": "controller", "source": "/export/data", "options": "rw,hard"}. path is required and absolute; type is one of nfs (default), lustre, beegfs, gpfs, mmfs, panfs or manual; state is one of mounted, present or absent. The resulting document is validated as a whole before it is stored.

Request

POST /config/cluster/mounts

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "cluster": {
      "mount": "eyJwYXRoIjogIi9kYXRhIiwgInR5cGUiOiAibmZzIiwgInNlcnZlciI6ICJjb250cm9sbGVyIiwgInNvdXJjZSI6ICIvZXhwb3J0L2RhdGEiLCAib3B0aW9ucyI6ICJydyxoYXJkIn0="
    }
  }
}

Response body

{
  "message": "Mount /data added to the cluster."
}

Response header

HTTP 201 Created will be expected to be returned when the entry was added or updated, or the document was already as requested.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 400 Bad Request is returned when no mount is given, the entry has no path, or the resulting document is invalid.

HTTP 403 Forbidden is returned when the token's user may not change the cluster, and when a node's provision token is used.

HTTP 404 Not Found is returned when the change could not be stored, or, on a high-availability setup, when this controller is not yet in sync with its peer.

Remove a cluster mount (POST /config/cluster/mounts/_remove)

Removes the entry with the given path from the cluster's network mounts document.

Request

POST /config/cluster/mounts/_remove

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "cluster": {
      "path": "/data"
    }
  }
}

Response body


Response header

HTTP 204 No Content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 400 Bad Request is returned when no path is given or the document holds no entry at that path.

HTTP 403 Forbidden is returned when the token's user may not change the cluster, and when a node's provision token is used.

HTTP 404 Not Found is returned when the change could not be stored, or, on a high-availability setup, when this controller is not yet in sync with its peer.

Network Management

Network management covers the network configuration section of the configuration management database. It does not configure the network equipment.

Get the list of networks (GET /config/network)

Request

GET /config/network

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "network": {
      "cluster": {
        "network": "10.141.0.0/16",
        "nameserver_ip": "10.141.255.254",
        "ntp_server": "10.141.255.254",
        "gateway": "10.141.255.254",
        "comment": "Default cluster network",
        "dhcp": true,
        "dhcp_range_begin": "10.141.0.200",
        "dhcp_range_end": "10.141.0.253"
      },
      "ipmi": {
        "network": "10.148.0.0/16",
        "nameserver_ip": "10.148.255.254",
        "ntp_server": "10.148.255.254",
        "gateway": "10.148.255.254",
        "comment": "Default OOB network",
        "dhcp": false
      },
      "ib": {
        "network": "10.149.0.0/16",
        "nameserver_ip": "10.149.255.254",
        "ntp_server": "10.149.255.254",
        "gateway": "10.149.255.254",
        "comment": "Default highspeed interconnect network",
        "dhcp": false
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get network information (GET /config/network/{networkname})

Request

GET /config/network/cluster

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "network": {
      "cluster": {
        "name": "cluster",
        "network": "10.141.0.0/16",
        "gateway": "10.141.255.254",
        "nameserver_ip": "10.141.255.254",
        "ntp_server": "10.141.255.254",
        "comment": "Default cluster network",
        "dhcp": true,
        "dhcp_range_begin": "10.141.0.200",
        "dhcp_range_end": "10.141.0.253"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist

HTTP 503 Service unavailable is returned when the backend is unavailable.

Update network information (POST /config/network/{networkname})

Request

POST /config/network/cluster

Request body

{
  "config": {
    "network": {
      "cluster": {
        "newnetname": "cluster2",
        "network": "10.141.0.0/16",
        "gateway": "10.141.255.254",
        "nameserver_ip": "10.141.255.254",
        "ntp_server": "10.141.255.254",
        "comment": "Default cluster network",
        "dhcp": true,
        "dhcp_range_begin": "10.141.0.200",
        "dhcp_range_end": "10.141.0.253"
      }
    }
  }
}

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 200 OK will be expected to be returned.

HTTP 201 Created will be expected to be returned when a new object is created.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Deleting network information (GET /config/network/{networkname}/_delete)

Request

GET /config/network/cluster/_delete

Request body


Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 201 Created will be expected to be returned when a new object is created.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get IP Address information (GET /config/network/{ipaddr})

Request

GET /config/network/cluster/10.141.0.3

Request header


Response body

{
  "config": {
    "network": {
      "10.141.0.1": {
        "status": "free"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned when the query executes. The client is responsible for handling the response

HTTP 404 Not found when the IP is not in the network range (out-of-scope)

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get all taken IP address with device name (GET /config/network/{networkname}/_member)

This API will fetch all the taken IP address with there device names.

Request

GET /config/network/cluster/_member

Request header


Response body

{
  "config": {
    "network": {
      "cluster": {
        "taken": [
            {"ipaddress": "10.141.255.254", "device": "controller"},
            {"ipaddress": "10.141.0.1", "device": "node001"},
            {"ipaddress": "10.141.0.2", "device": "node003"},
            {"ipaddress": "10.141.0.3", "device": "switch001"},
            {"ipaddress": "10.141.0.4", "device": "otherdevice003"}
        ]
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned when the query executes. The client is responsible for handling the response

HTTP 404 Not found when the IP is not in the network range (out-of-scope)

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get next available IP address (GET /config/network/{networkname}/_nextfreeip)

The Next IP will search the database for the next available IP address:

  • check database for occupied nodes, otherdev addresses,

  • removing the gateway and network addresses

  • returning the first available address in the range

The client is responsible for processing this, no reservation is made.

Request

GET /config/network/cluster/_nextfreeip

Request header


Response body

{
  "config": {
    "network": {
      "cluster": {
        "nextip": "10.141.0.2"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned when the query executes. The client is responsible for handling the response

HTTP 404 Not found when the IP is not in the network range (out-of-scope)

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get the status of a single IP address (GET /config/network/{name}/{ipaddress})

Request

GET /config/network/cluster/10.141.0.10

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "network": {
      "10.141.0.10": {
        "status": "taken"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned. The reported status is either taken or free.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not Found is returned when the network does not exist or the IP address is not within its range.

Get the list of static routes (GET /config/route)

Static routes are kept in a catalogue and coupled to networks, groups and nodes. assigned lists what each route is coupled to as type/name. Only the routes the caller may read are listed.

Token is required.

Request

GET /config/route

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "route": {
      "storage": {
        "name": "storage",
        "destination": "10.149.0.0/16",
        "gateway": "10.141.255.250",
        "metric": 100,
        "device": "",
        "comment": "storage network",
        "assigned": "network/cluster,group/compute",
        "owners": "rootus",
        "usergroups": "",
        "access": "rw-r--r--"
      },
      "default": {
        "name": "default",
        "destination": "0.0.0.0/0",
        "gateway": "10.141.255.254",
        "metric": null,
        "device": "BOOTIF",
        "comment": null,
        "assigned": "",
        "owners": "rootus",
        "usergroups": "",
        "access": "rw-r--r--"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when a node's provision token is used; this endpoint takes a user token.

HTTP 404 Not found is returned when no routes are available.

Get static route information (GET /config/route/{name})

Token is required.

Request

GET /config/route/storage

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "route": {
      "storage": {
        "name": "storage",
        "destination": "10.149.0.0/16",
        "gateway": "10.141.255.250",
        "metric": 100,
        "device": "",
        "comment": "storage network",
        "assigned": "network/cluster,group/compute",
        "owners": "rootus",
        "usergroups": "",
        "access": "rw-r--r--"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when a node's provision token is used; this endpoint takes a user token.

HTTP 404 Not found is returned when the route does not exist or the caller may not read it.

Create, update or rename a static route (POST /config/route/{name})

Token is required. Fields: destination (a network in CIDR notation or a host, IPv4 or IPv6), gateway (the next-hop address, same family as the destination), device (an interface name; BOOTIF means the node's provisioning interface), metric (a number) and comment. A route needs a gateway, a device or both. An update carries only the fields that change. Renaming is done by passing the newname field.

Creating a route is for the controller account and admin users.

Request

POST /config/route/storage

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "route": {
      "storage": {
        "destination": "10.149.0.0/16",
        "gateway": "10.141.255.250",
        "metric": 100,
        "comment": "storage network"
      }
    }
  }
}

Response body

{
  "message": "Route storage created"
}

Response header

HTTP 201 Created will be expected to be returned when the route is created or renamed.

HTTP 204 No content will be expected to be returned when the route is updated.

HTTP 400 Bad request is returned when the destination is missing or invalid, neither gateway nor device is given, the gateway is not a valid address of the destination's family, the metric is not a number, the new name already exists, or the body is not valid.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the caller may not create or change the route.

HTTP 404 Not found is returned when the caller may not read the route.

Delete a static route (GET /config/route/{name}/_delete)

Token is required. A route that is still coupled to a network, group or node cannot be deleted; decouple it first. Deleting a route is for the controller account and admin users.

Request

GET /config/route/storage/_delete

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No content will be expected to be returned.

HTTP 400 Bad request is returned when the route is still coupled; the message names what it is coupled to.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the caller is not the controller account or an admin user.

HTTP 404 Not found is returned when the route does not exist.

Couple a static route (GET /config/route/{name}/{tableref}/{target}/_couple)

Token is required. Couples the route to a network, group or node: tableref is network, group or node, target its name. A node receives the routes of the most specific level that has any coupled: its own replace its group's, and its group's replace those of its networks. The caller needs read access to the route and change access to the target.

Request

GET /config/route/storage/group/compute/_couple

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "message": "Route storage coupled to group compute"
}

Response header

HTTP 201 Created will be expected to be returned, also when the route was already coupled.

HTTP 400 Bad request is returned when tableref is not network, group or node.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the caller may not change the target.

HTTP 404 Not found is returned when the route or the target does not exist.

Decouple a static route (GET /config/route/{name}/{tableref}/{target}/_decouple)

Token is required. Removes the coupling of the route to a network, group or node; the route itself stays in the catalogue.

Request

GET /config/route/storage/group/compute/_decouple

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "message": "Route storage decoupled from group compute"
}

Response header

HTTP 201 Created will be expected to be returned.

HTTP 400 Bad request is returned when tableref is not network, group or node.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the caller may not change the target.

HTTP 404 Not found is returned when the route or the target does not exist, or the route is not coupled to the target.

BMC Management

BMC management entails the ipmi settings. The actual trigger to setup the BMC is done in the group or node configuration using the setupbmc boolean.

Get the list of BMC settings (GET /config/bmcsetup)

Request

GET /config/bmcsetup

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "bmcsetup": {
      "dell": {
        "mgmtchannel": 1,
        "netchannel": 1,
        "password": "calvin",
        "username": "root",
        "userid": 2,
        "comment": "Default DELL"
      },
      "gigabyte": {
        "mgmtchannel": 1,
        "netchannel": 1,
        "password": "password",
        "username": "admin",
        "userid": 2,
        "comment": "Default Gigabyte"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get the list of nodes in BMC setup (GET /config/bmcsetup/{name}/_member)

Request

GET /config/bmcsetup/dell/_member

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "bmcsetup": {
      "ipmi": {
        "members": [
          "node001",
          "node002",
          "node003",
          "node004"
        ]
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Show BMC setup (GET /config/bmcsetup/{bmcname})

Request

GET /config/bmcsetup/dell

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "bmcsetup": {
      "dell": {
        "mgmtchannel": 1,
        "netchannel": 1,
        "password": "calvin",
        "username": "root",
        "userid": 2,
        "comment": "Default DELL"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist

HTTP 503 Service unavailable is returned when the backend is unavailable.

Create, configure or rename BMC setup (POST /config/bmcsetup/{bmcname})

Renaming is done by setting the newbmcname field.

Request

POST /config/bmcsetup/dell

Request body

{
  "config": {
    "bmcsetup": {
      "dell": {
        "newbmcname": "dell2",
        "mgmtchannel": 1,
        "netchannel": 1,
        "password": "calvin",
        "username": "root",
        "userid": 2,
        "comment": "Default DELL"
      }
    }
  }
}

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 200 OK will be expected to be returned when updating fields

HTTP 201 Created will be expected when the BMC setup is created

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist

HTTP 503 Service unavailable is returned when the backend is unavailable.

Clone BMC setup (POST /config/bmcsetup/{bmcname}/_clone)

Cloning is done by setting the newbmcname field. In this example the dell bmcsetup is cloned to dell2 .

Request

POST /config/bmcsetup/dell/_clone

Request body

{
  "config": {
    "bmcsetup": {
      "dell": {
        "newbmcname": "dell2",
        "mgmtchannel": 1,
        "netchannel": 1,
        "password": "calvin",
        "username": "root",
        "userid": 2,
        "comment": "Default DELL"
      }
    }
  }
}

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 201 Created will be expected when the BMC setup is created

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist

HTTP 503 Service unavailable is returned when the backend is unavailable.

Delete BMC setup (GET /config/bmcsetup/{bmcname}/_delete)

Removing an object is done by calling the _delete on the object.

Request

GET /config/bmcsetup/dell/_delete

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No content will be expected when the object is successfully deleted

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist

HTTP 503 Service unavailable is returned when the backend is unavailable.

Redfish management

A Redfish setup describes how Luna reaches a BMC over Redfish (scheme, port, certificate verification) and which accounts it logs in with. It is assigned to a group or a node with the redfishsetup field, the same way a BMC setup is. A node without a Redfish setup is not contacted over Redfish.

Get the list of Redfish setups (GET /config/redfishsetup)

Request

GET /config/redfishsetup

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

Only the Redfish setups the user may read are listed.

{
  "config": {
    "redfishsetup": {
      "datacentre": {
        "name": "datacentre",
        "scheme": "https",
        "port": 443,
        "verify": false,
        "comment": "Compute racks",
        "owners": "rootus",
        "usergroups": "",
        "access": "rwxrwx---",
        "accounts": [
          {
            "name": "monitor",
            "username": "monitor",
            "password": "<password>",
            "role": "ReadOnly",
            "comment": null
          },
          {
            "name": "admin",
            "username": "rfadmin",
            "password": "<password>",
            "role": "Administrator",
            "comment": null
          }
        ]
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is returned when no Redfish setup is available.

Show Redfish setup (GET /config/redfishsetup/{name})

Request

GET /config/redfishsetup/datacentre

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "redfishsetup": {
      "datacentre": {
        "name": "datacentre",
        "scheme": "https",
        "port": 443,
        "verify": false,
        "comment": "Compute racks",
        "owners": "rootus",
        "usergroups": "",
        "access": "rwxrwx---",
        "accounts": [
          {
            "name": "monitor",
            "username": "monitor",
            "password": "<password>",
            "role": "ReadOnly",
            "comment": null
          }
        ]
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist or the user may not read it.

Get the list of members of a Redfish setup (GET /config/redfishsetup/{name}/_member)

Lists the nodes and groups that have this Redfish setup assigned directly. A node that only inherits it from its group is listed through its group.

Request

GET /config/redfishsetup/datacentre/_member

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

Only the members the user may read are listed.

{
  "config": {
    "redfishsetup": {
      "datacentre": {
        "members": [
          "node node001",
          "group compute"
        ]
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is returned when the Redfish setup does not exist or has no members.

Create, configure or rename Redfish setup (POST /config/redfishsetup/{name})

Creates the Redfish setup when it does not exist, otherwise changes it. Renaming is done by setting the newredfishsetupname field; nodes and groups that use the setup keep using it under the new name.

  • scheme is https or http, and defaults to https on creation.
  • port is a number between 1 and 65535.
  • verify sets whether the BMC certificate is verified, and defaults to no on creation.
  • accounts creates or changes accounts by name. A new account needs username and password; a change carries only the fields that change. Accounts not named are left as they are; an account is removed with the account delete call.

Request

POST /config/redfishsetup/datacentre

Request body

{
  "config": {
    "redfishsetup": {
      "datacentre": {
        "scheme": "https",
        "port": 443,
        "verify": false,
        "comment": "Compute racks",
        "accounts": [
          {
            "name": "monitor",
            "username": "monitor",
            "password": "<password>",
            "role": "ReadOnly"
          },
          {
            "name": "operator",
            "username": "operator",
            "password": "<password>",
            "role": "Operator"
          }
        ]
      }
    }
  }
}

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

Empty when the Redfish setup is changed. On creation:

{
  "message": "Redfish Setup datacentre created"
}

Response header

HTTP 201 Created will be expected when the Redfish setup is created

HTTP 204 No content will be expected to be returned when updating fields or renaming

HTTP 400 Bad request is returned when the body is not valid JSON or not in this structure, a field is unknown or invalid, the port is out of range, the new name is already in use, or a new account lacks a name, username or password. When an account is refused, the Redfish setup itself, and the accounts listed before the refused one, have already been created or changed

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the user may not change or create the Redfish setup

HTTP 404 Not found is returned when a Redfish setup that does not exist is renamed

HTTP 500 Internal Server error is returned when the Redfish setup could not be created.

Clone Redfish setup (POST /config/redfishsetup/{name}/_clone)

Cloning is done by setting the newredfishsetupname field. The clone gets the settings and all accounts of the original. In this example the datacentre Redfish setup is cloned to datacentre-gpu .

Request

POST /config/redfishsetup/datacentre/_clone

Request body

{
  "config": {
    "redfishsetup": {
      "datacentre": {
        "newredfishsetupname": "datacentre-gpu"
      }
    }
  }
}

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "message": "Redfish Setup datacentre cloned to datacentre-gpu"
}

Response header

HTTP 201 Created will be expected when the Redfish setup is cloned

HTTP 400 Bad request is returned when the new name is missing or already in use, or the body is not in this structure

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the user may not create a Redfish setup

HTTP 404 Not found is mandatory if the object does not exist

Delete Redfish setup (GET /config/redfishsetup/{name}/_delete)

Removes the Redfish setup and its accounts. A Redfish setup that is assigned to a node or a group is not removed.

Request

GET /config/redfishsetup/datacentre/_delete

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No content will be expected when the object is successfully deleted

HTTP 400 Bad request is returned when the Redfish setup is still in use; the message names the nodes and groups using it

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the user may not remove the Redfish setup

HTTP 404 Not found is mandatory if the object does not exist

Delete an account from a Redfish setup (GET /config/redfishsetup/{name}/{account}/_delete)

Removes one account from the Redfish setup in Luna. The account on the BMC itself is not touched.

Request

GET /config/redfishsetup/datacentre/monitor/_delete

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No content will be expected when the account is successfully deleted

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the user may not change the Redfish setup

HTTP 404 Not found is returned when the Redfish setup or the account does not exist

BIOS configuration

A BIOS configuration is grabbed from a node over Redfish, stored under a name and pushed to other nodes of the same board type. It is created by the grab, not by a POST on the configuration itself. It is assigned to a group or a node with the biosconfig field.

Get the list of BIOS configurations (GET /config/biosconfig)

Request

GET /config/biosconfig

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

Only the BIOS configurations the user may read are listed. settings is the number of stored attributes, grabbedfrom the node the configuration was grabbed from, and grab_exclude is returned base64 encoded, as it is stored.

{
  "config": {
    "biosconfig": {
      "hpc-tuned": {
        "name": "hpc-tuned",
        "manufacturer": "Supermicro",
        "model": "X12DPG-QT6",
        "biosversion": "1.4a",
        "grabbedfrom": "node001",
        "settings": 412,
        "grab_exclude": "KkFzc2V0VGFnKiwgKlNlcmlhbE51bWJlcio=",
        "updated": "2026-10-20 09:14:52",
        "comment": "Golden node",
        "owners": "rootus",
        "usergroups": "",
        "access": "rwxrwxr--"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is returned when no BIOS configuration is available.

Show BIOS configuration (GET /config/biosconfig/{name})

Returns the summary, every stored attribute with its value, and the setting name the board gives each attribute where it gives one.

Request

GET /config/biosconfig/hpc-tuned

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "biosconfig": {
      "hpc-tuned": {
        "name": "hpc-tuned",
        "manufacturer": "Supermicro",
        "model": "X12DPG-QT6",
        "biosversion": "1.4a",
        "grabbedfrom": "node001",
        "settings": 412,
        "grab_exclude": "KkFzc2V0VGFnKiwgKlNlcmlhbE51bWJlcio=",
        "updated": "2026-10-20 09:14:52",
        "comment": "Golden node",
        "owners": "rootus",
        "usergroups": "",
        "access": "rwxrwxr--",
        "attributes": {
          "ProcessorHyperThreading": "Disabled",
          "SRIOVEnable": "Enabled"
        },
        "labels": {
          "ProcessorHyperThreading": "Hyper-Threading",
          "SRIOVEnable": "SR-IOV Support"
        }
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist or the user may not read it.

Change or rename BIOS configuration (POST /config/biosconfig/{name})

Changes an existing BIOS configuration; it does not create one. The fields that can be set are comment , grab_exclude (comma separated patterns, sent base64 encoded), newbiosname to rename, and set to change individual entries. An entry under set is named by a concept (such as hyperthreading), by the attribute name the board publishes, or by the setting name the board gives it. Entries are checked against the attribute registry of the configuration's board type, read live from a node of that type, so a BMC of that type has to be reachable. The change is all or nothing: one entry the board type cannot express refuses the whole change.

Request

POST /config/biosconfig/hpc-tuned

Request body

{
  "config": {
    "biosconfig": {
      "hpc-tuned": {
        "set": {
          "hyperthreading": "off",
          "SRIOVEnable": "Enabled"
        }
      }
    }
  }
}

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No content will be expected to be returned when the configuration is changed

HTTP 400 Bad request is returned when the body is not valid JSON or not in this structure, or set carries no entries

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the user may not change the BIOS configuration

HTTP 404 Not found is returned when the BIOS configuration does not exist, or the change is refused: a field that cannot be set, a new name that is already in use, nothing to change, an entry the board type cannot express, or no node of the board type whose registry can be read. The message says which.

Clone BIOS configuration (POST /config/biosconfig/{name}/_clone)

Cloning is done by setting the newbiosname field. The clone keeps everything the original holds, including the node it was grabbed from; comment can be set on the clone in the same request.

Request

POST /config/biosconfig/hpc-tuned/_clone

Request body

{
  "config": {
    "biosconfig": {
      "hpc-tuned": {
        "newbiosname": "hpc-tuned-gpu",
        "comment": "GPU nodes"
      }
    }
  }
}

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "message": "BIOS configuration hpc-tuned cloned to hpc-tuned-gpu"
}

Response header

HTTP 201 Created will be expected when the BIOS configuration is cloned

HTTP 400 Bad request is returned when the new name is missing or the body is not in this structure

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the user may not create a BIOS configuration

HTTP 404 Not found is returned when the BIOS configuration does not exist, or the new name is already in use

Delete BIOS configuration (GET /config/biosconfig/{name}/_delete)

A BIOS configuration that is assigned to a node or a group is not removed.

Request

GET /config/biosconfig/hpc-tuned/_delete

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No content will be expected when the object is successfully deleted

HTTP 400 Bad request is returned when the BIOS configuration is still assigned; the message names the nodes and groups it is assigned to

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the user may not remove the BIOS configuration

HTTP 404 Not found is mandatory if the object does not exist

Get the BIOS status of all nodes (GET /config/biosconfig/status)

Returns, per node, what it was last seen holding, read from the stored inventory. No BMC is contacted, so nodes that are switched off are reported too. Only nodes the user may read are listed.

Each node has a state :

  • matched: the last read found the node holding its configuration
  • pending: the node is assigned a configuration it was not last found holding
  • stale: the node holds its configuration as it was when pushed, and entries have been changed on the configuration since
  • drifted: the node matched once and its BIOS has changed since
  • collected: the BIOS has been read and matches no stored configuration
  • unknown: no Redfish inventory has been taken from the node yet

config is the configuration the node was last found holding, assigned the one it is assigned through the node or its group, and since when the inventory was last updated. summary counts the nodes per state.

Request

GET /config/biosconfig/status

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "biosconfig": {
      "status": {
        "node001": {
          "config": "hpc-tuned",
          "digest": "3f9a1c0be27d",
          "state": "matched",
          "assigned": "hpc-tuned",
          "bios_version": "1.4a",
          "since": "2026-10-21 14:02:11",
          "group": "compute"
        },
        "node002": {
          "config": "",
          "digest": "",
          "state": "unknown",
          "assigned": "hpc-tuned",
          "bios_version": "",
          "since": "",
          "group": "compute"
        }
      },
      "summary": {
        "matched": 1,
        "unknown": 1
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is returned when there are no nodes.

Get the BIOS status of a node (GET /config/biosconfig/status/{name})

The same as the status of all nodes, for one node.

Request

GET /config/biosconfig/status/node001

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "biosconfig": {
      "status": {
        "node001": {
          "config": "hpc-tuned",
          "digest": "3f9a1c0be27d",
          "state": "drifted",
          "assigned": "hpc-tuned",
          "bios_version": "1.4a",
          "since": "2026-10-21 14:02:11",
          "group": "compute"
        }
      },
      "summary": {
        "drifted": 1
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is returned when the node does not exist or the user may not read it.

Get the BIOS status of a group (GET /config/biosconfig/status/group/{name})

The same as the status of all nodes, for the nodes of one group.

Request

GET /config/biosconfig/status/group/compute

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "biosconfig": {
      "status": {
        "node001": {
          "config": "hpc-tuned",
          "digest": "3f9a1c0be27d",
          "state": "matched",
          "assigned": "hpc-tuned",
          "bios_version": "1.4a",
          "since": "2026-10-21 14:02:11",
          "group": "compute"
        },
        "node002": {
          "config": "hpc-tuned",
          "digest": "3f9a1c0be27d",
          "state": "stale",
          "assigned": "hpc-tuned",
          "bios_version": "1.4a",
          "since": "2026-10-21 14:05:37",
          "group": "compute"
        }
      },
      "summary": {
        "matched": 1,
        "stale": 1
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is returned when the group does not exist or has no nodes the user may read.

Firmware catalogue

An entry in the firmware catalogue names the hardware (manufacturer and model, as the board reports them), the component (as the board's firmware inventory names it), the version that hardware should run, and the image file. The image file is a bare file name in Luna's files directory on the active controller.

Get the firmware catalogue (GET /config/firmwarecatalog)

Request

GET /config/firmwarecatalog

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

Only the entries the user may read are listed.

{
  "config": {
    "firmwarecatalog": {
      "r181-bmc": {
        "name": "r181-bmc",
        "manufacturer": "GIGABYTE",
        "model": "R181-Z91-00",
        "component": "BMC",
        "version": "12.61.25",
        "imagefile": "rom_v12.61.25.ima_enc",
        "updated": null,
        "comment": null,
        "owners": "rootus",
        "usergroups": "",
        "access": "rwxrwxr--"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is returned when the catalogue is empty, or the user may read none of its entries.

Show firmware catalogue entry (GET /config/firmwarecatalog/{name})

Request

GET /config/firmwarecatalog/r181-bmc

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "firmwarecatalog": {
      "r181-bmc": {
        "name": "r181-bmc",
        "manufacturer": "GIGABYTE",
        "model": "R181-Z91-00",
        "component": "BMC",
        "version": "12.61.25",
        "imagefile": "rom_v12.61.25.ima_enc",
        "updated": null,
        "comment": null,
        "owners": "rootus",
        "usergroups": "",
        "access": "rwxrwxr--"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist or the user may not read it.

Create, change or rename firmware catalogue entry (POST /config/firmwarecatalog/{name})

Creates the entry when it does not exist, otherwise changes it. A new entry needs manufacturer , model , component and version . Renaming is done by setting the newfirmwarename field. imagefile must be a bare file name, and not of a type the file server only hands out with a token, as a BMC cannot present one. Whether the file is staged is checked at push time, not here.

Request

POST /config/firmwarecatalog/r181-bmc

Request body

{
  "config": {
    "firmwarecatalog": {
      "r181-bmc": {
        "manufacturer": "GIGABYTE",
        "model": "R181-Z91-00",
        "component": "BMC",
        "version": "12.61.25",
        "imagefile": "rom_v12.61.25.ima_enc"
      }
    }
  }
}

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

When the request names an image file, the message carries a note on where to stage it. A change that names no image file returns an empty body.

{
  "message": "Firmware catalogue entry r181-bmc created; note: stage rom_v12.61.25.ima_enc in /trinity/local/luna/files on the active controller. BMCs fetch it from the controller over port 7051, so the interface facing the BMC network must be in the firewall's trusted zone"
}

Response header

HTTP 201 Created will be expected when the entry is created, or changed with an image file named

HTTP 204 No content will be expected to be returned when updating fields without an image file

HTTP 400 Bad request is returned when the body is not valid JSON or not in this structure, a new entry lacks one of the required fields, a change names an unknown field, the image file name is not usable, or the new name is already in use

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the user may not change or create the entry

HTTP 404 Not found is returned when an entry that does not exist is renamed, or a change carries no fields

HTTP 500 Internal Server error is returned when the entry could not be created, for instance because the request names an unknown field.

Delete firmware catalogue entry (GET /config/firmwarecatalog/{name}/_delete)

Request

GET /config/firmwarecatalog/r181-bmc/_delete

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No content will be expected when the object is successfully deleted

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the user may not remove the entry

HTTP 404 Not found is mandatory if the object does not exist

Get the firmware update status of all nodes (GET /config/firmwarecatalog/status)

Returns the newest firmware update request per node and what became of it. This reports what was asked and its outcome, not what a node runs now. Only nodes the user may read are listed.

state is queued , in progress , done or failed . restore is pending while the node still owes a restore of its BMC settings after a flash reset its BMC; once the restore has run it holds its outcome, starting with done: or failed: followed by the message. summary counts the nodes per state. When requests exist but the user may read none of their nodes, the answer is 200 with an empty status and summary .

Request

GET /config/firmwarecatalog/status

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "firmwarecatalog": {
      "status": {
        "node001": {
          "group": "compute",
          "component": "BMC",
          "request_id": "1761736212.4825933482120113",
          "state": "done",
          "message": "node001: BMC now at the catalogue version; BMC configuration retained",
          "restore": "",
          "since": "2026-10-22 10:41:07"
        },
        "node002": {
          "group": "compute",
          "component": "BMC",
          "request_id": "1761736212.4825933482120113",
          "state": "in progress",
          "message": "",
          "restore": "",
          "since": "2026-10-22 10:35:12"
        }
      },
      "summary": {
        "done": 1,
        "in progress": 1
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is returned when no firmware update has been requested.

Get the firmware update status of a node (GET /config/firmwarecatalog/status/{name})

The same as the status of all nodes, for one node.

Request

GET /config/firmwarecatalog/status/node001

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "firmwarecatalog": {
      "status": {
        "node001": {
          "group": "compute",
          "component": "BMC",
          "request_id": "1761736212.4825933482120113",
          "state": "done",
          "message": "node001: BMC now at the catalogue version; BMC configuration retained; 2 BIOS setting(s) differ from the recorded configuration compute-bios - re-applied when the node next installs through Luna",
          "restore": "pending",
          "since": "2026-10-22 10:41:07"
        }
      },
      "summary": {
        "done": 1
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is returned when no firmware update has been requested for the node, or the node does not exist.

Get the firmware update status of a group (GET /config/firmwarecatalog/status/group/{name})

The same as the status of all nodes, for the nodes of one group.

Request

GET /config/firmwarecatalog/status/group/compute

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "firmwarecatalog": {
      "status": {
        "node001": {
          "group": "compute",
          "component": "BMC",
          "request_id": "1761736212.4825933482120113",
          "state": "failed",
          "message": "image rom_v12.61.25.ima_enc is not staged on this controller",
          "restore": "",
          "since": "2026-10-22 10:36:40"
        }
      },
      "summary": {
        "failed": 1
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is returned when the group does not exist, or no firmware update has been requested for its nodes.

Image management

Image management is mostly token based, as it made introduce breaking changes to the system.

Get a list of images (GET /config/osimage):

Request

GET /config/osimage

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "osimage": {
      "compute": {
        "grab_exclude": [
          "/dev",
          "/proc",
          "/sys"
        ],
        "grab_filesystems": [
          "/",
          "/boot"
        ],
        "initrdfile": "compute-initramfs-`uname -r`",
        "kernelfile": "compute-kernel-`uname -r`",
        "kernelmodules": "ipmi_devinft, ipmi_si, ipmi_msghandler",
        "kerneloptions": "mitigations=off nosmt noht",
        "kernelversion": "`uname -r`",
        "path": "/trinity/images/compute",
        "imagefile": "compute.tar.bz2",
        "comment": "Default image"
      },
      "compute-ib": {
        "grab_exclude": [
          "/dev",
          "/proc",
          "/sys"
        ],
        "grab_filesystems": [
          "/",
          "/boot"
        ],
        "initrdfile": "compute-initramfs-`uname -r`",
        "kernelfile": "compute-kernel-`uname -r`",
        "kernelmodules": "ipmi_devinft, ipmi_si, ipmi_msghandler",
        "kerneloptions": "mitigations=off nosmt noht",
        "kernelversion": "`uname -r`",
        "path": "/trinity/images/compute-ib",
        "imagefile": "compute.tar.bz2",
        "comment": "Default image with updated drivers"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get a list members of the osimage (GET /config/osimage/{osimage}/_member)

Request

GET /config/osimage/{osimage}/_member

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "osimage": {
      "compute-b": {
        "members": [
          "node001",
          "node002",
          "node003",
          "node004"
        ]
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get osimage information (GET /config/osimage/{osimage})

Request

GET /config/osimage/compute

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "osimage": {
      "compute": {
        "grab_exclude": [
          "/dev",
          "/proc",
          "/sys"
        ],
        "grab_filesystems": [
          "/",
          "/boot"
        ],
        "initrdfile": "compute-initramfs-`uname -r`",
        "kernelfile": "compute-kernel-`uname -r`",
        "kernelmodules": "ipmi_devinft, ipmi_si, ipmi_msghandler",
        "kerneloptions": "mitigations=off nosmt noht",
        "kernelversion": "`uname -r`",
        "path": "/trinity/images/compute",
        "imagefile": "compute.tar.bz2",
        "comment": "Default image"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 404 Not found is mandatory if the object does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Updating or creating osimage information (POST /config/osimage/{osimage})

Note that when posting to a non-existing osimage name, it will create the image with the settings submitted.

Request

POST /config/osimage/compute

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "osimage": {
      "compute": {
        "comment": "Default image",
        "distribution": "redhat",
        "grab_exclude": [
          "/dev",
          "/proc",
          "/sys"
        ],
        "grab_filesystems": [
          "/",
          "/boot"
        ],
        "initrdfile": "compute-initramfs-`uname -r`",
        "kernelfile": "compute-kernel-`uname -r`",
        "kernelmodules": "ipmi_devinft, ipmi_si, ipmi_msghandler",
        "kerneloptions": "mitigations=off nosmt noht",
        "kernelversion": "`uname -r`",
        "path": "/trinity/images/compute",
        "imagefile": "compute.tar.bz2"
      }
    }
  }
}

Response body


Response header

HTTP 204 No content will be expected to be returned.

HTTP 201 Created will be expected when a new object is created.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Delete osimage (GET /config/osimage/{osimage}/_delete)

Request

GET /config/osimage/compute/_delete

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Renaming osimage (POST /config/osimage/{osimage})

This example will rename the image compute to compute-ib.

Request

POST /config/osimage/compute/

Request body

{
  "config": {
    "osimage": {
      "compute": {
        "newosimage": "compute-ib"
      }
    }
  }
}

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the newosimage field is not set.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Cloning osimage (POST /config/osimage/{osimage}/_clone)

This example will clone the image compute to compute-ib.

Request

POST /config/osimage/compute/_clone

Request body

{
  "config": {
    "osimage": {
      "compute": {
        "newosimage": "compute-ib"
      }
    }
  }
}

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response header

HTTP 201 Created will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the newosimage field is not set.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Packing osimage (GET /config/osimage/{osimage}/_pack)

This example will pack the osimage compute.

Request

GET /config/osimage/compute/_pack

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Cancel an osimage pack (GET /config/osimage/{name}/_cancel)

Cancels a pack of the osimage that is in progress on this controller: the pack worker is stopped (and, if it ignores the request to stop, killed and the mounts below the image cleaned up), the remaining queued tasks of the same request are removed and the request is closed. The cancel acts only on the controller that runs the pack and is not replicated.

Request

GET /config/osimage/compute-image/_cancel

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "message": "cancelled pack for osimage compute-image (worker stopped)"
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the token's user may not change the osimage.

HTTP 404 Not Found is returned when no pack of the osimage is in progress, or the worker was killed but the mount cleanup failed.

Changing kernel version in osimage (incl. pack) (POST /config/osimage/{osimage}/kernel)

This example will pack the osimage compute, as well as triggering a pack afterwards.

Request

POST /config/osimage/compute/kernel

Request body

{
  "config": {
    "osimage": {
      "compute": {
        "initrdfile": "compute-initramfs-`uname -r`",
        "kernelfile": "compute-kernel-`uname -r`",
        "kernelversion": "`uname -r`"
      }
    }
  }
}

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Update the CA certificates in an osimage (GET /config/osimage/{name}/_updatecerts)

Copies the controller's RHSM CA certificates (/etc/rhsm/ca/) into the osimage, so that package management inside the image keeps working after the Satellite or Red Hat CA keys are rotated. This is an asynchronous operation: the task is queued and a request_id is returned that can be polled with GET /config/status/{request_id}. When an equal task is already queued, its request_id is returned instead. On a high-availability setup where this controller is not the master, the request is forwarded to the master and the message reflects that.

Request

GET /config/osimage/compute-image/_updatecerts

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "message": "osimage certificate update for compute-image queued",
  "request_id": "1761738600.7712093518814211"
}

Response header

HTTP 200 OK will be expected to be returned with the request_id in the body.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the token's user may not change the osimage.

HTTP 404 Not Found is returned when the osimage does not exist or the task could not be queued.

Get osimage+osimage tag information (GET /config/osimagetag)

Request

GET /config/osimagetag

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "osimagetag": {
      "versionx": {
        "name": "versionx",
        "osimage": "compute",
        "kernelfile": "compute-kernel-`uname -r`",
        "initrdfile": "compute-initramfs-`uname -r`",
        "imagefile": "uuid",
        "path": "/trinity/images/compute"
      }
    }
  }
}

Response header

​ HTTP 200 OK will be expected to be returned.

​ HTTP 404 Not found is mandatory if the object does not exist.

​ HTTP 503 Service unavailable is returned when the backend is unavailable.

Get osimage+osimage tag information (GET /config/osimagetag/{osimage})

Request

GET /config/osimagetag/compute

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "osimagetag": {
      "versionx": {
        "name": "versionx",
        "osimage": "compute",
        "kernelfile": "compute-kernel-`uname -r`",
        "initrdfile": "compute-initramfs-`uname -r`",
        "imagefile": "uuid",
        "path": "/trinity/images/compute"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 404 Not found is mandatory if the object does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Changing/creating tag in osimage (POST /config/osimage/{osimage}/tag)

Request

POST /config/osimage/compute/tag

Request body

{
  "config": {
    "osimage": {
      "compute": {
        "tag": "version1"
      }
    }
  }
}

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No content will be expected to be returned for change, create or update.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Delete osimagetag (GET /config/osimage/{osimage}/osimagetag/{tagname}/_delete)

Request

GET /config/osimage/compute/osimagetag/versionx/_delete

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Secret management

Secrets (encrypted data) may not be revealed without a valid token. The secrets endpoint is token only.

Secrets are stored on node and group level, proper resolving of the hierarchy is the responsibility of the API.

Secrets can be requested on different levels:

  • Global (list)

  • Overview of node (incl. group)

  • Overview of group

  • Single item from node

  • Single item from group

Get a list of secrets (GET /config/secrets):

Request

GET /config/secrets

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "secrets": {
      "node": {
        "node001": [
          {
            "secretname": "shared secret",
            "content": "<ENC>",
            "path": "/etc/keys.crt"
          },
          {
            "secretname": "software license",
            "content": "<ENC>",
            "path": "/etc/app/license.lic"
          },
          {
            "secretname": "shared secret",
            "content": "<ENC>",
            "path": "/etc/keys.crt"
          }
        ],
        "node002": [
          {
            "secretname": "software license",
            "content": "<ENC>",
            "path": "/etc/app/license.lic"
          }
        ]
      },
      "group": {
        "compute": [
          {
            "secretname": "Proprietary key",
            "content": "<ENC>",
            "path": "/var/lib/key.pem"
          }
        ],
        "compute-ib": [
          {
            "secretname": "Infiniband",
            "content": "<ENC>",
            "path": "/etc/rdma/license.lic"
          }
        ]
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token

HTTP 503 Service unavailable is returned when the backend is unavailable.

Retrieve all secrets for a node (GET /config/secrets/node/{node})

Token is required. Note that the secrets from the group membership must also be resolved and provided.

Request

GET /config/secrets/node/node002

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "secrets": {
      "node": {
        "node002": [
          {
            "secretname": "software license",
            "content": "<ENC>",
            "path": "/etc/app/license.lic"
          }
        ]
      },
      "group": {
        "compute-ib": [
          {
            "secretname": "Infiniband",
            "content": "<ENC>",
            "path": "/etc/rdma/license.lic"
          }
        ]
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Update all secrets for a node (POST /config/secrets/node/{node})

Request

POST /config/secrets/node/node001

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "secrets": {
      "node": {
        "node001": [
          {
            "secretname": "shared secret",
            "content": "<ENC>",
            "path": "/etc/keys.crt"
          },
          {
            "secretname": "software license",
            "content": "<ENC>",
            "path": "/etc/app/license.lic"
          },
          {
            "secretname": "shared secret",
            "content": "<ENC>",
            "path": "/etc/keys.crt"
          }
        ]
      }
    }
  }
}

Response body


Response header

HTTP 200 OK will be expected to be returned when no updates have occurred

HTTP 201 Created is expected when one or more creations have occurred

HTTP 204 No content is expected when one or more updates have occurred

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Retrieve a single secret from a node (GET /config/secrets/node/{node}/{secret})

Token is required.

Request

GET /config/secrets/node/node002/software%20license

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "secrets": {
      "node": {
        "node002": [
          {
            "secretname": "software license",
            "content": "<ENC>",
            "path": "/etc/app/license.lic"
          }
        ]
      }
    }
  }
}

Response header

HTTP 204 No content will be expected to be returned when the query executed successfully.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Updating a single secret from a node (POST /config/secrets/node/{node}/{secret})

In this example, a node and secret name must be specified.

Request

POST /config/secrets/node/node002/software%20license

Request body

{
  "config": {
    "secrets": {
      "node": {
        "node001": [
          {
            "secretname:": "software license",
            "content": "<ENC>",
            "path": "/etc/app/license.lic"
          }
        ]
      }
    }
  }
}

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

A HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token

HTTP 404 Not Found is mandatory if the object is not found

HTTP 503 Service unavailable is returned when the backend is unavailable.

Cloning a secret from a node (POST /config/secrets/node/{node}/{secret}/_clone)

In this example, a nodeand secret name must be specified.

Token is required.

Request

POST /config/secrets/node/node001/software%20license/_clone

Request body

{
  "config": {
    "secrets": {
      "node": {
        "node001": [
          {
            "secretname": "software license",
            "newsecretname": "software license2",
            "content": "<ENC>",
            "path": "/etc/app/license.lic"
          }
        ]
      }
    }
  }
}

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response header

HTTP 201 Created will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the newsecret field is not set.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Deleting a secret from a node (GET /config/secrets/node/{node}/{secret}/_delete)

In this example, a node and secret name must be specified.

Token is required.

Request

GET /config/secrets/node/node002/software%20license/_delete

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

A HTTP 204 No content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token

HTTP 404 Not Found is mandatory if the object is not found

HTTP 503 Service unavailable is returned when the backend is unavailable.

Retrieve all secrets for a group (GET /config/secrets/group/{group})

Token is required.

Request

GET /config/secrets/group/compute

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "secrets": {
    "group": {
      "compute": [
        {
          "secretname": "Proprietary key",
          "content": "<ENC>",
          "path": "/var/lib/key.pem"
        }
      ]
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Updating all secrets for a group (POST /config/secrets/group/{group})

Request

POST /config/secrets/group/compute

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "secrets": {
      "group": {
        "compute": [
          {
            "secretname": "Proprietary key",
            "content": "<ENC>",
            "path": "/var/lib/key.pem"
          }
        ]
      }
    }
  }
}

Response body


Response header

HTTP 200 OK will be expected to be returned when no updates have occurred

HTTP 201 Created is expected when one or more creations have occurred

HTTP 204 No content is expected when one or more updates have occurred

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Retrieve a single secret from a group (GET /config/secrets/group/{group}/{secret})

Token is required.

Request

GET /config/secrets/group/compute-ib/Infiniband

Request body

{
  "secrets": {
    "group": {
      "compute": null,
      "compute-ib": [
        {
          "secretname": "Infiniband",
          "content": "<ENC>",
          "path": "/etc/rdma/license.lic"
        }
      ]
    }
  }
}

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No content will be expected to be returned when the query executed successfully.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Updating a single secret from a group (POST /config/secrets/group/{group}/{secret})

In this example, a group and secret name must be specified.

Request

POST /config/secrets/group/compute-ib/Infiniband
{
  "secrets": {
    "group": {
      "compute-ib": [
        {
          "secretname": "Infiniband",
          "content": "<ENC>",
          "path": "/etc/rdma/license.lic"
        }
      ]
    }
  }
}

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

A HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token

HTTP 404 Not Found is mandatory if the object is not found

HTTP 503 Service unavailable is returned when the backend is unavailable.

Cloning a secret from a group (POST /config/secrets/group/{group}/{secret}/_clone)

In this example, a group and secret name must be specified.

Token is required.

Request

POST /config/secrets/group/compute-ib/Infiniband/_clone

Request body

{
  "secrets": {
    "group": {
      "compute-ib": [
        {
          "secretname": "Infiniband",
          "newsecretname": "Infiniband2",
          "content": "<ENC>",
          "path": "/etc/rdma/license.lic"
        }
      ]
    }
  }
}

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response header

HTTP 201 Created will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the newsecret field is not set.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Deleting a secret from a group (GET /config/secrets/group/{group}/{secret}/_delete)

In this example, a group and secret name must be specified.

Token is required.

Request

GET /config/secrets/group/compute-ib/Infiniband/_delete

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

A HTTP 204 No content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token

HTTP 404 Not Found is mandatory if the object is not found

HTTP 503 Service unavailable is returned when the backend is unavailable.

Retrieve all cluster secrets (GET /config/secrets/cluster)

Token is required. Cluster secrets apply to every node, on top of its group and node secrets. They are for the controller account and admin users only. content is base64 encoded and returned decrypted; an unset owner and mode read as root:root and 600, and resolved_owner carries the owner as numeric ids.

Request

GET /config/secrets/cluster

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "secrets": {
      "cluster": [
        {
          "name": "software license",
          "content": "<base64 content>",
          "path": "/etc/app/license.lic",
          "owner": "root:root",
          "mode": "600",
          "resolved_owner": "0:0"
        },
        {
          "name": "site key",
          "content": "<base64 content>",
          "path": "/etc/pki/site.key",
          "owner": "root:root",
          "mode": "400",
          "resolved_owner": "0:0"
        }
      ]
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the caller is not the controller account or an admin user.

HTTP 404 Not found is returned when no cluster secrets are available.

Update all cluster secrets (POST /config/secrets/cluster)

Token is required. Creates or updates the cluster secrets in the list. Every entry needs name and content; path, owner (user or user:group, names or numeric ids) and mode (octal) are optional.

Request

POST /config/secrets/cluster

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "secrets": {
      "cluster": [
        {
          "name": "software license",
          "content": "<base64 content>",
          "path": "/etc/app/license.lic",
          "owner": "root:root",
          "mode": "600"
        }
      ]
    }
  }
}

Response body

{
  "message": "Cluster Secret created"
}

Response header

HTTP 201 Created will be expected to be returned when secrets are created only, or when the message carries a warning that an owner cannot currently be resolved.

HTTP 204 No content will be expected to be returned when existing secrets are updated.

HTTP 400 Bad request is returned when the entries are not a list of objects, or an entry lacks name or content.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the caller is not the controller account or an admin user.

Retrieve a single cluster secret (GET /config/secrets/cluster/{secret})

Token is required.

Request

GET /config/secrets/cluster/software%20license

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "secrets": {
      "cluster": [
        {
          "name": "software license",
          "content": "<base64 content>",
          "path": "/etc/app/license.lic",
          "owner": "root:root",
          "mode": "600",
          "resolved_owner": "0:0"
        }
      ]
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the caller is not the controller account or an admin user.

HTTP 404 Not found is returned when the secret does not exist.

Updating a single cluster secret (POST /config/secrets/cluster/{secret})

Token is required. The body carries one entry; its name identifies the secret that is updated, or created when it does not exist. The name in the path is not compared with it and only appears in the response message. An existing secret is updated with only the fields sent; a new one needs content.

Request

POST /config/secrets/cluster/software%20license

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "secrets": {
      "cluster": [
        {
          "name": "software license",
          "mode": "640",
          "owner": "root:app"
        }
      ]
    }
  }
}

Response body


Response header

HTTP 201 Created will be expected to be returned when the secret is created, or when the message carries a warning that the owner cannot currently be resolved.

HTTP 204 No content will be expected to be returned when the secret is updated.

HTTP 400 Bad request is returned when the entries are not a list of objects, a field is not a secret field, or a new secret has no content.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the caller is not the controller account or an admin user.

HTTP 500 Internal server error is returned when the secret could not be written.

Cloning a cluster secret (POST /config/secrets/cluster/{secret}/_clone)

Token is required. The entry names the source secret in name and the copy in newsecretname. The source is taken from name; the name in the path is not compared with it and only appears in the response message. content, path, owner and mode are copied from the source unless given.

Request

POST /config/secrets/cluster/software%20license/_clone

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "secrets": {
      "cluster": [
        {
          "name": "software license",
          "newsecretname": "software license2",
          "path": "/etc/app/license2.lic"
        }
      ]
    }
  }
}

Response body

{
  "message": "Cluster Secret software license Cloned to software license2."
}

Response header

HTTP 201 Created will be expected to be returned.

HTTP 400 Bad request is returned when newsecretname is missing or already exists, or the entries are not a list of objects.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the caller is not the controller account or an admin user.

HTTP 404 Not found is returned when the source secret does not exist.

Deleting a cluster secret (GET /config/secrets/cluster/{secret}/_delete)

Token is required.

Request

GET /config/secrets/cluster/software%20license/_delete

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the caller is not the controller account or an admin user.

HTTP 404 Not found is returned when the secret does not exist.

Profile management

A profile is a named set of files, with their path, owner and mode on the node, and optionally a service on the node to act on once the files are in place. Profiles are assigned to groups and nodes and stack: a node applies its group's profiles and its own. File content is base64 encoded. See Luna profiles for how profiles are assigned and delivered.

Profiles are subject to access control: a profile the caller may not read answers 404, a missing permission answers 403.

Get a list of profiles (GET /config/profiles)

Token is required. Only the profiles the caller may read are listed.

Request

GET /config/profiles

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "profiles": {
      "motd": {
        "scope": "static",
        "service": null,
        "action": "none",
        "enabled": true,
        "files": [
          {
            "name": "motd",
            "content": "V2VsY29tZSB0byB0aGUgY29tcHV0ZSBjbHVzdGVyCg==",
            "path": "/etc/motd",
            "owner": "root:root",
            "mode": "644"
          }
        ],
        "owners": "rootus",
        "usergroups": "",
        "access": "rwxrwx---"
      },
      "sysctl-hpc": {
        "scope": "static",
        "service": "systemd-sysctl",
        "action": "restart",
        "enabled": true,
        "files": [
          {
            "name": "90-hpc.conf",
            "content": "dm0uc3dhcHBpbmVzcyA9IDEK",
            "path": "/etc/sysctl.d/90-hpc.conf",
            "owner": null,
            "mode": null
          }
        ],
        "owners": "rootus",
        "usergroups": "",
        "access": "rwxrwx---"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when a node's provision token is used; this endpoint takes a user token.

HTTP 404 Not found is returned when no profiles are available.

Get profile information (GET /config/profiles/{name})

Token is required.

Request

GET /config/profiles/sysctl-hpc

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "profiles": {
      "sysctl-hpc": {
        "scope": "static",
        "service": "systemd-sysctl",
        "action": "restart",
        "enabled": true,
        "files": [
          {
            "name": "90-hpc.conf",
            "content": "dm0uc3dhcHBpbmVzcyA9IDEK",
            "path": "/etc/sysctl.d/90-hpc.conf",
            "owner": null,
            "mode": null
          }
        ],
        "owners": "rootus",
        "usergroups": "",
        "access": "rwxrwx---"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when a node's provision token is used; this endpoint takes a user token.

HTTP 404 Not found is returned when the profile does not exist or the caller may not read it.

Get the members of a profile (GET /config/profiles/{name}/_member)

Token is required. Lists the groups that apply the profile and the nodes that apply it themselves; a node that has it only through its group is not listed. Only groups and nodes the caller may read are listed.

Request

GET /config/profiles/sysctl-hpc/_member

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "profiles": {
      "sysctl-hpc": {
        "members": {
          "groups": [
            "compute"
          ],
          "nodes": [
            "node001"
          ]
        }
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when a node's provision token is used; this endpoint takes a user token.

HTTP 404 Not found is returned when the profile does not exist or the caller may not read it.

Create, update or rename a profile (POST /config/profiles/{name})

Token is required. Profile names are lower case: a-z, 0-9, - and .. Fields: service (a systemd unit on the node), action (restart, reload, start, stop or none), enabled (false freezes the profile on the nodes), scope (static or dynamic) and files. A file is identified by name; a new file needs content and path, a change carries only what changes. owner is user or user:group, names or numeric ids (default root:root); mode is octal (default 644). Files not named in the request are left as they are. A new profile needs a service or at least one file. Renaming is done by passing the newprofilename field. A change is delivered to the running nodes that apply the profile.

Request

POST /config/profiles/sysctl-hpc

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "profiles": {
      "sysctl-hpc": {
        "service": "systemd-sysctl",
        "action": "restart",
        "files": [
          {
            "name": "90-hpc.conf",
            "content": "dm0uc3dhcHBpbmVzcyA9IDEK",
            "path": "/etc/sysctl.d/90-hpc.conf",
            "owner": "root:root",
            "mode": "644"
          }
        ]
      }
    }
  }
}

Response body

{
  "message": "Profile sysctl-hpc created"
}

Response header

HTTP 201 Created will be expected to be returned when the profile is created or renamed, or when the message carries a warning that a file owner cannot currently be resolved.

HTTP 204 No content will be expected to be returned when the profile is updated.

HTTP 400 Bad request is returned when a field is not a profile or file field, action or enabled has an invalid value, the profile would have neither a service nor a file, a new file lacks name, content or path, the new name already exists, or the body is not valid.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the caller may not create or change the profile, or when a caller that is not rootus or an admin user sets owners, usergroups or access in the body.

HTTP 404 Not found is returned when a profile to be renamed does not exist, or the caller may not read it.

HTTP 500 Internal server error is returned when the profile could not be created.

Clone a profile (POST /config/profiles/{name}/_clone)

Token is required. Cloning is done by passing the newprofilename field; the copy includes all files.

Request

POST /config/profiles/sysctl-hpc/_clone

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "profiles": {
      "sysctl-hpc": {
        "newprofilename": "sysctl-gpu"
      }
    }
  }
}

Response body

{
  "message": "Profile sysctl-hpc cloned to sysctl-gpu"
}

Response header

HTTP 201 Created will be expected to be returned.

HTTP 400 Bad request is returned when newprofilename is missing or already exists, or the body is not valid.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the caller may not create profiles, or when a caller that is not rootus or an admin user sets owners, usergroups or access in the body.

HTTP 404 Not found is returned when the profile does not exist or the caller may not read it.

Delete a profile (GET /config/profiles/{name}/_delete)

Token is required. A profile that is still assigned to a group or node cannot be deleted; unassign it first, which reverts its files on the nodes.

Request

GET /config/profiles/sysctl-hpc/_delete

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No content will be expected to be returned.

HTTP 400 Bad request is returned when the profile is still assigned; the message names the groups and nodes.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the caller may not change the profile.

HTTP 404 Not found is returned when the profile does not exist or the caller may not read it.

Delete a file from a profile (GET /config/profiles/{name}/{filename}/_delete)

Token is required. The file is reverted on the running nodes that apply the profile. The last file of a profile without a service cannot be deleted; delete the profile, or give it a service first.

Request

GET /config/profiles/sysctl-hpc/90-hpc.conf/_delete

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No content will be expected to be returned.

HTTP 400 Bad request is returned when it is the last file of a profile without a service.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the caller may not change the profile.

HTTP 404 Not found is returned when the profile or the file does not exist.

Get the profiles of a node (GET /config/profiles/node/{name})

Returns every profile the node applies, enabled or not, its group's first and then its own, in the same apply-ready form as Boot profile.

Token is required: the node's own provision token, or a user token with read access to the node.

Request

GET /config/profiles/node/node001

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "profiles": {
      "motd": {
        "scope": "static",
        "service": "",
        "action": "none",
        "enabled": true,
        "files": [
          {
            "name": "motd",
            "content": "V2VsY29tZSB0byB0aGUgY29tcHV0ZSBjbHVzdGVyCg==",
            "path": "/etc/motd",
            "owner": "root:root",
            "mode": "644",
            "resolved_owner": "0:0"
          }
        ]
      },
      "sysctl-hpc": {
        "scope": "static",
        "service": "systemd-sysctl",
        "action": "restart",
        "enabled": true,
        "files": [
          {
            "name": "90-hpc.conf",
            "content": "dm0uc3dhcHBpbmVzcyA9IDEK",
            "path": "/etc/sysctl.d/90-hpc.conf",
            "owner": "root:root",
            "mode": "644",
            "resolved_owner": "0:0"
          }
        ]
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when a provision token of another node is used.

HTTP 404 Not found is returned when the node does not exist, the caller may not read it, or it applies no profiles.

Get the profile status of all nodes (GET /config/profiles/status)

Token is required. Reports per node what it should hold, what it last accepted and what happened at the last delivery, with a count per state in summary. Only the nodes the caller may read are listed. state is one of in sync, behind (a delivery is due or under way; detail says why it waits), failed (the last delivery failed and is retried), given up (the retries are exhausted), frozen (in sync, with a disabled profile, named in frozen) and not applied (nothing assigned, nothing delivered). attempts counts the failed deliveries in a row.

Request

GET /config/profiles/status

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "profiles": {
      "status": {
        "node001": {
          "profiles": "motd,sysctl-hpc",
          "state": "in sync",
          "frozen": "",
          "detail": "",
          "since": "2026-10-28 09:12:44",
          "attempts": 0
        },
        "node002": {
          "profiles": "motd,sysctl-hpc",
          "state": "failed",
          "frozen": "",
          "detail": "<reason of the last failure>",
          "since": "2026-10-28 09:14:02",
          "attempts": 3
        },
        "node003": {
          "profiles": "",
          "state": "not applied",
          "frozen": "",
          "detail": "",
          "since": "",
          "attempts": 0
        }
      },
      "summary": {
        "in sync": 1,
        "failed": 1,
        "not applied": 1
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when a node's provision token is used; this endpoint takes a user token.

HTTP 404 Not found is returned when no nodes are available.

Get the profile status of a node (GET /config/profiles/status/{name})

Token is required. The same report for one node.

Request

GET /config/profiles/status/node002

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "profiles": {
      "status": {
        "node002": {
          "profiles": "motd,sysctl-hpc",
          "state": "failed",
          "frozen": "",
          "detail": "<reason of the last failure>",
          "since": "2026-10-28 09:14:02",
          "attempts": 3
        }
      },
      "summary": {
        "failed": 1
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when a node's provision token is used; this endpoint takes a user token.

HTTP 404 Not found is returned when the node does not exist.

Switch management

Switches are used for identifying nodes. Also creating them and assigning them an IP address will create an entry into the CMDB.

Get a list of switches (GET /config/switch):

Request

GET /config/switch

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "switch": {
      "switch01": {
        "network": "cluster",
        "ipaddress": "10.141.253.1",
        "oid": ".1.3.6.1.2.1.17.7.1.2.2.1.2",
        "read": "public",
        "rw": "private",
        "comments": "Bootswitch"
      },
      "switch02": {
        "network": "ipmi",
        "ipaddress": "10.148.253.1",
        "oid": ".1.3.6.1.2.1.17.7.1.2.2.1.2",
        "read": "public",
        "rw": "private",
        "comments": "Bootswitch"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get switch information (GET /config/switch/{switch}):

Request

GET /config/switch/switch01

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "switch": {
      "switch01": {
        "network": "cluster",
        "ipaddress": "10.141.253.1",
        "oid": ".1.3.6.1.2.1.17.7.1.2.2.1.2",
        "read": "public",
        "rw": "private",
        "comments": "Bootswitch"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token

HTTP 404 Not found is mandatory if object doesn’t exist

HTTP 503 Service unavailable is returned when the backend is unavailable.

Create or update switch information (POST /config/switch/{switch}):

Renaming the switch is done by passing the newswitchname field.

Note that a switch with the network and ipaddress configured will create an entry in the CMDB.

Request

POST /config/switch/switch01

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "switch": {
      "switch01": {
        "network": "cluster",
        "ipaddress": "10.141.253.1",
        "oid": ".1.3.6.1.2.1.17.7.1.2.2.1.2",
        "read": "public",
        "rw": "private",
        "comments": "Bootswitch"
      }
    }
  }
}

Response body


Response header

HTTP 201 Created will be expected to be returned when a switch is created

HTTP 204 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token

HTTP 503 Service unavailable is returned when the backend is unavailable.

Clone switch (POST /config/switch/{switch}/_clone):

Token is required. Cloning is done by passing the newswitchname field. Fields not given are copied from the source switch. When no ipaddress is given, the clone gets the next free address in the given network; DHCP and DNS are reloaded afterwards. Without network the clone is created without an address, with the message Switch cloned without network or ipaddress. The interfaces of the source switch are not copied. Creating a switch is for the controller account and admin users.

Request

POST /config/switch/switch01/_clone

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "switch": {
      "switch01": {
        "newswitchname": "switch02",
        "network": "cluster",
        "ipaddress": "10.141.253.2",
        "comment": "Bootswitch"
      }
    }
  }
}

Response body

{
  "message": "Switch cloned"
}

Response header

HTTP 201 Created will be expected to be returned, also when the switch is cloned without a network or address.

HTTP 400 Bad request is returned when newswitchname is missing or already exists, a field is not a switch field, the address cannot be assigned, or the body is not valid.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the caller may not create switches.

HTTP 404 Not found is returned when the source switch does not exist or the caller may not read it.

HTTP 500 Internal server error is returned when the clone clashes with an existing configuration.

Delete switch (GET /config/switch/{switch}/_delete):

Request

GET /config/switch/switch01/_delete

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get switch interfaces (GET /config/switch/{name}/interfaces)

Token is required. Lists the interfaces of the switch that have an IP address. Empty fields are left out; the management interface carries "mgmt": 1.

Request

GET /config/switch/switch01/interfaces

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "switch": {
      "switch01": {
        "interfaces": [
          {
            "interface": "eth0",
            "macaddress": "aa:bb:cc:dd:ee:01",
            "mgmt": 1,
            "ipaddress": "10.141.253.1",
            "network": "cluster"
          },
          {
            "interface": "eth1",
            "macaddress": "aa:bb:cc:dd:ee:02",
            "ipaddress": "10.148.253.1",
            "network": "ipmi"
          }
        ]
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when a node's provision token is used; this endpoint takes a user token.

HTTP 404 Not found is returned when the switch does not exist, has no interface configured, or the caller may not read it.

Get a single switch interface (GET /config/switch/{name}/interfaces/{interface})

Token is required.

Request

GET /config/switch/switch01/interfaces/eth1

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "switch": {
      "switch01": {
        "interfaces": [
          {
            "interface": "eth1",
            "macaddress": "aa:bb:cc:dd:ee:02",
            "ipaddress": "10.148.253.1",
            "network": "ipmi"
          }
        ]
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when a node's provision token is used; this endpoint takes a user token.

HTTP 404 Not found is returned when the switch or the interface does not exist, or the caller may not read the switch.

Create or update switch interfaces (POST /config/switch/{name}/interfaces)

Token is required. Each entry needs interface; macaddress, network, ipaddress, mgmt and newinterfacename (to rename) are optional. An empty ipaddress clears the interface's addresses. A switch has one management interface: "mgmt": true moves it to this interface, and the only management interface cannot be cleared. DHCP and DNS are reloaded afterwards.

Request

POST /config/switch/switch01/interfaces

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "switch": {
      "switch01": {
        "interfaces": [
          {
            "interface": "eth1",
            "macaddress": "aa:bb:cc:dd:ee:02",
            "network": "ipmi",
            "ipaddress": "10.148.253.1"
          }
        ]
      }
    }
  }
}

Response body


Response header

HTTP 204 No content will be expected to be returned.

HTTP 400 Bad request is returned when no interfaces are given, an entry lacks interface, the new interface name already exists, the only management interface would be cleared, or the body is not valid.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the caller may not change the switch.

HTTP 404 Not found is returned when the switch or the interface to rename does not exist, or the IP address cannot be assigned (no network given, or not valid in the network).

Delete a switch interface (GET /config/switch/{name}/interfaces/{interface}/_delete)

Token is required. The interface's addresses are removed with it and DHCP and DNS are reloaded. The only management interface cannot be deleted; flag another interface as management first, or delete the switch.

Request

GET /config/switch/switch01/interfaces/eth1/_delete

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No content will be expected to be returned.

HTTP 400 Bad request is returned when it is the only management interface.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the caller is not the controller account or an admin user and either lacks change access on the switch (with the default mode only its owners have it) or is not an admin or manager of a usergroup with the hardware flag that is listed on the switch.

HTTP 404 Not found is returned when the switch or the interface does not exist, or the caller may not read the switch.

Other devices management

The otherdev section is used to create entries in the CMDB, for non-bootable devices and switches. These objects are usually PDU, UPS or other externally managed devices.

Get a list of otherdev devices (GET /config/otherdev):

Request

GET /config/otherdev

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "otherdev": {
      "apc01": {
        "network": "cluster",
        "ipaddress": "10.141.250.1",
        "comments": "APC for rack01a"
      },
      "ups01": {
        "network": "ipmi",
        "ipaddress": "10.148.250.1",
        "comments": "UPS for the head node"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get otherdev information (GET /config/otherdev/{device}):

Request

GET /config/otherdev/apc01

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "otherdev": {
      "apc01": {
        "network": "cluster",
        "ipaddress": "10.141.250.1",
        "comments": "APC for rack01a"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token

HTTP 404 Not found is mandatory if object doesn’t exist

HTTP 503 Service unavailable is returned when the backend is unavailable.

Create or update otherdev information (POST/config/otherdev/{device}):

Renaming is done by passing the newotherdevname field.

Request

POST /config/otherdev/apc01

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "otherdev": {
      "apc01": {
        "network": "cluster",
        "ipaddress": "10.141.250.1",
        "comments": "APC for rack01a"
      }
    }
  }
}

Response body


Response header

HTTP 201 Created will be expected to be returned when a new device is created

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token

HTTP 503 Service unavailable is returned when the backend is unavailable.

Clone otherdev information (POST/config/otherdev/{device}/_clone):

Cloning is done by passing the newotherdevname field.

Request

POST /config/otherdev/apc01/_clone

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "otherdev": {
      "apc01": {
        "network": "cluster",
        "newotherdevname": "apc01b",
        "ipaddress": "10.141.250.1",
        "comments": "APC for rack01a"
      }
    }
  }
}

Response body


Response header

HTTP 201 Created will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token

HTTP 503 Service unavailable is returned when the backend is unavailable.

Deleting otherdev device (GET /config/otherdev/{device}/_delete):

Request

GET /config/otherdev/apc01/_delete

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body


Response header

HTTP 204 No Content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token

HTTP 503 Service unavailable is returned when the backend is unavailable.

Service management

Reload DNS

Note that Luna2 will automatically schedule a reload once changes have been made to objects which have changed the network and/or ipaddress field.

Request

GET /service/dns/reload

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 200 OK will be expected to be returned.

HTTP 204 No Content will be returned when the service is in cooldown

HTTP 401 Unauthorized is mandatory if there is no valid token

HTTP 503 Service unavailable is returned when the backend is unavailable.

Reload DHCP

Request

GET /service/dhcp/reload

Request body



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 200 OK will be expected to be returned.

HTTP 204 No Content will be returned when the service is in cooldown

HTTP 401 Unauthorized is mandatory if there is no valid token

HTTP 503 Service unavailable is returned when the backend is unavailable.

Reload Luna2

This is required when templates on the filesystem have manually changed.

Request

GET /service/luna2/reload

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 200 OK will be expected to be returned.

HTTP 204 No Content will be returned when the service is in cooldown

HTTP 401 Unauthorized is mandatory if there is no valid token

HTTP 503 Service unavailable is returned when the backend is unavailable.

Poll the result of a service action (GET /service/status/{request_id})

Request

GET /service/status/1781092799.0698555248730542

Response body

{
  "message": "2026-06-10 12:00:00 :: restarting dhcp;;2026-06-10 12:00:02 :: dhcp restarted",
  "status": 200
}

Response header

HTTP 200 OK will be expected to be returned while results are available. Poll again until the request is complete.

HTTP 404 Not Found is returned when there is no data for this request id.

Monitoring handles

Monitoring DNS service

Request

GET /monitor/service/dns

Request header


Response body

{
  "monitor": {
    "service": {
      "dns": "OK, running"
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 204 No Content will be returned when the service is in cooldown

HTTP 500 Internal Server Error is returned when the service is unavailable.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Monitoring DHCP service

Request

GET /monitor/service/dhcp

Request header


Response body

{
  "monitor": {
    "service": {
      "dns": "OK, reloaded"
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 204 No Content will be returned when the service is in cooldown

HTTP 500 Internal Server Error is returned when the service is unavailable.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Monitoring Luna2 service

Request

GET /monitor/service/luna2

Request header


Response body

{
  "monitor": {
    "service": {
      "luna2": "OK"
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 204 No Content will be returned when the service is in cooldown

HTTP 500 Internal Server Error is returned when the service is unavailable.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Node monitoring (GET /monitor/node/{node})

Request

GET /monitor/node/node001

Request header


Response body

{
  "monitor": {
    "status": {
      "node001": {
        "status": "Luna installer: No errors",
        "state": "installer.ok"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned when the node is OK

HTTP 500 Internal Server Error is when the node is not OK

HTTP 503 Service unavailable is returned when the backend is unavailable.

Node monitoring (POST /monitor/node/{node})

Meant to be called from the LUNA installer only. Once the node is only, a monitoring stack will be available.

Request

POST /monitor/node/node001

Request header



x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "monitor": {
    "status": {
      "node001": {
        "status": "Luna installer: No errors",
        "state": "installer.ok"
      }
    }
  }
}

Response body


Response header

HTTP 204 No Content will be expected when the node contents have been successfully updated

HTTP 401 Unauthorized is mandatory if there is no valid token

HTTP 404 Not Found is to be returned when the node does not exist

HTTP 503 Service unavailable is returned when the backend is unavailable.

Cluster monitoring status (GET /monitor/status)

Request

GET /monitor/status

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "monitor": {
    "status": [
      {
        "request_id": "1781082942.0591104302914211",
        "username_initiator": "admin",
        "created": "2026-06-10 09:15:42",
        "read": 0,
        "message": "osimage compute build started"
      }
    ]
  }
}

The handler returns every message still held in the status table, ordered by creation time; each entry carries request_id, username_initiator, created, read and message. When the table is empty the list is returned empty.

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Push cluster monitoring status (POST /monitor/status)

Request

POST /monitor/status

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "monitor": {
    "status": {
      "request_id": "1781082942.0591104302914211",
      "messages": [
        { "message": "osimage compute sync finished" }
      ]
    }
  }
}

This route receives remote status messages and appends them to the local status table; it is not tied to a node. The payload must contain monitor.status.request_id. Either a list of messages (each with a message, and optionally remote_request_id/remote_host) or a single remote reference (remote_request_id plus remote_host) is accepted.

Response body

{
  "message": "success"
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Node monitoring state (GET /monitor/node)

Request

GET /monitor/node

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "monitor": {
    "status": {
      "node": {
        "node001": {
          "state": "node001 ok",
          "status": "ready"
        }
      }
    }
  }
}

Each node is keyed by name and reports a state string (the node name followed by its state) and an interpreted status.

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

HA monitoring summary (GET /monitor/ha)

Request

GET /monitor/ha

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "monitor": {
    "status": {
      "ha": {
        "controller": {
          "state": "controller ok",
          "status": "active"
        }
      }
    }
  }
}

Every HA reference entry is returned, keyed by its name, with a state string and a status.

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

HA monitoring for one controller (GET /monitor/ha/{name})

Request

GET /monitor/ha/controller

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "monitor": {
    "status": {
      "controller": {
        "status": "active",
        "state": "controller ok"
      }
    }
  }
}

The single HA entry is keyed by the requested name; if no monitor row exists for it the endpoint responds with HTTP 404 Not Found.

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Mother monitoring summary (GET /monitor/mother)

Request

GET /monitor/mother

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "monitor": {
    "status": {
      "mother": {
        "controller": {
          "state": "controller ok",
          "status": "running"
        }
      }
    }
  }
}

Every mother/core reference entry is returned, keyed by its name, with a state string and a status.

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Mother monitoring for one entry (GET /monitor/mother/{name})

Request

GET /monitor/mother/controller

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "monitor": {
    "status": {
      "controller": {
        "status": "running",
        "state": "controller ok"
      }
    }
  }
}

The single mother entry is keyed by the requested name; if no monitor row exists for it the endpoint responds with HTTP 404 Not Found.

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

OS image monitoring summary (GET /monitor/osimage)

Request

GET /monitor/osimage

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "monitor": {
    "status": {
      "osimage": {
        "compute": {
          "state": "compute ok",
          "status": "built"
        }
      }
    }
  }
}

Every OS image is returned, keyed by image name, with its build/sync state string and a status.

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

OS image monitoring for one image (GET /monitor/osimage/{name})

Request

GET /monitor/osimage/compute

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "monitor": {
    "status": {
      "compute": {
        "status": "built",
        "state": "compute ok"
      }
    }
  }
}

The single image is keyed by the requested name and reports the recorded status and state; if no monitor row exists for it the endpoint responds with HTTP 404 Not Found.

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Task queue status (GET /monitor/queue)

Request

GET /monitor/queue

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "monitor": {
    "queue": [
      {
        "level": "maintask",
        "queue_id": 12,
        "request_id": "1781082942.0591104302914211",
        "username_initiator": "admin",
        "created": "2026-06-10 09:15:42",
        "subsystem": "osimage",
        "task": "pack_n_build compute",
        "status": "queued"
      }
    ]
  }
}

Each queued task is reported with a level of maintask or subtask, a queue_id, and its request_id, username_initiator, created, subsystem, task (with any parameter appended) and status.

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Sync monitoring summary (GET /monitor/sync)

Request

GET /monitor/sync

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "monitor": {
    "status": {
      "sync": {
        "compute": {
          "state": "compute ok",
          "status": "synced"
        }
      }
    }
  }
}

Sync state is derived from the OS image entries; each is keyed by image name and reports a state string and a status.

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Sync monitoring for one entry (GET /monitor/sync/{name})

Request

GET /monitor/sync/compute

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "monitor": {
    "status": {
      "compute": {
        "status": "synced",
        "state": "compute ok"
      }
    }
  }
}

The single sync entry is keyed by the requested name and reports the recorded status and state; if no monitor row exists for it the endpoint responds with HTTP 404 Not Found.

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Control API

The control API is used by the Luna tools such as lpower or any scripts to control nodes: power, chassis identification, the system event log, a one-time boot into the BIOS setup and Redfish actions. The calls below list the subsystems and actions they take.

Control a single node (GET /control/action/{subsystem}/{hostname}/_{action})

Runs one action on the BMC of one node and waits for the answer. The node needs a BMC interface and a BMC setup, assigned to the node or its group.

Subsystem Actions
power on, off, reset, cycle, status
chassis identify, noidentify
sel list, clear
nextboot bios, status, clear

nextboot sets a one-time boot into the BIOS setup and needs Redfish. The redfish subsystem needs a request body and is only available through the POST call.

Request

GET /control/action/power/node001/_on
GET /control/action/power/node001/_status
GET /control/action/chassis/node001/_identify
GET /control/action/sel/node001/_list
GET /control/action/nextboot/node001/_bios

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

No body is returned for an action that changes something. A status or list action returns the answer under the subsystem; for sel list the lines are separated by ;; .

{
  "control": {
    "power": "on"
  }
}

When the BMC refuses or fails the action, the reason is returned under the subsystem:

{
  "control": {
    "nextboot": "this system exposes no boot override"
  }
}

Response header

HTTP 200 OK will be expected for a status or list action

HTTP 204 No Content will be expected when any other action is carried out

HTTP 400 Bad request is returned when the hostname is not a valid name

HTTP 401 Unauthorized is mandatory if there is no valid token

HTTP 403 Forbidden is returned when the user may read the node but not operate it (a status action needs read only)

HTTP 404 Not Found is returned when the node does not exist, the user may not read it, it has no BMC interface, or it has no usable BMC setup

HTTP 501 Not Implemented is returned when the action failed on the BMC or is not implemented

Control a list of nodes (POST /control/action/{subsystem}/_{action})

Runs one action on the BMCs of a list of nodes, given as a hostlist. The subsystems and actions are those of the single-node call, plus redfish with the actions setting and upload . The subsystem and action that run are taken from the request body; the path should name the same, as the access check reads the action from the path.

The work runs in the background in batches. The call waits up to about three seconds and returns the results available by then, with a request_id . Poll the remaining results with GET /control/status/{request_id} until the request is complete.

Request

POST /control/action/power/_on

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "control": {
    "power": {
      "on": {
        "hostlist": "node[001-004]"
      }
    }
  }
}

A redfish action also carries the uri to work on and the content to send, as base64 encoded JSON:

{
  "control": {
    "redfish": {
      "setting": {
        "hostlist": "node[001-004]",
        "uri": "/redfish/v1/Systems/1/Bios/Settings",
        "content": "eyJBdHRyaWJ1dGVzIjogeyJQcm9jZXNzb3JIeXBlclRocmVhZGluZyI6ICJEaXNhYmxlZCJ9fQ=="
      }
    }
  }
}

Response body

ok lists the nodes where the action succeeded (for redfish , with what the BMC reports it did), on and off list the answers to power status , and failed lists the nodes that failed with the reason. In this example node002 has failed and node004 has not answered yet; its result is returned when polling:

{
  "request_id": "1761736212.4825933482120113",
  "control": {
    "power": {
      "ok": {
        "node001": "power on",
        "node003": "power on"
      },
      "on": {},
      "off": {}
    },
    "failed": {
      "node002": "host does not exist or has no BMC interface configured"
    }
  }
}

When no node has answered yet, the same shape is returned with every list empty:

{
  "request_id": "1761736212.4825933482120113",
  "control": {
    "power": {
      "ok": {},
      "on": {},
      "off": {}
    },
    "failed": {}
  }
}

Response header

HTTP 200 OK will be expected when the action has been started (incl. failed results)

HTTP 400 Bad request is returned when the body is not valid JSON or not in this structure

HTTP 401 Unauthorized is mandatory if there is no valid token

HTTP 403 Forbidden is returned when the user may not read or may not operate one or more of the nodes (a status action needs read only); the message names them

HTTP 404 Not Found is returned when the body has no hostlist, the hostlist is invalid, or a redfish action lacks a uri or content, or its content is not base64 encoded JSON

Poll the result of a control action (GET /control/status/{request_id})

Request

GET /control/status/1781085753.0374956810530542

Response body

{
  "request_id": "1781085753.0374956810530542",
  "control": {
    "power": {
      "ok": {
        "node001": "power on"
      },
      "on": {},
      "off": {}
    },
    "failed": {}
  }
}

Response header

HTTP 200 OK will be expected to be returned while results are available. Poll again until the request is complete.

HTTP 404 Not Found is returned when there is no data for this request id.

Rack View

Get all the racks in detailed view

Request

GET /config/rack

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
    "config": {
        "rack": {
            "rack001": {
                "size": 52,
                "order": "ascending",
                "room": "Basement",
                "site": "ClusterVision Amsterdam",
                "name": "rack001",
                "devices": [
                    {"name": "controller", "type": "controller", "vendor": "Supermicro", "orientation": "front", "height": 1, "position": 5},
                    {"name": "node001", "type": "node", "vendor": "Dell", "orientation": "front", "height": 2, "position": 8}
                ]
            },
            "rack002": {
                "size": 52,
                "order": "descending",
                "room": "Basement",
                "site": "ClusterVision Amsterdam",
                "name": "rack002",
                "devices": [
                    {"name": "node002", "type": "node", "vendor": "GigaByte", "orientation": "front", "height": 4, "position": 27}
                ]
            },
            "rack006": {
                "size": 42,
                "order": "descending",
                "room": "1st Floor",
                "site": "ClusterVision Schiphol",
                "name": "rack006",
                "devices": []
            }
        }
    }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get a single rack with detailed view

Request

GET /config/rack/{RACK-NAME}

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
    "config": {
        "rack": {
            "rack001": {
                "size": 52,
                "order": "ascending",
                "room": "Basement",
                "site": "ClusterVision Amsterdam",
                "name": "rack001",
                "devices": [
                    {"name": "node001", "type": "node", "vendor": "HP", "orientation": "front", "height": 1, "position": 5},
                    {"name": "node002", "type": "node", "vendor": "Lenovo", "orientation": "front", "height": 2, "position": 8}
                ]
            }
        }
    }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist

HTTP 503 Service unavailable is returned when the backend is unavailable.

Create a new or update a rack

Request

POST /config/rack/{RACK-NAME}

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
    "config": {
        "rack": {
            "rack001": {
                "size": 52,
                "order": "ascending",
                "room": "Basement",
                "site": "ClusterVision Amsterdam",
                "name": "rack001",
                "devices": [
                    {"name": "node001", "type": "node", "vendor": "HP", "orientation": "front", "height": 1, "position": 5},
                    {"name": "node002", "type": "node", "vendor": "Lenovo", "orientation": "front", "height": 2, "position": 8}
                ]
            }
        }
    }
}

Response header

HTTP 204 No content will be expected to be returned.

HTTP 201 Created will be expected when a new object is created.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get all the inventories in detailed view

Request

GET /config/rack/inventory

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
    "config": {
        "rack": {
            "inventory": [
                {"name": "node001", "type": "node", "vendor": "Dell", "height": 1, "orientation": "front"},
                {"name": "node002", "type": "node", "vendor": "Dell",  "height": 2, "orientation": "front"}
            ]
        }
    }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get all the configured or unconfigured inventories in detailed view

Request

GET /config/rack/inventory/{SUBSET}

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
    "config": {
        "rack": {
            "inventory": [
                {"name": "node001", "type": "node", "vendor": "Dell", "height": 1, "orientation": "front"},
                {"name": "node002", "type": "node", "vendor": "Dell",  "height": 2, "orientation": "front"}
            ]
        }
    }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist

HTTP 503 Service unavailable is returned when the backend is unavailable.

Update a Inventory

Request

POST /config/rack/inventory

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
    "config": {
        "rack": {
            "inventory": [
                {"name": "node001", "type": "node", "vendor": "Dell", "height": 1, "orientation": "front"},
                {"name": "node002", "type": "node", "vendor": "Dell",  "height": 2, "orientation": "front"}
            ]
        }
    }
}

Response header

HTTP 204 No content will be expected to be returned.

HTTP 201 Created will be expected when a new object is created.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Delete a Rack

Request

GET /config/rack/{RACK-NAME}/_delete 

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Delete a Inventory [Remove it from the Rack]

Request

GET /config/rack/inventory/{DEVICE_NAME}/type/{DEVICE_TYPE}/_delete

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
    "message": "Inventory cleared"
}

Response header

HTTP 201 With content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Journal

The journal carries the changes of one controller of an HA pair to the other. These calls are made by the Luna daemons themselves and need the rootus account; a pull removes the entries it returns. They are not meant for administrators or tools.

Get all the journal entries for a controller

Request

GET /journal/{controller}

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
    "journal": [
        {"function": "Node.update_node", "object": "node001", "param": null, "payload": "IyBUaGlzIGZpbGUgd2FzIGdlbmVyYXRlZCBieSB3Zy1xdWljayg4KSBmb3IgdXNlIHdpdGgKIyB0", "masteronly": 0, "remoteonly": 0, "misc": null, "sendfor": "controller2", "sendto": null, "sendby": "controller1", "tries": 0, "created": "1713520340"},
        {"function": "OSImage.pack", "object": "compute", "param": null, "payload": null, "masteronly": 1, "remoteonly": 0, "misc": "1703678426.721102268962463531", "sendfor": "controller2", "sendto": null, "sendby": "controller1", "tries": 0, "created": "1713520344"}
    ]
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is mandatory if the object does not exist

HTTP 503 Service unavailable is returned when the backend is unavailable.

Update journal with entries on controller

Request

POST /journal

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
    "journal": [
        {"function": "Node.update_node", "object": "node001", "param": null, "payload": "IyBUaGlzIGZpbGUgd2FzIGdlbmVyYXRlZCBieSB3Zy1xdWljayg4KSBmb3IgdXNlIHdpdGgKIyB0", "masteronly": 0, "remoteonly": 0, "misc": null, "sendfor": "controller2", "sendto": null, "sendby": "controller1", "tries": 0, "created": "1713520340"},
        {"function": "OSImage.pack", "object": "compute", "param": null, "payload": null, "masteronly": 1, "remoteonly": 0, "misc": "1703678426.721102268962463531", "sendfor": "controller2", "sendto": null, "sendby": "controller1", "tries": 0, "created": "1713520344"}
    ]
}

Response body

{
  "message": "success"
}

Response header

HTTP 201 Created will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 400 Bad request is returned when the request carries no journal entries or an entry has the wrong fields.

HTTP 404 Not found is returned when an entry could not be added to the journal.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get the journal for the calling controller (GET /journal)

Returns the pending journal entries addressed to the controller that makes the request, which is recognised by its source address. This is how a controller in a high-availability setup fetches the changes its peer recorded for it. The returned entries are removed from the journal, so each entry is delivered once. When the source address is not that of a known controller, every entry in the journal is returned, and removed. Only rootus and admin users may call it.

Request

GET /journal

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "journal": [
    {
      "function": "Node.update_mount",
      "object": "node001",
      "param": null,
      "payload": "eyJjb25maWciOiB7Im5vZGUiOiB7Im5vZGUwMDEiOiB7Im1vdW50IjogIi4uLiJ9fX19",
      "masteronly": 0,
      "remoteonly": 0,
      "misc": null,
      "sendfor": "controller2",
      "sendto": null,
      "sendby": "controller1",
      "tries": 0,
      "created": "1761730320"
    }
  ]
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 403 Forbidden is returned when the token's user is not rootus or an admin user.

Get journal entries for a host (GET /journal/{name})

Request

GET /journal/controller

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "journal": [
    {
      "function": "Node.update_node",
      "object": "node001",
      "payload": "[...]"
    },
    { "...": "..." }
  ]
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not Found is returned when there are no journal entries for the host.

Clear journal entries for a host (GET /journal/{name}/_delete)

Request

GET /journal/controller/_delete

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

Response header

HTTP 204 No Content will be expected to be returned when the host's journal entries are deleted.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not Found is returned when there are no journal entries to delete.

Cloud management

Get a list of clouds (GET /config/cloud)

Request

GET /config/cloud

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "cloud": {
      "aws1": {
        "name": "aws1",
        "type": "aws",
        "comment": "Production AWS account"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get a cloud (GET /config/cloud/{name})

Request

GET /config/cloud/aws1

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "cloud": {
      "aws1": {
        "name": "aws1",
        "type": "aws",
        "comment": "Production AWS account"
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is returned when the requested cloud does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Create or update a cloud (POST /config/cloud/{name})

Request

POST /config/cloud/aws1

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "cloud": {
      "aws1": {
        "type": "aws",
        "comment": "Production AWS account"
      }
    }
  }
}

To rename an existing cloud, include the newcloudname field in the body. The cloud addressed by the URI is then renamed to this value:

{
  "config": {
    "cloud": {
      "aws1": {
        "newcloudname": "aws-prod",
        "type": "aws",
        "comment": "Production AWS account"
      }
    }
  }
}

Response body

{
  "message": "Cloud aws1 created successfully"
}

Response header

HTTP 201 Created is returned when a new cloud is created.

HTTP 204 No Content is returned when an existing cloud is updated.

HTTP 400 Bad Request is returned when the request contains no data or unknown columns.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Delete a cloud (GET /config/cloud/{name}/_delete)

Request

GET /config/cloud/aws1/_delete

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "message": "Cloud aws1 removed successfully"
}

Response header

HTTP 204 No Content is returned when the cloud is removed.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is returned when the requested cloud does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

DNS management

Get DNS record(s) for a network (GET /config/dns/{name})

The {name} URI parameter is the name of the network. All additional DNS host entries belonging to that network are returned.

Request

GET /config/dns/cluster

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "dns": {
      "cluster": [
        {
          "host": "mirror",
          "ipaddress": "10.141.0.5"
        },
        {
          "host": "license",
          "ipaddress": "10.141.0.6"
        }
      ]
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is returned when the network does not exist or has no additional DNS entries.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Create or update DNS records for a network (POST /config/dns/{name})

The {name} URI parameter is the name of the network. The body carries a list of host entries; each entry must provide both a host and an ipaddress. Existing hosts on the network are updated, new hosts are inserted.

Request

POST /config/dns/cluster

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "dns": {
      "cluster": [
        {
          "host": "mirror",
          "ipaddress": "10.141.0.5"
        },
        {
          "host": "license",
          "ipaddress": "10.141.0.6"
        }
      ]
    }
  }
}

Response body

{
  "message": "DNS entries added or changed"
}

Response header

HTTP 201 Created is returned when the DNS entries are added or changed.

HTTP 400 Bad Request is returned when the request contains no data.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is returned when the network is not present in the database.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Delete a DNS record from a network (GET /config/dns/{network}/{name}/_delete)

The {network} URI parameter is the name of the network and {name} is the host entry to remove from it.

Request

GET /config/dns/cluster/mirror/_delete

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "message": "Entry removed"
}

Response header

HTTP 204 No Content is returned when the host entry is removed.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is returned when the host entry does not exist for the given network.

HTTP 503 Service unavailable is returned when the backend is unavailable.

OS user group management

Get a list of OS groups (GET /config/osgroup)

Request

GET /config/osgroup

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "osgroup": {
      "users": {
        "gidNumber": 100,
        "member": ["alice", "bob"]
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get a single OS group (GET /config/osgroup/{name})

Request

GET /config/osgroup/users

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "osgroup": {
      "users": {
        "gidNumber": 100,
        "member": ["alice", "bob"]
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is returned when the requested OS group does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Create or update an OS group (POST /config/osgroup/{name})

Request

POST /config/osgroup/users

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "osgroup": {
      "users": {
        "gidNumber": 100,
        "member": ["alice", "bob"]
      }
    }
  }
}

Response body

{
  "message": "[obol: group users created]"
}

Response header

HTTP 201 Created will be expected to be returned when a new OS group is created.

HTTP 204 No content will be expected to be returned when an existing OS group is updated.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the request data is missing or the backend is unavailable.

Delete an OS group (GET /config/osgroup/{name}/_delete)

Request

GET /config/osgroup/users/_delete

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "message": "[obol: group users deleted]"
}

Response header

HTTP 204 No content will be expected to be returned when the OS group is deleted.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is returned when the requested OS group does not exist.

OS user management

Get a list of OS users (GET /config/osuser)

Request

GET /config/osuser

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "osuser": {
      "alice": {
        "uidNumber": 1050,
        "gidNumber": 100,
        "cn": "Alice Anderson",
        "sn": "Anderson",
        "givenName": "Alice",
        "mail": "alice@controller",
        "telephoneNumber": "555-0100",
        "loginShell": "/bin/bash",
        "homeDirectory": "/home/alice",
        "memberOf": ["users"],
        "shadowExpire": -1
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get a single OS user (GET /config/osuser/{name})

Request

GET /config/osuser/alice

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "osuser": {
      "alice": {
        "uidNumber": 1050,
        "gidNumber": 100,
        "cn": "Alice Anderson",
        "sn": "Anderson",
        "givenName": "Alice",
        "mail": "alice@controller",
        "telephoneNumber": "555-0100",
        "loginShell": "/bin/bash",
        "homeDirectory": "/home/alice",
        "memberOf": ["users"],
        "shadowExpire": -1
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is returned when the requested OS user does not exist.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Create or update an OS user (POST /config/osuser/{name})

Request

POST /config/osuser/alice

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "osuser": {
      "alice": {
        "uidNumber": 1050,
        "gidNumber": 100,
        "userPassword": "s3cr3t",
        "cn": "Alice Anderson",
        "sn": "Anderson",
        "givenName": "Alice",
        "mail": "alice@controller",
        "telephoneNumber": "555-0100",
        "loginShell": "/bin/bash",
        "homeDirectory": "/home/alice",
        "memberOf": ["users"],
        "shadowExpire": -1
      }
    }
  }
}

Response body

{
  "message": "[obol: user alice created]"
}

Response header

HTTP 201 Created will be expected to be returned when a new OS user is created.

HTTP 204 No content will be expected to be returned when an existing OS user is updated.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the request data is missing or the backend is unavailable.

Delete an OS user (GET /config/osuser/{name}/_delete)

Request

GET /config/osuser/alice/_delete

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "message": "[obol: user alice deleted]"
}

Response header

HTTP 204 No content will be expected to be returned when the OS user is deleted.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not found is returned when the requested OS user does not exist.

User management (Luna)

Luna users are the identities that obtain a token through POST /token. They are not the cluster's OS accounts, which are managed under OS user management. A user is authenticated by the sources configured for the daemon (local, pam and ldap are available); a user known to an external source is created at its first login. rootus, the account defined in the daemon's configuration file, is not stored as a Luna user and is not listed.

These endpoints are for rootus and admin users, except reading what a user may access, which users may also do for themselves. A password is never returned: password_set says whether one is stored.

Get a list of Luna users (GET /config/user)

Request

GET /config/user

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "user": {
      "asmith": {
        "name": "asmith",
        "username": "asmith",
        "source": "ldap",
        "external_id": "asmith",
        "password_set": false,
        "lastlogin": "2026-10-27 14:05:51",
        "created": "2026-10-01 09:12:44",
        "createdby": "luna",
        "enabled": true,
        "admin": false,
        "delegate": false,
        "usergroups": {
          "physics": "reader"
        }
      },
      "jdoe": {
        "name": "jdoe",
        "username": "jdoe",
        "source": "local",
        "external_id": null,
        "password_set": true,
        "lastlogin": "2026-10-28 08:41:12",
        "created": "2026-09-15 10:02:37",
        "createdby": "luna",
        "enabled": true,
        "admin": false,
        "delegate": false,
        "usergroups": {
          "physics": "manager"
        }
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled.

HTTP 403 Forbidden is returned when the token does not belong to rootus or an admin user. The token of a delegate user and a node token are refused as well.

HTTP 404 Not found is returned when no Luna users exist.

Get a Luna user (GET /config/user/{name})

Request

GET /config/user/jdoe

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "user": {
      "jdoe": {
        "name": "jdoe",
        "username": "jdoe",
        "source": "local",
        "external_id": null,
        "password_set": true,
        "lastlogin": "2026-10-28 08:41:12",
        "created": "2026-09-15 10:02:37",
        "createdby": "luna",
        "enabled": true,
        "admin": false,
        "delegate": false,
        "usergroups": {
          "physics": "manager"
        }
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 400 Bad Request is returned when a name in the path contains characters that are not allowed.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled.

HTTP 403 Forbidden is returned when the token does not belong to rootus or an admin user. The token of a delegate user and a node token are refused as well.

HTTP 404 Not found is returned when the user does not exist.

Get what a Luna user may access (GET /config/user/{name}/_access)

Lists, per kind of governed object, every object the user may read and the permission bits the user holds on it (r read, w change or remove, x operate). Objects the user may not read are absent. See Object access control. rootus and admin users may ask this for any user; any other user only for themselves.

Request

GET /config/user/jdoe/_access

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "user": {
      "jdoe": {
        "access": {
          "group": {
            "compute": "rwx"
          },
          "node": {
            "node001": "rwx",
            "node002": "rwx"
          },
          "osimage": {
            "compute": "rwx",
            "default": "r--"
          },
          "network": {
            "cluster": "r--"
          }
        }
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 400 Bad Request is returned when a name in the path contains characters that are not allowed.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled. It is also returned, to any caller including rootus, when the user asked about is disabled.

HTTP 403 Forbidden is returned when a user that is not rootus or an admin user asks about another user, for the token of a delegate user, and for a node's provision token. It is also returned, to any caller including rootus, when the user asked about is a delegate user.

HTTP 404 Not found is returned when the user does not exist.

Create or update a Luna user (POST /config/user/{name})

Creates the user when it does not exist, otherwise updates it. Fields that are left out keep their value; a new user defaults to source local, enabled true, admin false and delegate false, and the caller is recorded as createdby.

  • password: stored as a salted digest; an empty value removes the stored password, so the user can only authenticate through another source.
  • source: the authentication source of the user; it cannot be changed once the user exists.
  • external_id: the user's identity in an external source.
  • admin: an admin user has every right rootus has.
  • delegate: a program that obtains tokens on behalf of other users; its own token is refused on every other endpoint.
  • newusername: renames an existing user.

Request

POST /config/user/jdoe

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "user": {
      "jdoe": {
        "password": "Secr3t-Passw0rd",
        "enabled": true,
        "admin": false
      }
    }
  }
}

To rename an existing user, include the newusername field:

{
  "config": {
    "user": {
      "jdoe": {
        "newusername": "jdoe2"
      }
    }
  }
}

Response body

{
  "message": "User jdoe created."
}

An update answers with 204 and no body.

Response header

HTTP 201 Created is returned when the user is created.

HTTP 204 No Content is returned when an existing user is updated.

HTTP 400 Bad Request is returned when the body is not valid JSON or not under config.user.{name}, holds an unknown field, changes source, sends newusername for a user that does not exist or names a user that already exists, or when a value contains characters that are not allowed.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled.

HTTP 403 Forbidden is returned when the token does not belong to rootus or an admin user. The token of a delegate user and a node token are refused as well.

HTTP 404 Not found is returned when the user could not be stored. It is also returned by a controller of an HA pair that is not in sync yet; the change is not made.

Delete a Luna user (GET /config/user/{name}/_delete)

Deletes the user and its usergroup memberships, and removes it from the owners of every object. An object whose last owner it was passes to an admin of a usergroup listed on the object, or to rootus when there is none.

Request

GET /config/user/jdoe/_delete

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No Content is returned when the user is removed.

HTTP 400 Bad Request is returned when a name in the path contains characters that are not allowed.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled.

HTTP 403 Forbidden is returned when the token does not belong to rootus or an admin user. The token of a delegate user and a node token are refused as well.

HTTP 404 Not found is returned when the user does not exist. It is also returned by a controller of an HA pair that is not in sync yet; the change is not made.

Usergroup management

Usergroups collect Luna users, each with a role, and are listed on governed objects to give their members access (see Object access control). They are neither node groups (Group configuration) nor OS groups (OS user group management). The role caps what the usergroup's permission bits grant to a member: admin and manager up to rwx, operator up to r-x, reader up to r--. Admins and managers of any usergroup may create groups, osimages and profiles; with the usergroup's hardware flag also nodes, BMC, Redfish, BIOS and firmware objects, and change the hardware fields of the nodes and groups the usergroup is listed on.

The usergroup map turns the groups a user has in an external authentication source into memberships: at every login through that source, the memberships it gave before are replaced by what the map says now. Memberships added by hand are left alone.

Listing, showing, changing and deleting usergroups and the map is for rootus and admin users. The members of a usergroup are managed by rootus, admin users and the members holding the admin role in that usergroup.

Get a list of usergroups (GET /config/usergroup)

Request

GET /config/usergroup

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "usergroup": {
      "chemistry": {
        "name": "chemistry",
        "comment": "Chemistry department",
        "hardware": false,
        "members": {
          "bkumar": "admin",
          "jdoe": "reader"
        }
      },
      "physics": {
        "name": "physics",
        "comment": "Physics department",
        "hardware": true,
        "members": {
          "asmith": "reader",
          "jdoe": "manager"
        }
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled.

HTTP 403 Forbidden is returned when the token does not belong to rootus or an admin user. The token of a delegate user and a node token are refused as well.

HTTP 404 Not found is returned when no usergroups exist.

Get a usergroup (GET /config/usergroup/{name})

Request

GET /config/usergroup/physics

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "usergroup": {
      "physics": {
        "name": "physics",
        "comment": "Physics department",
        "hardware": true,
        "members": {
          "asmith": "reader",
          "jdoe": "manager"
        }
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 400 Bad Request is returned when a name in the path contains characters that are not allowed.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled.

HTTP 403 Forbidden is returned when the token does not belong to rootus or an admin user. The token of a delegate user and a node token are refused as well.

HTTP 404 Not found is returned when the usergroup does not exist.

Get what a usergroup may access (GET /config/usergroup/{name}/_access)

Lists, per kind of governed object, every object the usergroup is listed on and the permission bits each role in the usergroup holds there.

Request

GET /config/usergroup/physics/_access

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "usergroup": {
      "physics": {
        "access": {
          "node": {
            "node001": {
              "admin": "rwx",
              "manager": "rwx",
              "operator": "r-x",
              "reader": "r--"
            }
          },
          "osimage": {
            "compute": {
              "admin": "rwx",
              "manager": "rwx",
              "operator": "r-x",
              "reader": "r--"
            }
          }
        }
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 400 Bad Request is returned when a name in the path contains characters that are not allowed.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled.

HTTP 403 Forbidden is returned when the token does not belong to rootus or an admin user. The token of a delegate user and a node token are refused as well.

HTTP 404 Not found is returned when the usergroup does not exist.

Create or update a usergroup (POST /config/usergroup/{name})

Creates the usergroup when it does not exist, otherwise updates it. The fields are comment, hardware (default false) and, to rename an existing usergroup, newusergroupname. Members are not part of this body; they are added and removed one at a time through the members endpoints.

Request

POST /config/usergroup/physics

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "usergroup": {
      "physics": {
        "comment": "Physics department",
        "hardware": true
      }
    }
  }
}

Response body

{
  "message": "Usergroup physics created."
}

An update answers with 204 and no body.

Response header

HTTP 201 Created is returned when the usergroup is created.

HTTP 204 No Content is returned when an existing usergroup is updated.

HTTP 400 Bad Request is returned when the body is not valid JSON or not under config.usergroup.{name}, holds an unknown field, sends newusergroupname for a usergroup that does not exist or names a usergroup that already exists, or when a value contains characters that are not allowed.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled.

HTTP 403 Forbidden is returned when the token does not belong to rootus or an admin user. The token of a delegate user and a node token are refused as well.

HTTP 404 Not found is returned when the usergroup could not be stored. It is also returned by a controller of an HA pair that is not in sync yet; the change is not made.

Delete a usergroup (GET /config/usergroup/{name}/_delete)

Deletes the usergroup, its memberships and its map entries, and removes it from the usergroups of every object.

Request

GET /config/usergroup/physics/_delete

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body


Response header

HTTP 204 No Content is returned when the usergroup is removed.

HTTP 400 Bad Request is returned when a name in the path contains characters that are not allowed.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled.

HTTP 403 Forbidden is returned when the token does not belong to rootus or an admin user. The token of a delegate user and a node token are refused as well.

HTTP 404 Not found is returned when the usergroup does not exist. It is also returned by a controller of an HA pair that is not in sync yet; the change is not made.

Get the members of a usergroup (GET /config/usergroup/{name}/members)

Request

GET /config/usergroup/physics/members

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "usergroup": {
      "physics": {
        "members": {
          "asmith": "reader",
          "jdoe": "manager"
        }
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 400 Bad Request is returned when a name in the path contains characters that are not allowed.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled.

HTTP 403 Forbidden is returned when the token does not belong to rootus, an admin user or a member with the admin role in this usergroup, for the token of a delegate user, and for a node's provision token.

HTTP 404 Not found is returned when the usergroup does not exist.

Add a member to a usergroup or change its role (POST /config/usergroup/{name}/members)

Adds one existing Luna user to the usergroup with a role, or changes the role of a member. username and role (admin, manager, operator or reader) are required; source is optional and defaults to local.

Request

POST /config/usergroup/physics/members

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "usergroup": {
      "physics": {
        "username": "asmith",
        "role": "operator"
      }
    }
  }
}

Response body

{
  "message": "Member asmith added to usergroup physics as operator."
}

Changing the role of an existing member answers with 204 and no body.

Response header

HTTP 201 Created is returned when the user is added to the usergroup.

HTTP 204 No Content is returned when the role of an existing member is changed.

HTTP 400 Bad Request is returned when the body is not valid JSON or not under config.usergroup.{name}, username is missing or role is not one of the four roles.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled.

HTTP 403 Forbidden is returned when the token does not belong to rootus, an admin user or a member with the admin role in this usergroup, for the token of a delegate user, and for a node's provision token.

HTTP 404 Not found is returned when the usergroup or the user does not exist. It is also returned by a controller of an HA pair that is not in sync yet; the change is not made.

Remove a member from a usergroup (POST /config/usergroup/{name}/members/_remove)

Request

POST /config/usergroup/physics/members/_remove

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "usergroup": {
      "physics": {
        "username": "asmith"
      }
    }
  }
}

Response body


Response header

HTTP 204 No Content is returned when the member is removed.

HTTP 400 Bad Request is returned when the body is not valid JSON or not under config.usergroup.{name}, or username is missing.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled.

HTTP 403 Forbidden is returned when the token does not belong to rootus, an admin user or a member with the admin role in this usergroup, for the token of a delegate user, and for a node's provision token.

HTTP 404 Not found is returned when the usergroup or the user does not exist, or the user is not a member of the usergroup. It is also returned by a controller of an HA pair that is not in sync yet; the change is not made.

Get the usergroup map (GET /config/usergroupmap)

Request

GET /config/usergroupmap

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "usergroupmap": [
      {
        "source": "ldap",
        "external_group": "physics-staff",
        "usergroup": "physics",
        "role": "manager"
      },
      {
        "source": "ldap",
        "external_group": "physics-students",
        "usergroup": "physics",
        "role": "reader"
      }
    ]
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled.

HTTP 403 Forbidden is returned when the token does not belong to rootus or an admin user. The token of a delegate user and a node token are refused as well.

HTTP 404 Not found is returned when the map has no entries.

Add or change a usergroup map entry (POST /config/usergroupmap)

An entry is identified by source and external_group. When it exists, its usergroup and role are changed; otherwise it is created. All four fields are required; role is admin, manager, operator or reader.

Request

POST /config/usergroupmap

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "usergroupmap": {
      "source": "ldap",
      "external_group": "physics-staff",
      "usergroup": "physics",
      "role": "manager"
    }
  }
}

Response body

{
  "message": "Map entry ldap physics-staff created."
}

Changing an existing entry answers with 204 and no body.

Response header

HTTP 201 Created is returned when the entry is created.

HTTP 204 No Content is returned when an existing entry is changed.

HTTP 400 Bad Request is returned when the body is not valid JSON or not under config.usergroupmap, source or external_group is missing, external_group contains a quote, or role is not one of the four roles.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled.

HTTP 403 Forbidden is returned when the token does not belong to rootus or an admin user. The token of a delegate user and a node token are refused as well.

HTTP 404 Not found is returned when the usergroup does not exist. It is also returned by a controller of an HA pair that is not in sync yet; the change is not made.

Remove a usergroup map entry (POST /config/usergroupmap/_remove)

Request

POST /config/usergroupmap/_remove

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "usergroupmap": {
      "source": "ldap",
      "external_group": "physics-staff"
    }
  }
}

Response body


Response header

HTTP 204 No Content is returned when the entry is removed.

HTTP 400 Bad Request is returned when the body is not valid JSON or not under config.usergroupmap, source or external_group is missing, or external_group contains a quote.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled.

HTTP 403 Forbidden is returned when the token does not belong to rootus or an admin user. The token of a delegate user and a node token are refused as well.

HTTP 404 Not found is returned when the entry does not exist. It is also returned by a controller of an HA pair that is not in sync yet; the change is not made.

Object access control

Every governed object carries owners, usergroups and an access mode, much as a file does. What a caller may do with an object is decided in this order: rootus and admin users may do everything; an owner holds the owner bits; a member of a usergroup listed on the object holds the usergroup bits, capped by the highest role it has in those usergroups; anyone else holds the other bits. r is read, w change or remove, x operate (power, provisioning and similar actions). An object the caller may not read answers 404 Not found, as if it did not exist; a missing w or x answers 403 Forbidden. An object without owners is owned by rootus.

The governed entities and their default mode are: node, group, bmcsetup, redfishsetup and profile rwxrwx---; osimage, biosconfig and firmwarecatalog rwxrwxr--; cluster, network, route, cloud, switch, rack and otherdevices rw-r--r--. Listings and shows of these objects include owners, usergroups and access.

Owners, usergroups and the mode are changed with the three endpoints below only: a create or update body that names them is refused for anyone but rootus and admin users. {entity} is the entity name as listed above (for example profile and otherdevices), and the body carries the object under config.{entity}.{objectname}. The caller needs read access on the object.

Change the access mode of an object (POST /config/{entity}/{objectname}/_chmod)

Sets the mode as ls shows it, nine characters such as rwxr-x---, or as three octal digits such as 750. Allowed for rootus, admin users, the owners of the object and the members with the admin role in a usergroup listed on it.

Request

POST /config/node/node001/_chmod

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "node": {
      "node001": {
        "access": "rwxr-x---"
      }
    }
  }
}

Response body


Response header

HTTP 204 No Content is returned when the mode is changed.

HTTP 400 Bad Request is returned when the body is not valid JSON or has no config object, access is missing or is not a valid mode, or when {entity} is not a governed entity or a name in the path contains characters that are not allowed. For a caller that is not rootus or an admin user, an object it may not read and an {entity} that is not governed answer 404 before the body is checked.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled.

HTTP 403 Forbidden is returned when the caller is not rootus, an admin user, an owner of the object or a usergroup admin on it, for the token of a delegate user, and for a node's provision token.

HTTP 404 Not found is returned when the object does not exist or the caller may not read it. It is also returned by a controller of an HA pair that is not in sync yet; the change is not made.

Change the usergroups of an object (POST /config/{entity}/{objectname}/_chgrp)

usergroups is a list of usergroup names, or the same as one comma-separated string. Names without a prefix replace the current list; +name adds a usergroup and -name removes one. rootus and admin users may set any usergroup; owners of the object and usergroup admins on it may add only usergroups they are a member of themselves.

Request

POST /config/node/node001/_chgrp

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "node": {
      "node001": {
        "usergroups": [
          "+physics",
          "-chemistry"
        ]
      }
    }
  }
}

Response body


Response header

HTTP 204 No Content is returned when the request is accepted, also when it leaves the list as it was, for example +name for a usergroup already listed.

HTTP 400 Bad Request is returned when the body is not valid JSON or has no config object, usergroups is missing or empty, a usergroup does not exist, or when {entity} is not a governed entity or a name in the path contains characters that are not allowed. For a caller that is not rootus or an admin user, an object it may not read and an {entity} that is not governed answer 404 before the body is checked.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled.

HTTP 403 Forbidden is returned when the request changes the list and the caller is not rootus, an admin user, an owner of the object or a usergroup admin on it, when it adds a usergroup it is not a member of, for the token of a delegate user, and for a node's provision token.

HTTP 404 Not found is returned when the object does not exist or the caller may not read it. It is also returned by a controller of an HA pair that is not in sync yet; the change is not made.

Change the owners of an object (POST /config/{entity}/{objectname}/_chown)

owners is a list of usernames, or the same as one comma-separated string, with the same +name and -name forms as _chgrp. rootus and admin users may set any owner; members with the admin role in a usergroup listed on the object may only make members of such a usergroup owner. An object left without owners is owned by rootus.

Request

POST /config/node/node001/_chown

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "config": {
    "node": {
      "node001": {
        "owners": "jdoe,asmith"
      }
    }
  }
}

Response body


Response header

HTTP 204 No Content is returned when the owners are changed.

HTTP 400 Bad Request is returned when the body is not valid JSON or has no config object, owners is missing or empty, a user does not exist, or when {entity} is not a governed entity or a name in the path contains characters that are not allowed. For a caller that is not rootus or an admin user, an object it may not read and an {entity} that is not governed answer 404 before the body is checked.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled.

HTTP 403 Forbidden is returned when the caller is not rootus, an admin user or a usergroup admin on the object, when a new owner is not a member of a usergroup the caller administers on it, for the token of a delegate user, and for a node's provision token.

HTTP 404 Not found is returned when the object does not exist or the caller may not read it. It is also returned by a controller of an HA pair that is not in sync yet; the change is not made.

High Availability

HA liveness check (GET /ping)

Request

GET /ping

This endpoint requires no token; it always replies with a small JSON acknowledgement and updates the controller's internal ping timestamp.

Response body

{
  "message": "pong"
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 503 Service unavailable is returned when the backend is unavailable.

HA state (GET /ha/state)

Request

GET /ha/state

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Returns the full HA record of this controller. The boolean flags (master, syncimages, enabled, insync, overrule) are normalised to true/false; updated holds the timestamp of the last state change.

Response body

{
  "ha": {
    "enabled": true,
    "syncimages": true,
    "insync": true,
    "sharedip": false,
    "overrule": false,
    "master": true,
    "updated": "2025-01-01 00:00:00"
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not Found is returned when HA is not available; the body is then {"message": "HA not available"}.

HA master role (GET /ha/master)

Request

GET /ha/master

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Returns whether this controller currently holds the master role (the boolean value of the master flag).

Response body

{
  "message": true
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not Found is returned when the controller does not hold the master role.

Become HA master (GET /ha/master/_set)

Request

GET /ha/master/_set

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Sets the current controller as master. It first forces the insync flag to true, then records the role-change request and sets the master role. The body is a single message describing the outcome.

Response body

{
  "message": "current role set to master"
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the role could not be set to master (for example when insync could not be set, or the role change failed). The message then describes the reason.

Set HA overrule flag (GET /ha/overrule/_set)

Request

GET /ha/overrule/_set

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Sets the overrule flag, allowing this controller to proceed even when it is out of sync. Intended only for the case where all controllers are down and a single one is brought back up; use with caution. The body carries the boolean result of setting the flag.

Response body

{
  "message": true
}

Response header

HTTP 204 No Content will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

List HA controllers (GET /ha/controllers)

Request

GET /ha/controllers

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Returns the HA state and configuration for every known controller. The local controller reports its own HA record directly; every other controller is queried over /ha/state. Each entry also carries a config block with its shadow/beacon settings, and an explanatory comment when a controller could not be reached.

Response body

{
  "message": {
    "controller": {
      "ha": {
        "enabled": true,
        "master": true,
        "insync": true,
        "syncimages": true,
        "sharedip": false,
        "overrule": false,
        "updated": "2025-01-01 00:00:00"
      },
      "config": {
        "shadow": false,
        "beacon": false
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not Found is returned when no controller data is available.

Sync image to controller (GET /ha/syncimage/{name})

Request

GET /ha/syncimage/image001

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

This endpoint is deprecated. Image synchronisation is now handled inline by the daemon, so the handler no longer triggers a sync and always reports that the operation is unavailable. The {name} path segment is validated as a name but is otherwise unused.

Response body

{
  "message": "sync not available for images"
}

Response header

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not Found is returned, as image sync is no longer offered through this endpoint.

File downloads

List downloadable files (GET /files)

Request

GET /files

Response body

[
  "compute-image-20240101.tar.bz2",
  "compute-image-20240101.torrent"
]

Response header

HTTP 200 OK will be expected to be returned.

HTTP 503 Service unavailable is returned when no files are present or the backend is unavailable.

Download a file (GET /files/{filename})

This endpoint streams the requested file from the configured image-files directory. Authentication is enforced inside the handler only for image and torrent extensions (.gz, .tar, .bz, .bz2, .torrent); for those a valid token must be supplied in the x-access-tokens header. Other extensions are served without a token, since some files are fetched during early boot (PXE, kernel, ramdisk) before a token is available.

Request

GET /files/compute-image-20240101.tar.bz2

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

[... binary file stream ...]

Response header

HTTP 200 OK will be expected to be returned, with the file delivered as a binary stream.

HTTP 401 Unauthorized is returned for image/torrent files when the token is missing or invalid.

HTTP 503 Service unavailable is returned when the file cannot be served.

Authenticated file-access check (GET /filesauth)

This endpoint performs an authentication subrequest (for example, an nginx auth_request). It inspects the X-Original-URI header to determine the requested file and enforces a token only for image and torrent extensions (.gz, .tar, .bz, .bz2, .torrent). For all other URIs it returns a "go" without a token. When authentication is required, a valid token must be present in the x-access-tokens header.

Request

GET /filesauth

Request header

X-Original-URI: /files/compute-image-20240101.tar.bz2
x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "message": "Go"
}

Response header

HTTP 200 OK will be expected to be returned when access is granted.

HTTP 401 Unauthorized is returned when authentication is required but the token is missing or invalid.

Database tables

Get hashes of all tables (GET /table/hashes)

Request

GET /table/hashes

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "table": {
    "hashes": {
      "node": "8f14e45fceea167a5a36dedd4bea2543",
      "group": "c9f0f895fb98ab9159f51fd0297e236d",
      "...": "..."
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Get raw data for one table (GET /table/data/{name})

Request

GET /table/data/node

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "table": {
    "data": {
      "node": [
        {
          "id": 1,
          "name": "node001",
          "...": "..."
        }
      ]
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 503 Service unavailable is returned when the backend is unavailable.

Artefact checksums

The SHA-256 checksums of the artefacts a controller holds on disk: for an osimage, its image file, kernel and initramfs. A checksum is recorded where the artefact is built, or pulled from the other controller of an HA pair, which uses these endpoints to verify what it pulled. Checksums describe the files on the controller that answers and are not replicated. The endpoints are read-only and for rootus and admin users.

Get all artefact checksums (GET /hash)

Request

GET /hash

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "hash": {
      "osimage": {
        "compute": {
          "compute-1760970728.tar.bz2": {
            "hash": "9f2c4e1b7a3d5c8e0f6a2b4d6e8f0a1c3e5b7d9f1a3c5e7b9d1f3a5c7e9b1d3f",
            "hashtype": "sha256",
            "created": "2026-10-20 14:32:08"
          },
          "compute-1760970951-vmlinuz-5.14.0-570.el9.x86_64": {
            "hash": "4b8d2f6a0c4e8b2d6f0a4c8e2b6d0f4a8c2e6b0d4f8a2c6e0b4d8f2a6c0e4b8d",
            "hashtype": "sha256",
            "created": "2026-10-20 14:35:51"
          },
          "compute-1760970951-initramfs-5.14.0-570.el9.x86_64": {
            "hash": "e1c3a5b7d9f1e3c5a7b9d1f3e5c7a9b1d3f5e7c9a1b3d5f7e9c1a3b5d7f9e1c3",
            "hashtype": "sha256",
            "created": "2026-10-20 14:35:51"
          }
        },
        "login": {
          "login-1760971502.tar.bz2": {
            "hash": "7a9c1e3b5d7f9a1c3e5b7d9f1a3c5e7b9d1f3a5c7e9b1d3f5a7c9e1b3d5f7a9c",
            "hashtype": "sha256",
            "created": "2026-10-20 14:45:02"
          }
        }
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled.

HTTP 403 Forbidden is returned when the token does not belong to rootus or an admin user. The token of a delegate user and a node token are refused as well.

HTTP 404 Not found is returned when this controller holds no checksums.

Get the checksums of an object (GET /hash/{object_type}/{name})

Request

GET /hash/osimage/compute

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "hash": {
      "osimage": {
        "compute": {
          "compute-1760970728.tar.bz2": {
            "hash": "9f2c4e1b7a3d5c8e0f6a2b4d6e8f0a1c3e5b7d9f1a3c5e7b9d1f3a5c7e9b1d3f",
            "hashtype": "sha256",
            "created": "2026-10-20 14:32:08"
          },
          "compute-1760970951-vmlinuz-5.14.0-570.el9.x86_64": {
            "hash": "4b8d2f6a0c4e8b2d6f0a4c8e2b6d0f4a8c2e6b0d4f8a2c6e0b4d8f2a6c0e4b8d",
            "hashtype": "sha256",
            "created": "2026-10-20 14:35:51"
          },
          "compute-1760970951-initramfs-5.14.0-570.el9.x86_64": {
            "hash": "e1c3a5b7d9f1e3c5a7b9d1f3e5c7a9b1d3f5e7c9a1b3d5f7e9c1a3b5d7f9e1c3",
            "hashtype": "sha256",
            "created": "2026-10-20 14:35:51"
          }
        }
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 400 Bad Request is returned when a name in the path contains characters that are not allowed.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled.

HTTP 403 Forbidden is returned when the token does not belong to rootus or an admin user. The token of a delegate user and a node token are refused as well.

HTTP 404 Not found is returned when this controller holds no checksums for the object.

Get the checksum of one artefact (GET /hash/{object_type}/{name}/{file})

Request

GET /hash/osimage/compute/compute-1760970728.tar.bz2

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Response body

{
  "config": {
    "hash": {
      "osimage": {
        "compute": {
          "compute-1760970728.tar.bz2": {
            "hash": "9f2c4e1b7a3d5c8e0f6a2b4d6e8f0a1c3e5b7d9f1a3c5e7b9d1f3a5c7e9b1d3f",
            "hashtype": "sha256",
            "created": "2026-10-20 14:32:08"
          }
        }
      }
    }
  }
}

Response header

HTTP 200 OK will be expected to be returned.

HTTP 400 Bad Request is returned when a name in the path contains characters that are not allowed.

HTTP 401 Unauthorized is mandatory if there is no valid token, or when the user of the token no longer exists or is disabled.

HTTP 403 Forbidden is returned when the token does not belong to rootus or an admin user. The token of a delegate user and a node token are refused as well.

HTTP 404 Not found is returned when this controller holds no checksum for the artefact, for example one packed before checksums were recorded.

Provisioning tracker

The provisioning tracker is the built-in BitTorrent tracker used for torrent-based image provisioning. It is queried by the aria2 clients running on nodes during deployment. These endpoints return a bencoded, plain-text (text/plain) tracker response, not JSON, and are unauthenticated (no token header is required).

BitTorrent announce (GET /announce)

The announce endpoint registers a peer for a torrent and returns the current peer list. The client passes the standard BitTorrent query parameters, including info_hash and peer_id.

Request

GET /announce?info_hash=%12%34...&peer_id=-aria2-...&port=6881&uploaded=0&downloaded=0&left=0&compact=1

Response body

d8:intervali1800e5:peers[... bencoded peer data ...]e

Response header

HTTP 200 OK will be expected to be returned, with Content-Type: text/plain.

HTTP 400 Bad Request is returned when info_hash or peer_id is missing or invalid.

HTTP 500 Internal Server Error is returned when the response cannot be generated.

BitTorrent scrape (GET /scrape)

The scrape endpoint returns the state (seeders, leechers, completed) of the torrents the tracker manages. One or more info_hash parameters may be supplied; when none are given, all currently active torrents are reported.

Request

GET /scrape?info_hash=%12%34...

Response body

d5:filesd20:[... info_hash ...]d8:completei3e10:downloadedi0e10:incompletei1eeee

Response header

HTTP 200 OK will be expected to be returned, with Content-Type: text/plain.

HTTP 500 Internal Server Error is returned when the response cannot be generated.

Plugin import and export

Import data via an import plugin (POST /import/{name})

This endpoint forwards a request to the named import plugin (for example, prometheus rules). The request body is forwarded as-is to the plugin: if it is valid JSON it is parsed and passed as an object, otherwise the raw body is passed through unchanged.

Request

POST /import/prometheus

Request header

x-access-tokens: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjY4ODQyMTQwfQ"

Request body

{
  "rules": [
    {
      "alert": "NodeDown",
      "expr": "up == 0",
      "...": "..."
    }
  ]
}

Response body

[... plugin-defined response ...]

Response header

HTTP 200 OK will be expected to be returned when the plugin accepts the data.

HTTP 401 Unauthorized is mandatory if there is no valid token.

HTTP 404 Not Found is returned when the plugin does not exist or rejects the request.

Export data via an export plugin (GET /export/{name})

This endpoint calls the named export plugin and returns its data as-is. Any query-string parameters are passed through to the plugin. This route is unauthenticated; no token header is required.

Request

GET /export/prometheus

Response body

[... plugin-defined response ...]

Response header

HTTP 200 OK will be expected to be returned when the plugin produces data.

HTTP 404 Not Found is returned when the plugin does not exist or has no data to return.

TPM authentication

Obtain a node token via TPM attestation (POST /tpm/{nodename})

This endpoint issues a node token after validating the supplied TPM attestation against the named node. When cluster security is enabled, the request body must contain the node's tpm_sha256 value, which is matched against the value stored for the node. When cluster security is not enabled, the TPM value is stored and a token is returned (a username/password pair may be supplied instead and is forwarded to the standard token flow). On success the response contains a JWT valid for the configured expiry time. This route is unauthenticated; no token header is required to call it.

Request

POST /tpm/node001

Request body

{
  "tpm_sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
}

Response body

{
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MCwiZXhwIjoxNjY4ODQyMTQwfQ"
}

Response header

HTTP 200 OK will be expected to be returned, with the node token in the body.

HTTP 401 Unauthorized is returned when the TPM information is missing, the node is invalid, or the attestation does not match.

Asynchronous requests

Some operations do not complete within the lifetime of the HTTP request. When a state-changing POST operation is queued for background processing — for example pushing or grabbing an osimage, or a bulk control or service action — the daemon responds immediately with a request_id alongside the message:

{
  "message": "queued",
  "request_id": "1781082941.3238328347230542"
}

The result is then retrieved by polling the matching status endpoint until the operation finishes:

  • GET /config/status/{request_id} — for configuration operations such as osimage push and grab.
  • GET /control/status/{request_id} — for control (power) actions.
  • GET /service/status/{request_id} — for service (DHCP/DNS) actions.

Each poll returns the status messages collected so far and marks them as read, so successive calls return only new output. Continue polling until the operation is reported complete.

Poll the result of a configuration operation (GET /config/status/{request_id})

Request

GET /config/status/1781082941.3238328347230542

Response body

The status messages collected for the request so far are returned, keyed by the request id. Each poll marks the returned messages as read, so a subsequent call returns only newer output.

{
  "1781082941.3238328347230542": [
    {
      "created": "2026-06-10 09:15:42",
      "message": "osimage compute: packing started"
    },
    {
      "created": "2026-06-10 09:18:10",
      "message": "osimage compute: build finished"
    }
  ]
}

Response header

HTTP 200 OK will be expected to be returned while results are available. Poll again until the request is complete.

HTTP 404 Not Found is returned when there is no data for this request id.

Error handling

Status code

Description

Content

(tick) 200 OK

Indicates the request has succeeded

Return response required, if just a confirmation, send a 204

(tick) 201 Created

Indicates the request has succeeded and a new resource has been created

The new id

(tick) 204 No Content

The server has fulfilled the request but there is no response body

None

(error) 400 Bad Request

The request could not be understood.

The faulty fields may be indicated by the server

(error) 401 Unauthorized

The request requires user authentication

None

(error) 403 Forbidden

The client does not have access rights to the content

None

(minus) 404 Not Found

The server can not find the resource

The faulty fields may be indicated by the server

(error) 500 Internal Server Error

The server encountered an unexpected condition.

Send feedback

(error) 503 Service Unavailable

The server is not ready to handle the request.

Send feedback

Note there are no 300 codes: Either the system is in fault (500), it doesn’t exist (400), but there is no (300) redirection to any other endpoint.

Full spec JSON

JSON

{
  "config": {
    "node": {
      "node001": {
        "newhostname": "gpu001",
        "group": "compute",
        "interfaces": [
          {
            "interface": "BOOTIF",
            "network": "clusternet",
            "ipaddress": "10.141.0.1"
          },
          {
            "interface": "BMC",
            "network": "ipmi",
            "ipaddress": "10.148.0.1"
          },
          {
            "interface": "ib0",
            "network": "ib",
            "ipaddress": "10.149.0.1"
          }
        ],
        "switch": "switch01",
        "switchport": 1,
        "service": false,
        "setupbmc": true,
        "status": "installer.completed",
        "comment": null,
        "osimage": "compute",
        "prescript": "#!/bin/bash \n exit 0;",
        "partscript": "#!/bin/bash \n exit 0;",
        "postscript": "#!/bin/bash \n exit 0;",
        "netboot": true,
        "bootmenu": false,
        "provision_interface": null,
        "provision_method": null,
        "provision_fallback": null,
        "tpm_uuid": null,
        "tpm_pubkey": null,
        "tpm_sha256": null
      }
    },
    "group": {
      "compute": {
        "newgroupname": "compute-gpu",
        "bmcsetup": true,
        "domain": "cluster",
        "interfaces": [
          {
            "interface": "BOOTIF",
            "network": "clusternet"
          },
          {
            "interface": "BMC",
            "network": "ipmi"
          },
          {
            "interface": "ib0",
            "network": "ib"
          }
        ],
        "osimage": "compute",
        "partscript": "#!/bin/bash \n exit 0",
        "postscript": "#!/bin/bash \n exit 0",
        "prescript": "#!/bin/bash \n exit 0",
        "provision_interface": null,
        "netboot": true,
        "bootmenu": false,
        "comment": "Default group",
        "provision_method": "torrent",
        "provision_fallback": "http",
        "members": [
          "node001",
          "node002",
          "node003",
          "node004"
        ]
      }
    },
    "cluster": {
      "controller1": {
        "status": "primary",
        "ipaddr": "10.141.255.254",
        "serverport": 7050,
        "luna_config": "/trinity/local/luna/config/luna-daemon.ini"
      },
      "controller2": {
        "status": "standby",
        "ipaddr": "10.141.255.253",
        "serverport": 7050,
        "luna_config": "/trinity/local/luna/config/luna-daemon.ini"
      },
      "ntp_server": "10.141.255.252",
      "debug": false,
      "technical_contacts": "root@localhost",
      "provision_method": "torrent",
      "provision_fallback": "http"
    },
    "network": {
      "cluster": {
        "newnetname": "cluster2",
        "network": "10.141.0.0/16",
        "nameserver_ip": "10.141.255.254",
        "ntp_server": "10.141.255.254",
        "gateway": "10.141.255.254",
        "comment": "Default cluster network",
        "dhcp": true,
        "dhcp_range_begin": "10.141.0.200",
        "dhcp_range_end": "10.141.0.253"
      },
      "ipmi": {
        "newnetname": "ipmi2",
        "network": "10.148.0.0/16",
        "nameserver_ip": "10.148.255.254",
        "ntp_server": "10.148.255.254",
        "gateway": "10.148.255.254",
        "comment": "Default OOB network",
        "dhcp": false
      },
      "ib": {
        "newnetname": "ib2",
        "network": "10.149.0.0/16",
        "nameserver_ip": "10.149.255.254",
        "ntp_server": "10.149.255.254",
        "gateway": "10.149.255.254",
        "comment": "Default highspeed interconnect network",
        "dhcp": false
      }
    },
    "bmcsetup": {
      "dell": {
        "newbmcname": "newname",
        "mgmtchannel": 1,
        "netchannel": 1,
        "password": "calvin",
        "username": "root",
        "userid": 2,
        "comment": "Default DELL",
        "unmanaged_bmc_users": "skip",
        "members": [
          "node003",
          "node004"
        ]        
      },
      "gigabyte": {
        "newbmcname": "newname2",
        "mgmtchannel": 1,
        "netchannel": 1,
        "password": "password",
        "username": "admin",
        "userid": 2,
        "comment": "Default Gigabyte",
        "unmanaged_bmc_users": "disable",
        "members": [
          "node001",
          "node002"
        ]        
      }
    },
    "switch": {
      "switch01": {
        "network": "cluster",
        "newswitchname": "mgmsw01",
        "ipaddress": "10.141.253.1",
        "oid": ".1.3.6.1.2.1.17.7.1.2.2.1.2",
        "readcommunity": "public",
        "rwcommunity": "private",
        "comment": "Bootswitch"
      },
      "switch02": {
        "network": "ipmi",
        "newswitchname": "mgmsw02",
        "ipaddress": "10.148.253.1",
        "oid": ".1.3.6.1.2.1.17.7.1.2.2.1.2",
        "readcommunity": "public",
        "rwcommunity": "private",
        "comment": "Bootswitch"
      }
    },
    "otherdev": {
      "apc01": {
        "network": "cluster",
        "newotherdevname": "apc01a",
        "ipaddress": "10.141.250.1",
        "comment": "APC for rack01a"
      },
      "ups01": {
        "network": "ipmi",
        "newotherdevname": "ups-01",
        "ipaddress": "10.148.250.1",
        "comment": "UPS for the head node"
      }
    },
    "osimage": {
      "compute": {
        "grab_exclude": [
          "/dev",
          "/proc",
          "/sys"
        ],
        "grab_filesystems": [
          "/",
          "/boot"
        ],
        "initrdfile": "compute-initramfs-`uname -r`",
        "kernelfile": "compute-kernel-`uname -r`",
        "kernelmodules": "ipmi_devinft, ipmi_si, ipmi_msghandler",
        "kerneloptions": "mitigations=off nosmt noht",
        "kernelversion": "`uname -r`",
        "path": "/trinity/images/compute",
        "imagefile": "compute.tar.bz2",
        "comment": "Default image",
        "members": [
          "node003",
          "node004"
        ]        
      },
      "compute-ib": {
        "grab_exclude": [
          "/dev",
          "/proc",
          "/sys"
        ],
        "grab_filesystems": [
          "/",
          "/boot"
        ],
        "initrdfile": "compute-initramfs-`uname -r`",
        "kernelfile": "compute-kernel-`uname -r`",
        "kernelmodules": "ipmi_devinft, ipmi_si, ipmi_msghandler",
        "kerneloptions": "mitigations=off nosmt noht",
        "kernelversion": "`uname -r`",
        "path": "/trinity/images/compute-ib",
        "imagefile": "compute.tar.bz2",
        "comment": "Default image with updated drivers",
        "members": [
          "node001",
          "node002"
        ]        
      }
    },
    "secrets": {
      "node": {
        "node001": [
          {
            "secretname": "shared secret",
            "content": "<ENC>",
            "path": "/etc/keys.crt"
          },
          {
            "secretname": "software license",
            "content": "<ENC>",
            "path": "/etc/app/license.lic"
          },
          {
            "secretname": "shared secret",
            "content": "<ENC>",
            "path": "/etc/keys.crt"
          }
        ],
        "node002": [
          {
            "name": "software license",
            "content": "<ENC>",
            "path": "/etc/app/license.lic"
          }
        ]
      },
      "group": {
        "compute": [
          {
            "secretname": "Proprietary key",
            "content": "<ENC>",
            "path": "/var/lib/key.pem"
          }
        ],
        "compute-ib": [
          {
            "secretname": "Infiniband",
            "content": "<ENC>",
            "path": "/etc/rdma/license.lic"
          }
        ]
      }
    }
  },
  "version": {
    "luna": "2.0-001",
    "api": 1,
    "commit": "hex(commit)"
  },
  "monitor": {
    "service": {
      "dns": "OK, running",
      "dhcp": "OK, reloaded",
      "luna2": "OK"
    },
    "status": {
      "node001": {
        "status": "Luna installer: No errors",
        "state": "installer.ok"
      },
      "node002": {
        "status": "Luna installer: No errors",
        "state": "installer.ok"
      },
      "beegfs01": {
        "status": "Luna installer: No errors",
        "state": "installer.ok"
      },
      "login01": {
        "status": "Luna installer: Error in partscript",
        "state": "installer.error"
      }
    }
  },
  "control": {
    "power": {
      "on": {
        "hostlist": "node[001,node003-004]"
      },
      "fail": {
        "hostlist": "node[002]"
      }
    }
  }
}

YAML

---
config:
  node:
    node001:
      newhostname: gpu001
      group: compute
      interfaces:
      - interface: BOOTIF
        network: clusternet
        ipaddress: 10.141.0.1
      - interface: BMC
        network: ipmi
        ipaddress: 10.148.0.1
      - interface: ib0
        network: ib
        ipaddress: 10.149.0.1
      macaddr: aa:bb:cc:dd:ee:ff
      switch: switch01
      switchport: 1
      service: False
      setupbmc: True
      status: installer.completed
      comment:
      osimage: compute
      prescript: "#!/bin/bash \n exit 0;"
      partscript: "#!/bin/bash \n exit 0;"
      postscript: "#!/bin/bash \n exit 0;"
      netboot: True
      bootmenu: False
      provision_interface:
      provision_method:
      provision_fallback:
      tpm_uuid:
      tpm_pubkey:
      tpm_sha256:
  group:
    compute:
      newgroupname: compute-gpu
      bmcsetup: True
      domain: cluster
      interfaces:
      - interface: BOOTIF
        network: clusternet
      - interface: BMC
        network: ipmi
      - interface: ib0
        network: ib
      osimage: compute
      partscript: "#!/bin/bash \n exit 0"
      postscript: "#!/bin/bash \n exit 0"
      prescript: "#!/bin/bash \n exit 0"
      provision_interface:
      netboot: True
      bootmenu: False
      comment: "Default group"
      provision_method: torrent
      provision_fallback: http
      members:
      - node001
      - node002
      - node003
      - node004
  cluster:
    controller1:
      status: primary
      ipaddr: 10.141.255.254
      serverport: 7050
      luna_config: /trinity/local/luna/config/luna-daemon.ini
    controller2:
      status: standby
      ipaddr: 10.141.255.253
      serverport: 7050
      luna_config: /trinity/local/luna/config/luna-daemon.ini
    ntp_server: 10.141.255.252 
    debug: False
    technical_contacts: root@localhost
    provision_method: torrent
    provision_fallback: http
  network:
    cluster:
      newnetname: cluster2
      network: 10.141.0.0/16
      nameserver_ip: 10.141.255.254
      ntp_server: 10.141.255.254
      gateway: 10.141.255.254
      comment: "Default cluster network"
      dhcp: True
      dhcp_range_begin: 10.141.0.200
      dhcp_range_end: 10.141.0.253
    ipmi:
      newnetname: ipmi2
      network: 10.148.0.0/16
      nameserver_ip: 10.148.255.254
      ntp_server: 10.148.255.254
      gateway: 10.148.255.254
      comment: "Default OOB network"
      dhcp: False
    ib:
      newnetname: ib2
      network: 10.149.0.0/16
      nameserver_ip: 10.149.255.254
      ntp_server: 10.149.255.254
      gateway: 10.149.255.254
      comment: "Default highspeed interconnect network"
      dhcp: False
  bmcsetup:
    dell:
      newbmcname: newname
      mgmtchannel: 1
      netchannel: 1
      password: calvin
      username: root
      userid: 2
      comment: "Default DELL"
      unmanaged_bmc_users: "skip"
      members:
      - node003
      - node004      
    gigabyte:
      newbmcname: newname2
      mgmtchannel: 1
      netchannel: 1
      password: password
      username: admin
      userid: 2
      comment: "Default Gigabyte"
      unmanaged_bmc_users: "disable"
      members:
      - node001
      - node002      
  switch:
    switch01:
       network: cluster
       newswitchname: mgmsw01
       ipaddress: 10.141.253.1
       oid: ".1.3.6.1.2.1.17.7.1.2.2.1.2"
       readcommunity: public
       rwcommunity: private
       comment: Bootswitch
    switch02:
       network: ipmi
       newswitchname: mgmsw02
       ipaddress: 10.148.253.1
       oid: ".1.3.6.1.2.1.17.7.1.2.2.1.2"
       readcommunity: public
       rwcommunity: private
       comment: Bootswitch    
  otherdev:
    apc01:
       network: cluster
       newotherdevname: apc01a
       ipaddress: 10.141.250.1
       comment: APC for rack01a
    ups01:
       network: ipmi
       newotherdevname: ups-01
       ipaddress: 10.148.250.1
       comment: UPS for the head node
  osimage:
    compute:
      grab_exclude:
        - /dev
        - /proc
        - /sys
      grab_filesystems:
        - /
        - /boot
      initrdfile: "compute-initramfs-`uname -r`"
      kernelfile: "compute-kernel-`uname -r`"
      kernelmodules: "ipmi_devinft, ipmi_si, ipmi_msghandler"
      kerneloptions: "mitigations=off nosmt noht"
      kernelversion: "`uname -r`"
      path: /trinity/images/compute
      imagefile: compute.tar.bz2
      comment: "Default image"
      members:
      - node003
      - node004      
    compute-ib:
      grab_exclude:
        - /dev
        - /proc
        - /sys
      grab_filesystems:
        - /
        - /boot
      initrdfile: "compute-initramfs-`uname -r`"
      kernelfile: "compute-kernel-`uname -r`"
      kernelmodules: "ipmi_devinft, ipmi_si, ipmi_msghandler"
      kerneloptions: "mitigations=off nosmt noht"
      kernelversion: "`uname -r`"
      path: /trinity/images/compute-ib
      imagefile: compute.tar.bz2
      comment: "Default image with updated drivers"
      members:
      - node001
      - node002  
  secrets:
    node:
      node001:
        - secretname: shared secret
          content: <ENC>
          path: /etc/keys.crt
        - secretname: software license
          content: <ENC>
          path: /etc/app/license.lic
        - secretname: shared secret
          content: <ENC>
          path: /etc/keys.crt
      node002:
        - name: software license
          content: <ENC>
          path: /etc/app/license.lic
    group:
      compute:
        - secretname: Proprietary key
          content: <ENC>
          path: /var/lib/key.pem
      compute-ib:
        - secretname: Infiniband
          content: <ENC>
          path: /etc/rdma/license.lic
version:
  luna: 2.0-001
  api: 1.0
  commit: hex(commit)          
monitor:
  service:
    dns: "OK, running"
    dhcp: "OK, reloaded"
    luna2: "OK"
  status:
    node001:
      status: "Luna installer: No errors"
      state: "installer.ok"
    node002:
      status: "Luna installer: No errors"
      state: "installer.ok"
    beegfs01:
      status: "Luna installer: No errors"
      state: "installer.ok"
    login01:
      status: "Luna installer: Error in partscript"
      state: "installer.error"
control:
  power:
    on:
      hostlist: node[001,node003-004]
    fail:
      hostlist: node[002]