User Tools

Site Tools


arch:rest-api

CONFINE REST API

Introduction

This page documents a REST API implemented in the testbed registry servers and nodes, based on HTTP methods and JSON representations, supporting a raw PULL behaviour. Examples below use inline comments for clarification of members (although JSON doesn't support comments), HTTP method calls (at the beginning) and accompanying HTTP headers (at the end).

This proposal uses ideas from:

Note: URLs in this document are only illustrative examples and not part of the specification.

Allowed methods

Resources retrieved from an API server may include an Allow: HTTP header that lists the HTTP methods supported by that particular resource. For instance, on a normal resource:

GET https://[2001:db8:cafe::2]/confine/api/nodes/12345

Allow: GET, PUT, PATCH

On a resource list:

GET https://[2001:db8:cafe::2]/confine/api/nodes/

Allow: GET, POST

Resources include an HTTP Link: header with rel="http://confine-project.eu/rel/<API>/base" (a set of extension relation types according to RFC 5988) that points to the base URI of the API service where they have been retrieved from. For instance:

GET https://[2001:db8:cafe::2]/confine/api/nodes/12345

Link: <https://[2001:db8:cafe::2]/confine/api/>; rel="http://confine-project.eu/rel/registry/base"

Some resources add state to a base configuration resource. The representation holding state is accompanied by an HTTP Link: header with rel="http://confine-project.eu/rel/<API>/source" (a set of extension relation types according to RFC 5988) which points to the API URI of the base resource. Particularly, every resource present in the node API conveys some additional state to a resource in the registry API, for instance:

GET https://[2001:db8:cafe:3039::2]/confine/api/slivers/9876543210

Link: <https://[2001:db8:cafe::2]/confine/api/slivers/12345-9876543210>; rel="http://confine-project.eu/rel/node/source"

A resource may offer some links that allow functions to be called. If so, HTTP Link: headers with rel="http://confine-project.eu/rel/registry/do-<FUNCTION-NAME>" (an extension relation type according to RFC 5988) are provided. Function arguments can be posted to these URIs to perform a function call. For instance:

GET https://[2001:db8:cafe:3039::2]/confine/api/nodes/12345

Link: <https://[2001:db8:cafe::2]/confine/api/nodes/12345/ctl/reboot>; rel="http://confine-project.eu/rel/registry/do-reboot"

The descriptions of some HTTP links are prefixed with the string [controller]. Although these links may be used to update the descriptions of some resources, they are not properly part of the registry REST API. When present, these links point to URLs where a running instance of the CONFINE controller software may offer additional, non-configuration functionality like authentication, certification, file storage, etc.

Media types

Besides plain application/json, and in order to allow the API client to indicate the desired format of a resource's JSON representation according to a specific version of the wanted API, a profile parameter pointing to a particular JSON Schema can be provided to the HTTP Accept: header. The URIs of of these profiles use to follow this format:

Accept: application/json; profile="http://confine-project.eu/schema/<API>[/<API_VERSION>]/<RESOURCE>"

Here RESOURCE is the type of resource being represented (e.g. node, sliver), API the particular service API being used (e.g. registry, node), and API_VERSION the version of that API (e.g. v0, v1, v1.1) or the latest one supported by the used service if omitted. For instance:

Accept: application/json; profile="http://confine-project.eu/schema/node/v1/sliver"

Indicates that the represented resource is a sliver according to version 1 of the node API. However, please note that the exact profile URI of each resource type is indicated below. These URIs should be considered opaque; constructing them from components is discouraged.

To know the latest API version supported by a service you can just request its base resource accepting a version-less profile:

GET / HTTP/1.1
Accept: application/json; profile="http://confine-project.eu/schema/node/base"
...

HTTP/1.1 200 OK
Content-Type: application/json; profile="http://confine-project.eu/schema/node/v2/base"
...

Then you may either check the profile URI against a mapping to API service, version number and resource type, or you may retrieve the schema and look for these values inside of it. Since profile URIs are considered opaque, splitting and parsing the URI itself is discouraged.

Data types

  • Dates are UTC and encoded as strings with the following ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ.
  • IPv6 networks use compact notation, e.g. 2001:db8:cafe::/48.
  • IPv4 networks use CIDR notation: A.B.C.D/N.

Member names

The names of JSON object members match the following regular expression: [a-z][_a-z0-9]*.

Hidden members

Some sensitive members like user names or e-mail addresses may be obfuscated under certain situations, e.g. when listing users while not being authenticated to the API provider. Non-unique values are shown as <HIDDEN>, while unique values are encoded to UTF-8 then hashed, and they are shown as <HIDDEN:ALGORITHM:HEXADECIMAL_HASH> so that obfuscated versions are also unique. For instance the unique value “Béla Lugosi” may be shown as <HIDDEN:sha1:302befbc1337e383d2c50dabcdb2cc670a10e885>.

Resource descriptions

Any relevant API resource (i.e. having an entity on its own) is accessible via a unique API URI. Retrieving that URI will yield a resource description, i.e. a document containing the description of that resource in the form of a JSON object. All resource descriptions include a uri member which contains their own API URI. For instance:

// GET https://[2001:db8:cafe::2]/confine/api/slivers/12345-9876543210
{
    // The URI of this resource (it matches the retrieved URI).
    "uri": "https://[2001:db8:cafe::2]/confine/api/slivers/12345-9876543210",
    // Other members in this resource.
    // ...
}

Resource references

A resource referenced inside of another resource is not included in its whole form, but represented instead as a JSON object which only includes a uri member with the API URI of the referenced resource and an id member with its identifier. For instance:

// GET https://[2001:db8:cafe::2]/confine/api/slices/9876543210
{
    // The URI of this resource.
    "uri": "https://[2001:db8:cafe::2]/confine/api/slices/9876543210",
    // The ID of this resource.
    "id": 9876543210,
    // Resource references only contain a URI and an ID.
    "template": { "uri": "https://[2001:db8:cafe::2]/confine/api/templates/4", "id": 4 },
    // Other members in this resource.
    // ...
}

Resource lists

A resource list consists of an array of JSON objects, each one representing a listed resource, all showing the same structure. In its more simple form, each resource object only includes a uri member with the API URI of that resource and an id member with its identifier, although it may contain other resource members at the discretion of the implementation. For instance, this is a possible list of users:

// GET https://[2001:db8:cafe::2]/confine/api/users/
[
    // These resources have more members, but only one is shown (besides the URI).
    { "uri": "https://[2001:db8:cafe::2]/confine/api/users/246", "id": 246, "is_active": "true" },
    { "uri": "https://[2001:db8:cafe::2]/confine/api/users/567", "id": 567, "is_active": "true" },
    { "uri": "https://[2001:db8:cafe::2]/confine/api/users/789", "id": 789, "is_active": "false" },
]

Note: Clients may take advantage of the additional members in the list (e.g. to avoid further requests), but they should not rely on their presence. If a client needs a member which is not included in the resource list, it should either use member selection (see below) or retrieve the full resource description from its URI.

The base resource of an API service may refer to the resource lists available in that service by using Link: headers with rel="http://confine-project.eu/rel/<API>/<TYPE>-list" (a set of extension relation types according to RFC 5988). For instance, the registry API base:

GET https://[2001:db8:cafe::2]/confine/api/

Link: <https://[2001:db8:cafe::2]/confine/api/nodes/>; rel="http://confine-project.eu/rel/registry/node-list",
      <https://[2001:db8:cafe::2]/confine/api/slices/>; rel="http://confine-project.eu/rel/registry/slice-list", ...

A resource belonging to a collection of resources of the same type may also refer to its resource list using a Link: header. For instance, a node:

GET https://[2001:db8:cafe::2]/confine/api/users/246

Link: <https://[2001:db8:cafe::2]/confine/api/users/>; rel="http://confine-project.eu/rel/registry/user-list"

Note: In the following sections some features of resource lists are introduced that rely on query arguments. For readability's sake the arguments in examples are shown in their raw form, but keep in mind that they should be appropriately encoded using percent encoding. For instance ?/foo/bar="foo bar" should actually be encoded as ?%2Ffoo%2Fbar=%22foo+bar%22.

Member selection

The members shown in a resource list can be configured by selecting them using the show query argument, which accepts a comma-separated list of JSON Pointer member paths which apply to each of the listed resources. The resources in the main list themselves are selected by default. The rules for deciding when a member is shown are:

  1. When a resource is selected, only its uri and id members are shown.
  2. When a member is selected in the show query argument, it is also shown (regardless of being scalar, array or object).
  3. The same rules apply to selected referenced resources.

The same example as before extended with additional members:

// GET https://[2001:db8:cafe::2]/confine/api/users/
[
    { "uri": "https://[2001:db8:cafe::2]/confine/api/users/246", "id": 246 },// Other resources show the same members.
]
 
// GET https://[2001:db8:cafe::2]/confine/api/nodes/?show=/name,/hosts,/group_roles
[
    { "uri": "https://[2001:db8:cafe::2]/confine/api/users/246",
      "id": 246,
      "name": "Bob M. Harley",
      "hosts": [
          { "uri": "https://[2001:db8:cafe::2]/confine/api/hosts/56", "id": 56 },
          { "uri": "https://[2001:db8:cafe::2]/confine/api/hosts/789", "id": 789 },
      ],
      "group_roles": [
          { "group": { "uri": "https://[2001:db8:cafe::2]/confine/api/groups/12", "id": 12 },
            "is_group_admin": true, "is_node_admin": false, "is_slice_admin": false },
          { "group": { "uri": "https://[2001:db8:cafe::2]/confine/api/groups/35", "id": 35 },
            "is_group_admin": false, "is_node_admin": true, "is_slice_admin": false },
          { "group": { "uri": "https://[2001:db8:cafe::2]/confine/api/groups/711", "id": 711 },
            "is_group_admin": false, "is_node_admin": true, "is_slice_admin": true },
      ]
    },// Other resources show the same members.
]

The three selected members appear besides the URI and the ID. Please note how the members /hosts and /group_roles are shown in its entirety since complex members (arrays and objects) are considered one piece. If only some of their nested members are desired, they can be explicitly selected:

// GET https://[2001:db8:cafe::2]/confine/api/nodes/?show=/name,/hosts/0,/group_roles/_/is_group_admin
[
    { "uri": "https://[2001:db8:cafe::2]/confine/api/users/246",
      "id": 246,
      "name": "Bob M. Harley",
      "hosts": [
          { "uri": "https://[2001:db8:cafe::2]/confine/api/hosts/56", "id": 56 },
      ],
      "group_roles": [
          { "is_group_admin": true },
          { "is_group_admin": false },
          { "is_group_admin": false },
      ]
    },// Other resources show the same members.
]

This example also shows how you can select particular indexes in an array (/hosts/0), any index in an array using the wildcard index _ (/group_roles/_), and particular members in objects (/group_roles/_/is_group_admin).

The examples above also show how the representation of a referenced resource (even those happening in complex members) only includes its uri and id members. If more members are desired, they can be explicitly selected. The following example descends from a node to its slivers then to their slices:

// GET https://[2001:db8:cafe::2]/confine/api/nodes/?show=/slivers/_/slice
[
    { "uri": "https://[2001:db8:cafe::2]/confine/api/nodes/12345",
      "id": 12345,
      "slivers": [
          { "uri": "https://[2001:db8:cafe::2]/confine/api/slivers/12345-9876543210",
            "id": "9876543210@12345",
            "slice": {
                "uri": "https://[2001:db8:cafe::2]/confine/api/slices/9876543210",
                "id": 9876543210,
             },
          },
          { "uri": "https://[2001:db8:cafe::2]/confine/api/slivers/12345-5729459",
            "id": "5729459@12345",
            "slice": {
                "uri": "https://[2001:db8:cafe::2]/confine/api/slices/5729459",
                "id": 5729459,
            },
          },
      ]
    },// Other resources show the same members.
]

The intermediate sliver and slice resource objects include their uri and id as usual.

Pagination

Resource lists can be split into several pages by using the query arguments page (page number, 1-based) and per_page (maximum number of items per page), so each resulting page may include Link: headers with links to other pages of the listing. For instance:

GET https://[2001:db8:cafe::2]/confine/api/slivers/?page=1&per_page=100

Link: <https://[2001:db8:cafe::2]/confine/api/slivers/?page=2&per_page=100>; rel="next",
      <https://[2001:db8:cafe::2]/confine/api/slivers/?page=3&per_page=100>; rel="last"

Possible values of rel are: first, last, prev, next.

Filtering

Resource lists can be constrained to only include items matching certain values. All scalar members occuring in a resource list can be matched against by using a POINTER=VALUE query argument in the API URI, where POINTER is the JSON Pointer of the desired member relative to the objects in the list (not to the list itself). Several matches may be specified, in which case they are ANDed together.

When matching against any object in an array, you can use the wildcard index _ (underscore), e.g. /foo/_/bar=42 matches any object in the resource list which has a foo member array with an item that has a bar member with value 42.

For instance, this gets a sliver list restricted to those intended to run on the node with ID 12345 and having IPv4 public interfaces:

GET https://[2001:db8:cafe::2]/confine/api/slivers/?/node/id=12345&/interfaces/_/type="public4"

Please note how the value of a string must be put inside double quotes. If the value itself contains a double quote, it must be duplicated (e.g. /node/name="This is the ""Foo"" node").

Combining

The query arguments for filtering, member selection, and paging can be freely combined into single queries, for instance:

GET https://[2001:db8:cafe::2]/confine/api/slivers/?/node/id=12345&show=/slice/id&page=1&per_page=10

This query can be read as «list the 10 first slivers whose node ID is 12345, and show their slice ID».

Resource patching

Patches applied to resources through the HTTP PATCH method should follow the JSON Patch format (application/json-patch media type).

Resource schemas (v1)

Members are noted by their JSON Pointer relative to the document containing them, e.g. in {"foo": {"bar": 42}} bar is noted as /foo/bar; in {"foo": [{"x":1, "y":2}, {"x":3, "y":4}]} the second x is noted as /foo/1/x. When describing the items in an array, the wildcard index _ (underscore) is used to mean “any item”, e.g. in the previous example /foo/_/x stands for x in any item in the foo array.

Member cardinality is given by column N and it refers to GET and PUT operations. For non-array members, N=1 indicates a required value which cannot be null, while N=0..1 means an optional value that can be null. For array members of a base type (noted as base_type[]), N gives the minimum and maximum number of items it may contain (an array member may be empty but in may never be null).

All members listed for each resource type below do appear in the resource description returned when using the HTTP GET method on the resource's URI (members with no value have a null value). Only members marked with POST, PUT or PATCH may be set or changed using these methods when creating, replacing or modifying a resource, respectively. Otherwise the operation results in an HTTP error 422 Unprocessable Entity (with the adequate description) and the whole operation has no effect.

A member having a default value may be left out in POST operations. The default value for a compound member is shown as “(yes)” when all underlying members that can also be posted have default values. An implementation may provide default values different than the ones given below as well as defaults for the other postable members, but it must provide defaults for the members having them below. A member having “(auto)” as its default value will get an automatically computed one, detailed in its description.

Finally, the ref type is a shorthand for a JSON object having just uri and id members, i.e. a resource reference. When posting a reference, only its uri member may be provided (in the future this may change so that either a URI or an ID – but not both – may be provided).

Common members

These members appear as part of many resource descriptions. Some of them include associated function links.

Testbed or node resource

A resource offered by the testbed itself to slices, or by a node to slivers.

Member Type N Default Methods Description
/name string 1 POST The name of this resource, unique for the component that offers it.
/unit string 1 POST The unit in which this resource is measured.
/max_req integer 0..1 null POST PUT PATCH An optional, positive integer number indicating the maximum amount of units of this resource that a slice or sliver may request. If present, it must be greater than or equal to dflt_req. A null value means “unbound”.
/dflt_req integer 1 0 POST PUT PATCH A positive integer number indicating the default amount of units of this resource to be allocated to a slice or sliver which has not explicitly requested it. max_req and dflt_req allow setting basic policies on the allocation of resources.

Resource request

A request (explicit or implicit) for an amount of a testbed or node resource by a slice or sliver, respectively.

Member Type N Default Methods Description
/name string 1 POST The name of the requested resource, unique for the component that requests it.
/unit string 1 POST The unit in which the requested amount of resource is expressed. Mainly for readability purposes, it must match the unit of the requested resource.
/req integer 0..1 null POST PUT PATCH An optional, positive integer number indicating the amount of units of the resource requested by a slice or sliver. A null value requests the default amount for this resource, which is equivalent to this resource request being missing. This is different from 0, which explicitly requests no amount of the resource.

API endpoint data

Data on an endpoint that can be user to access an API provided by this host. Please note that the API may be offered by another host (e.g. a caching proxy), which doesn't preclude the host from running the API itself as well (e.g. on its management network address).

Member Type N Default Methods Description
/type string 1 POST PUT PATCH The type of API in this endpoint (e.g. registry, node, controller).
/base_uri string 1 POST PUT PATCH The base URI of the API endpoint.
/cert string 0..1 null POST PUT PATCH An optional X.509 PEM-encoded certificate for the API endpoint. Providing this may save API clients from checking the API certificate's signature.

Management network configuration

Management network configuration for this host.

Member Type N Default Methods Description
/addr string 1 (auto) The IPv6 address of this host in the testbed management network. The host may be expected to provide certain services on this address. It is automatically computed according to addressing rules.
/backend string 1 POST PUT PATCH The network backend that provides access to the management network. Possible values: native, tinc. The host should only use the native backend if it is connected to a network that itself implements the addressing. In the host resource description, a top-level member with the same name as the selected backend may carry additional configuration data for that backend, and the configuration contained in the top-level members of other backends is simply ignored (they may be null).
Header Value Description
Link: <URI>; rel="http://confine-project.eu/rel/controller/do-request-mgmt-cert" [controller] Contains the controller API function URI used to upload a certificate signing request (CSR) to be signed by the testbed CA. The distinguished name of the request must match this host's management address. POST data (multipart/form-data): a request field with the ASCII-armored PEM representation of the CSR. Response data: a JSON document with a /cert member containing the ASCII-armored PEM representation of the signed certificate.

Tinc host configuration

Tinc backend configuration data for this host.

Member Type N Default Methods Description
/name string 1 (auto) The name given to this host in the tinc network, usually TYPE_ID (e.g. server_4).
/pubkey string 1 POST PUT PATCH The PEM-encoded unique RSA public key used in the tinc network.
/addresses object[] 0..n [] POST PUT PATCH A list of tinc addresses this host listens on.
/addresses/_/addr string 1 POST The IP address or host name of this tinc address.
/addresses/_/port integer 1 POST The TCP/UDP port of this tinc address.
/addresses/_/island ref 0..1 null POST PUT PATCH An optional island used to hint where this tinc address is reachable from.

Community network data

Community network-related data for this host.

Member Type N Default Methods Description
/cndb_uri string 0..1 null POST PUT PATCH An optional, unique URI for this host/device in its CN's CNDB REST API.
/app_url string 0..1 null POST PUT PATCH An optional URL pointing to a description of this host/device in its CN's node DB web application.

SFA support

SFA-related data for this object.

Member Type N Default Methods Description
/uuid string 1 POST PUT PATCH A universally unique identifier (UUID, RFC 4122) for this object. Once set to a valid UUID it can not be changed.
/pubkey string 1 POST PUT PATCH A unique PEM-encoded RSA public key for this object.

Error at registry

Media type: application/json; profile="http://confine-project.eu/schema/registry/v1/error"

This type of resource is not requested nor sent by the client. Instead, the registry server returns it together with an appropriate HTTP client error (4xx) status code when it encounters a problem with the current request. A single error document can point out problems with several members at once to reduce the number of interactions when the request contains several invalid or problematic members.

Member Type N Default Methods Description
/message string 1 A non-empty textual summary of the problem with the request.
/errors object[] 0..n A detailed list of problematic members.
/errors/_/member string 1 A JSON Pointer to the member causing a problem, relative to the request document (the empty string means a generic error for the request).
/errors/_/message string 1 A non-empty textual description of the particular problem with the member.

Examples:

An example authorization error when trying to remove a sliver:

// DELETE https://[2001:db8:cafe::2]/confine/api/slivers/12345-9876543210
// HTTP error 403 Forbidden
{
    "message": "User 1032 is not allowed to remove sliver 9876543210 at node 12345.",
    "errors": [],
}

An example error for invalid, missing and extra members (the new resource is not created):

// POST https://[2001:db8:cafe::2]/confine/api/nodes/
{
    "id": 6789,
    // "arch": "i686",
    "direct_ifaces": [ 1234 ],
    "resources": [ { "name": "pub_ipv4", "unit": "addrs", "max_req": 1, "dflt_req": -1 } ],
    "foobar": "foo",
    // ...
}
 
// HTTP error 422 Unprocessable Entity
{
    "message": "Request validation failed.",
    "errors": [
        { "member": "/id", "message": "can not set" },
        { "member": "/arch", "message": "missing value" },
        { "member": "/direct_ifaces/0", "message": "invalid type" },
        { "member": "/resources/0/dflt_req", "message": "invalid value" },
        { "member": "/foobar", "message": "invalid member" },
    ],
}

An example error for trying to modify read-only members (no members at all are changed as a result):

// PATCH https://[2001:db8:cafe::2]/confine/api/nodes/12345
[
    { "op": "replace", "path": "/id", "value": 6789 },
    { "op": "replace", "path": "/description", "value": "New description blah blah..." },
    { "op": "replace", "path": "/foobar", "value": true },
]
 
// HTTP error 422 Unprocessable Entity
{
    "message": "Request validation failed.",
    "errors": [
        { "member": "/id", "message": "can not modify" },
        { "member": "/foobar", "message": "invalid member" },
    ],
}

Resource list at registry

Media type: application/json; profile="http://confine-project.eu/schema/registry/v1/resource-list"

This type of resource is used by the registry server to provide resource lists as described above. It consists of an array of objects having the same structure. Each object has at least the following members:

Member Type N Default Methods Description
/uri string 1 The API URI of the listed resource.
/id (atomic) 1 The unique ID of the listed resource.

Deletion behaviour: This resource cannot be deleted, using DELETE results in HTTP error 405 Method Not Allowed.

Example:

// GET https://[2001:db8:cafe::2]/confine/api/slivers/
[
    { "uri": "https://[2001:db8:cafe::2]/confine/api/slivers/12345-9876543210",
      "id": "9876543210@12345",
      "node": { "uri": "https://[2001:db8:cafe::2]/confine/api/nodes/12345",
                "id": 12345 },
      "slice": { "uri": "https://[2001:db8:cafe::2]/confine/api/slices/9876543210",
                 "id": 9876543210, "set_state": "start" },
      "set_state": null },
    { "uri": "https://[2001:db8:cafe::2]/confine/api/slivers/12345-5729459",
      "id": "5729459@12345",
      "node": { "uri": "https://[2001:db8:cafe::2]/confine/api/nodes/12345",
                "id": 12345 },
      "slice": { "uri": "https://[2001:db8:cafe::2]/confine/api/slices/5729459",
                 "id": 5729459, "set_state": "start" },
      "set_state": "register" },
]

Base at registry

Media type: application/json; profile="http://confine-project.eu/schema/registry/v1/base"

This resource is located at the base URI of the registry API. It describes testbed-wide parameters and provides the API URIs to navigate to other resources in the testbed.

Member Type N Default Methods Description
/uri string 1 (auto) The API URI of this registry API base.
/confine_params object 1 (yes) CONFINE-wide constant parameters.
/confine_params/debug_ipv6_prefix string 1 (yes) An IPv6 /48 network used as the CONFINE debug IPv6 prefix. See addressing for its fixed value.
/confine_params/priv_ipv6_prefix string 1 (yes) An IPv6 /48 network used as the CONFINE private IPv6 prefix. See addressing for its fixed value.
/testbed_params object 1 PUT PATCH Testbed-wide parameters.
/testbed_params/mgmt_ipv6_prefix string 1 PUT PATCH An IPv6 /48 network used as the testbed management IPv6 prefix. See addressing for legal values. This member can only be changed if all nodes are in the safe set state (/set_state=safe).
/testbed_resources object[] 0..n [] PUT PATCH A list of testbed-wide resources (see testbed or node resource). The only allowed resource is vlan (measured in tags with a maximum amount of 1 tag per slice) for VLAN tags currently only available for the exclusive use of a slice in its slivers' isolated interfaces (see node architecture). Such a tag may be requested implicitly by a slice via its /allow_isolated member.
/testbed_resources/_/avail integer 0..1 The currently unused amount of units of this resource available in the testbed to be allocated to slices (may be null if unknown).
Header Value Description
Link: <URI>; rel="http://confine-project.eu/rel/registry/base" The base URI of the registry API where this resource was retrieved from.
Link: <URI>; rel="http://confine-project.eu/rel/registry/server-list" The API URI of the resource list of servers in the testbed. A server description can be POSTed to this URI to create a new server.
Link: <URI>; rel="http://confine-project.eu/rel/registry/node-list" The API URI of the resource list of nodes in the testbed. A node description can be POSTed to this URI to create a new node.
Link: <URI>; rel="http://confine-project.eu/rel/registry/slice-list" The API URI of the resource list of slices in the testbed. A slice description can be POSTed to this URI to create a new slice.
Link: <URI>; rel="http://confine-project.eu/rel/registry/sliver-list" The API URI of the resource list of slivers in the testbed. A sliver description can be POSTed to this URI to create a new sliver.
Link: <URI>; rel="http://confine-project.eu/rel/registry/user-list" The API URI of the resource list of users in the testbed. A user description can be POSTed to this URI to create a new user.
Link: <URI>; rel="http://confine-project.eu/rel/registry/group-list" The API URI of the resource list of groups in the testbed. A group description can be POSTed to this URI to create a new group.
Link: <URI>; rel="http://confine-project.eu/rel/registry/host-list" The API URI of the resource list of odd hosts in the testbed. A host description can be POSTed to this URI to create a new host.
Link: <URI>; rel="http://confine-project.eu/rel/registry/template-list" The API URI of the resource list of sliver templates available in the testbed. A template description can be POSTed to this URI to create a new template.
Link: <URI>; rel="http://confine-project.eu/rel/registry/island-list" The API URI of the resource list of islands supported by the testbed. An island description can be POSTed to this URI to create a new island.
Link: <URI>; rel="http://confine-project.eu/rel/controller/do-get-auth-token" [controller] Contains the controller API function URI used to get the user authentication token. POST data: username and password fields for the authenticated user (an email can be provided as username). Response data: a JSON document with a /token member containing a string that can be used as an authentication token.

Deletion behaviour: This resource cannot be deleted, using DELETE results in HTTP error 405 Method Not Allowed.

Example:

// GET https://[2001:db8:cafe::2]/confine/api/
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/",
 
    // These are common for all CONFINE testbeds and immutable.
    "confine_params": {
        "debug_ipv6_prefix": "fd5f:eee5:e6ad::/48",
        "priv_ipv6_prefix": "fdbd:e804:6aa9::/48",
    },
 
    "testbed_params": {
        "mgmt_ipv6_prefix": "2001:db8:cafe::/48",
    },
 
    "testbed_resources": [
        { "name": "vlan", "unit": "tags", "max_req": 1, "dflt_req": 0, "avail": 3820 },
    ],
}
// Link: <https://[2001:db8:cafe::2]/confine/api/>; rel="http://confine-project.eu/rel/registry/base",
//       <https://[2001:db8:cafe::2]/confine/api/servers/>; rel="http://confine-project.eu/rel/registry/server-list",
//       <https://[2001:db8:cafe::2]/confine/api/nodes/>; rel="http://confine-project.eu/rel/registry/node-list",
//       <https://[2001:db8:cafe::2]/confine/api/slices/>; rel="http://confine-project.eu/rel/registry/slice-list",
//       <https://[2001:db8:cafe::2]/confine/api/slivers/>; rel="http://confine-project.eu/rel/registry/sliver-list",
//       <https://[2001:db8:cafe::2]/confine/api/users/>; rel="http://confine-project.eu/rel/registry/user-list",
//       <https://[2001:db8:cafe::2]/confine/api/groups/>; rel="http://confine-project.eu/rel/registry/group-list",
//       <https://[2001:db8:cafe::2]/confine/api/hosts/>; rel="http://confine-project.eu/rel/registry/host-list",
//       <https://[2001:db8:cafe::2]/confine/api/templates/>; rel="http://confine-project.eu/rel/registry/template-list",
//       <https://[2001:db8:cafe::2]/confine/api/islands/>; rel="http://confine-project.eu/rel/registry/island-list",
//       <https://[2001:db8:cafe::2]/api-token-auth/>; rel="http://confine-project.eu/rel/controller/do-get-auth-token"

Server at registry

Media type: application/json; profile="http://confine-project.eu/schema/registry/v1/server"

This resource describes a server in the testbed. It may for instance be a registry server providing access to the registry API, a controller instance, or a gateway providing access to the management network.

Member Type N Default Methods Description
/uri string 1 (auto) The API URI of this server.
/id integer 1 (auto) A 48-bit, positive, non-zero integer number, the unique ID of this server.
/name string 1 POST PUT PATCH The unique name of this server. A single non-empty line of free-form text with no whitespace surrounding it.
/description string 0..1 null POST PUT PATCH An optional free-form textual description of this host/device.
/properties object 1 {} POST PUT PATCH A mapping of arbitrary server property names to their (string) values. Names must match the regular expression ^[a-z][_0-9a-z]*[0-9a-z]$.
/api object[] 0..n [] POST PUT PATCH Data on the endpoints that can be user to access the APIs provided by this server (see API endpoint data).
/api/_/type string 1 POST PUT PATCH The type of API in this endpoint. Possible values: registry, controller.
/api/_/island ref 0..1 null POST PUT PATCH An optional island used to hint where this API endpoint is reachable from. An API endpoint reachable from the management network may omit this member.
/mgmt_net object 1 POST PUT PATCH Management network configuration for this server (see management network configuration). The API certificate may be self-signed.
/tinc object 0..1 null POST PUT PATCH Tinc backend configuration data for this server (see tinc host configuration).
/cn object 0..1 (yes) POST PUT PATCH Community network-related data for this host (see community network data).
Header Value Description
Link: <URI>; rel="http://confine-project.eu/rel/registry/base" The base URI of the registry API where this resource was retrieved from.
Link: <URI>; rel="http://confine-project.eu/rel/registry/server-list" Contains the API URI of the resource list of servers in the testbed.

Deletion behaviour: Only authenticated superusers can delete this resource, otherwise DELETE results in HTTP error 401 Unauthorized. At least one server must exist, using DELETE on the last server results in HTTP error 403 Forbidden.

Example:

// GET https://[2001:db8:cafe::2]/confine/api/servers/2
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/servers/2",
 
    "id": 2,
    "name": "Secondary server",
    "description": "This is the secondary server of the Foo testbed, located at Bar. See http://...",
 
    "properties": {
        "is_master": "false",
        "update_interval": "900",
    },
 
    "api": [
        // from ServerApi
        { "type": "registry",
          "base_uri": "https://[2001:db8:cafe::2]/confine/api/",
          "cert": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
          "island": null,  // for the whole management network
        },
        { "type": "registry",
          "base_uri": "https://api.my-testbed.net/",
          "cert": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
          "island": { "uri": "https://[2001:db8:cafe::2]/confine/api/islands/1", "id": 1 },  // for the Internet
        },
        { "type": "controller",
          "base_uri": "https://controller.my-testbed.net/api/",
          "cert": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
          "island": { "uri": "https://[2001:db8:cafe::2]/confine/api/islands/1", "id": 1 },  // for the Internet
        },
    ],
 
    "mgmt_net": {
        // from MgmtNetConf
        "addr": "2001:db8:cafe::2",
        "backend": "tinc",
    },
 
    "tinc": {
        // from TincHost
        "name": "server_2",
        "pubkey": "-----BEGIN RSA PUBLIC KEY-----\n...\n-----END RSA PUBLIC KEY-----",
        "addresses": [
            { "addr": "10.228.203.1",
              "port": 655,
              "island": { "uri": "https://[2001:db8:cafe::2]/confine/api/islands/1", "id": 1 },
            },
        ],
    },
 
    "cn": {
        // from CnHost
        "cndb_uri": "http://guifi.net/cndb/device/46430",
        "app_url": "http://guifi.net/guifi/device/46430",
    },
}
// Link: <https://[2001:db8:cafe::2]/confine/api/>; rel="http://confine-project.eu/rel/registry/base"
// Link: <https://[2001:db8:cafe::2]/confine/api/servers/>; rel="http://confine-project.eu/rel/registry/server-list"
// Link: <https://[2001:db8:cafe::2]/confine/api/servers/2/ctl/request-api-cert>; rel="http://confine-project.eu/rel/controller/do-request-mgmt-cert"

Node at registry

Media type: application/json; profile="http://confine-project.eu/schema/registry/v1/node"

This resource describes a node in the testbed as well as listing the slivers intended to run on it with API URIs to navigate to them.

Applying some changes to the members described below in a node may be difficult, especially if it has deployed slivers. For that reason the node may choose to ignore those changes until it is rebooted, which can be accomplished via the do-reboot call described below. Applying those changes (with or without a reboot) may also cause some slivers to be undeployed since the old allocations may no longer be valid.

Member Type N Default Methods Description
/uri string 1 (auto) The API URI of this node.
/id integer 1 (auto) A 16-bit, positive, non-zero integer number, the unique ID of this node.
/name string 1 POST PUT PATCH The unique name of this node. A single non-empty line of free-form text with no whitespace surrounding it.
/description string 0..1 null POST PUT PATCH An optional free-form textual description of this host/device.
/arch string 1 POST PUT PATCH The architecture of this node (as reported by uname -m, non-empty). Slivers using this node should use templates that accept this architecture. This member cannot be changed if there are slivers intended to run on this node.
/boot_sn integer 1 0 The number of times this node has been instructed to be rebooted (reboot sequence number).
/set_state string 1 "debug" PUT PATCH The state set on this node (set state). Possible values: debug (initial), safe, production, failure. To support the late addition or generation of node keys, the set state is forced to remain debug while the node is missing some key, certificate or other configuration item. The set state is automatically changed to safe when all items are in place. Changing existing keys also moves the node into state debug or safe as appropriate. All set states but debug can be manually selected. See node states for the full description of set states and possible transitions.
/direct_ifaces string[] 0..n [] POST PUT PATCH A list of non-empty names of interfaces used as direct interfaces. See node architecture. Changing this member may result in slivers being undeployed.
/properties object 1 {} POST PUT PATCH A mapping of arbitrary node property names to their (string) values. Names must match the regular expression ^[a-z][_0-9a-z]*[0-9a-z]$.
/resources object[] 0..n [] POST PUT PATCH A list of node-wide resources (see testbed or node resource). The only allowed resources are i) pub_ipv4 and pub_ipv6 (both measured in addrs) for public IPv4 and IPv6 addresses in the node's local network available for the exclusive use of a sliver's public interface (see node architecture), ii) disk (measured in MiB, i.e. 220 bytes) for disk space available for the exclusive use of a sliver, and iii) memory (also measured in MiB) for an amount of system memory available for the exclusive use of the sliver. Public addresses are requested implicitly by a sliver by defining public interfaces, and disk space and memory are requested explicitly by a sliver or its slice by using a resource request.
/api object 0..1 null POST PUT PATCH Data on the endpoint that can be used to access this node's REST API (see API endpoint data).
/api/type string 1 "node" POST PUT PATCH The type of API in this endpoint. Always node.
/mgmt_net object 1 POST PUT PATCH Management network configuration for this node (see management network configuration). See /set_state for more information on changing the node's keys and certificates.
/tinc object 0..1 null POST PUT PATCH Tinc backend configuration data for this node (see tinc host configuration). See /set_state for more information on changing the node's keys and certificates.
/cn object 0..1 (yes) POST PUT PATCH Community network-related data for this host (see community network data).
/sfa object 0..1 null POST PUT PATCH SFA-related data for this host (see SFA support). See /set_state for more information on changing the node's SFA public key.
/island ref 0..1 null POST PUT PATCH An optional island used to hint where this node is located network-wise.
/group ref 1 POST The group this node belongs to. The user creating this node must be an group or node administrator of this group, and the group must have node creation allowed (/allow_nodes=true). Group and node administrators in this group are able to manage this node.
/slivers ref[] 0..n (auto) A list of slivers that are intended to run on this node.
Header Value Description
Link: <URI>; rel="http://confine-project.eu/rel/registry/base" The base URI of the registry API where this resource was retrieved from.
Link: <URI>; rel="http://confine-project.eu/rel/registry/node-list" Contains the API URI of the resource list of nodes in the testbed.
Link: <URI>; rel="http://confine-project.eu/rel/registry/do-reboot" Contains the function URI used to reboot this node. POST data: null.
Link: <URI>; rel="http://confine-project.eu/rel/controller/firmware" [controller] Contains the controller API URI used to generate a custom firmware image for this node. Using GET on the URI returns a JSON document with the state of the firmware generation process (if it has been started) and a link to the resulting image file. The process can be started by using an empty POST on the URI, which returns the same description. Using DELETE on the URI removes the generated firmware image. For more information, see firmware application.
Link: <URI>; rel="http://confine-project.eu/rel/controller/state" [controller] Contains the controller API URI used to get the current state of this node. Using GET on the URI returns a JSON document with its state. For more information, see state application.
Link: <URI>; rel="http://confine-project.eu/rel/controller/vm" [controller][vct] Contains the controller API URI used to manage the virtual machine of this node. Using GET on the URI returns a JSON document with the state of the virtual machine (or 404 if doesn't exist). The virtual machine can be created by using an empty POST on the URI and updated via PUT or PATCH requests. For more information, see node application.

Deletion behaviour: Only authenticated superusers or group and node administrators for the node's group can delete this resource, otherwise DELETE results in HTTP error 401 Unauthorized. Deleting a node with slivers assigned to it is allowed (but UIs should ask for confirmation), and the deletion cascades to them.

Example:

// GET https://[2001:db8:cafe::2]/confine/api/nodes/12345
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/nodes/12345",
 
    "id": 12345,
    "name": "MyCampus NE rooftop",
    "description": "This node is sponsored by the CONFINE project.\n\nBlah blah...",
    "arch": "i686",
    "boot_sn": 23,
    "set_state": "production",
 
    "direct_ifaces": [ "eth0", "eth1", "wlan0" ],
    "properties": {
        "allow_fooserv_monitoring": "yes",
    },
 
    "resources": [
        // no more than 4 public IPv4 addresses per sliver
        { "name": "pub_ipv4", "unit": "addrs", "max_req": 4, "dflt_req": 0 },
        // public IPv6 addresses are unbound
        { "name": "pub_ipv6", "unit": "addrs", "max_req": null, "dflt_req": 0 },
        // default disk per sliver is 512 MiB, 4 GiB maximum
        { "name": "disk", "unit": "MiB", "max_req": 4096, "dflt_req": 512 },
        // default memory per sliver is 256 MiB, 1 GiB maximum
        { "name": "memory", "unit": "MiB", "max_req": 1024, "dflt_req": 256 },
    ],
 
    "api": {
        // from NodeApi
        "type": "node",
        "base_uri": "https://[2001:db8:cafe:3039::2]/confine/api/",
        "cert": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
    },
 
    "mgmt_net": {
        // from MgmtNetConf
        "addr": "2001:db8:cafe:3039::2",
        "backend": "tinc"
    },
 
    "tinc": {
        // from TincHost
        "name": "node_12345",
        "pubkey": "-----BEGIN RSA PUBLIC KEY-----\n...\n-----END RSA PUBLIC KEY-----",
        "addresses": [],
    },
 
    "cn": {
        // from CnHost
        "cndb_uri": "http://guifi.net/cndb/device/38720",
        "app_url": "http://guifi.net/guifi/device/38720",
    },
 
    "sfa": {
        // from SfaObject
        "uuid": "d130b607-b2bc-471d-b2e1-f509981feff8",
        "pubkey": "-----BEGIN RSA PUBLIC KEY-----\n...\n-----END RSA PUBLIC KEY-----",
    },
 
    "island": { "uri": "https://[2001:db8:cafe::2]/confine/api/islands/1", "id": 1 },
    "group": { "uri": "https://[2001:db8:cafe::2]/confine/api/groups/35", "id": 35 },
 
    "slivers": [
        { "uri": "https://[2001:db8:cafe::2]/confine/api/slivers/12345-9876543210", "id": "9876543210@12345" },
        { "uri": "https://[2001:db8:cafe::2]/confine/api/slivers/12345-5729459", "id": "5729459@12345" },
    ],
}
// Link: <https://[2001:db8:cafe::2]/confine/api/>; rel="http://confine-project.eu/rel/registry/base"
// Link: <https://[2001:db8:cafe::2]/confine/api/nodes/>; rel="http://confine-project.eu/rel/registry/node-list"
// Link: <https://[2001:db8:cafe::2]/confine/api/nodes/12345/ctl/reboot>; rel="http://confine-project.eu/rel/registry/do-reboot"
// Link: <https://[2001:db8:cafe::2]/confine/api/nodes/12345/ctl/request-api-cert>; rel="http://confine-project.eu/rel/controller/do-request-mgmt-cert"
// Link: <https://[2001:db8:cafe::2]/confine/api/nodes/12345/ctl/firmware>; rel="http://confine-project.eu/rel/controller/firmware"
// Link: <https://[2001:db8:cafe::2]/confine/api/nodes/12345/ctl/state>; rel="http://confine-project.eu/rel/controller/state"

Slice at registry

Media type: application/json; profile="http://confine-project.eu/schema/registry/v1/slice"

This resource describes a slice in the testbed, including its slivers with API URIs to navigate to them.

Member Type N Default Methods Description
/uri string 1 (auto) The API URI of this slice.
/id integer 1 (auto) A 48-bit, positive, non-zero integer number, the unique ID of this slice.
/name string 1 POST PUT PATCH The unique name of this slice. A single non-empty line of free-form text with no whitespace surrounding it.
/description string 0..1 null POST PUT PATCH An optional free-form textual description of this slice.
/expires_on string 1 (auto) The date of expiration of this slice. If the slice is not renewed by that date, it is automatically deleted.
/instance_sn integer 1 0 The number of times this slice has been instructed to be reset (instance sequence number). Automatically incremented by the reset function (see below).
/allow_isolated boolean 1 false POST PUT PATCH Whether to request a VLAN tag for isolated sliver interfaces (see node architecture) at slice deployment time. If the allocation is successful, the tag is stored in the /isolated_vlan_tag member (see below). Otherwise, the deployment of the slice fails.
/isolated_vlan_tag integer 0..1 null A VLAN tag allocated to this slice for its isolated sliver interfaces. If requested and successfully allocated, this member gets a value greater than 0xff and less than 0xfff (numbers from 2 to 255 are too frequent to be used) while the slice is deployed or started. Null otherwise.
/set_state string 1 "register" PATCH The state set on this slice (set state). Possible values: register (initial) < deploy < start. Please note that this set state limits the effective set state for its slivers (e.g. sliver's register overrides slice's start, but sliver's start does not override slice's register). See slice and sliver states for the full description of set states and possible transitions.
/resources object[] 0..n (yes) A list of resource requests for this slice. Currently no explicit requests are allowed in this list, although implicit ones may be available.
/resources/_/alloc integer 0..1 null The amount of the requested resource currently allocated to the slice. Null for slices in the register set state.
/sliver_defaults object 1 POST PUT PATCH Default values that slivers of this slice will use if they do not explicitly indicate different ones (when possible).
/sliver_defaults/instance_sn integer 1 0 The instance sequence number that newly created slivers will get. Automatically incremented whenever a sliver of this slice is instructed to be updated.
/sliver_defaults/template ref 1 POST PUT PATCH The template to be used by slivers.
/sliver_defaults/data_uri string 0..1 null POST PUT PATCH The URI of a file containing data for slivers. This member may be set directly or through the do-upload-data controller API function.
/sliver_defaults/data_sha256 string 0..1 null POST PUT PATCH The SHA256 hash of the previous file. Compulsory when a file has been specified. This member may be set directly or through the do-upload-data controller API function.
/sliver_defaults/set_state string 1 "start" POST PUT PATCH The state set on this sliver (set state).
/sliver_defaults/resources object[] 0..n [] POST PUT PATCH A list of resource requests for slivers. The allowed requests are the same as in slivers.
/properties object 1 {} POST PUT PATCH A mapping of arbitrary slice property names to their (string) values. Names must match the regular expression ^[a-z][_0-9a-z]*[0-9a-z]$.
/sfa object 0..1 null POST PUT PATCH SFA-related data for this slice (see SFA support).
/group ref 1 POST The group this slice belongs to. The user creating this slice must be a group or slice administrator of this group, and the group must have slice creation allowed (/allow_slices=true). Group and slice administrators in this group are able to manage this slice and log in its slivers. They log in as root using their authentication tokens (usually an SSH key).
/slivers ref[] 0..n (auto) A list of slivers that are part of this slice.
Header Value Description
Link: <URI>; rel="http://confine-project.eu/rel/registry/base" The base URI of the registry API where this resource was retrieved from.
Link: <URI>; rel="http://confine-project.eu/rel/registry/slice-list" Contains the API URI of the resource list of slices in the testbed.
Link: <URI>; rel="http://confine-project.eu/rel/registry/do-renew" Contains the function URI used to renew this slice. POST data: null.
Link: <URI>; rel="http://confine-project.eu/rel/registry/do-reset" Contains the function URI used to reset this slice. Resetting a slice increments its instance_sn. POST data: null.
Link: <URI>; rel="http://confine-project.eu/rel/controller/do-upload-data" [controller] Contains the controller API function URI used to upload this slice's sliver default data file to some remote storage. The URI of the stored file will be placed in the /sliver_defaults/data_uri member and its hash in /sliver_defaults/data_sha256. POST data (multipart/form-data): a file field with the name and contents of the file.

Deletion behaviour: Only authenticated superusers or group and slice administrators for the slice's group can delete this resource, otherwise DELETE results in HTTP error 401 Unauthorized. Deleting a slice with slivers assigned to it is allowed (but UIs may ask for confirmation), and the deletion cascades to them.

Example:

// GET https://[2001:db8:cafe::2]/confine/api/slices/9876543210
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/slices/9876543210",
 
    "id": 9876543210,
    "name": "foobar",
    "description": "This slice runs an experiment for P2P foobar, see http://...",
    "expires_on": "2012-07-20T11:25:33Z",
    "instance_sn": 2,
    "allow_isolated": true,
    "isolated_vlan_tag": 420,  // allocated on deployment
    "set_state": "start",
 
    "properties": {
        "omf_foo_cookie": "0x1a2b3c4d",
    },
 
    "resources": [
        // an implicit request for a VLAN tag
        { "name": "vlan", "unit": "tags", "req": 1, "alloc": 1 },
    ],
 
    "sliver_defaults": {
        "instance_sn": 7,
        "template": { "uri": "https://[2001:db8:cafe::2]/confine/api/templates/4", "id": 4 },
        "data_uri": "http://.../sliver-data.tar.gz",
        // so sliver data can be retrieved by unsafe means
        "data_sha256": "114d003d0f04d0d39c0051709f72997ca30a11052ebab49b9f995e74225e0581",
        "set_state": "start",  // limited by slice's set state
        "resources": [
            // default requests for slivers
            { "name": "disk", "unit": "MiB", "req": 1024 },
            { "name": "memory", "unit": "MiB", "req": 128 },
        ],
    },
 
    "sfa": {
        // from SfaObject
        "uuid": "43b7dde3-1b65-4879-9fb1-846f1c85fb93",
        "pubkey": "-----BEGIN RSA PUBLIC KEY-----\n...\n-----END RSA PUBLIC KEY-----",
    },
 
    "group": { "uri": "https://[2001:db8:cafe::2]/confine/api/groups/12", "id": 12 },
 
    "slivers": [
        { "uri": "https://[2001:db8:cafe::2]/confine/api/slivers/12345-9876543210", "id": "9876543210@12345" },
        { "uri": "https://[2001:db8:cafe::2]/confine/api/slivers/6789-9876543210", "id": "9876543210@6789" },
    ],
}
// Link: <https://[2001:db8:cafe::2]/confine/api/>; rel="http://confine-project.eu/rel/registry/base"
// Link: <https://[2001:db8:cafe::2]/confine/api/slices/>; rel="http://confine-project.eu/rel/registry/slice-list"
// Link: <https://[2001:db8:cafe::2]/confine/api/slices/9876543210/ctl/renew>; rel="http://confine-project.eu/rel/registry/do-renew",
//       <https://[2001:db8:cafe::2]/confine/api/slices/9876543210/ctl/reset>; rel="http://confine-project.eu/rel/registry/do-reset"
//       <https://[2001:db8:cafe::2]/confine/api/slices/9876543210/ctl/upload-data>; rel="http://confine-project.eu/rel/controller/do-upload-data"

Sliver at registry

Media type: application/json; profile="http://confine-project.eu/schema/registry/v1/sliver"

This resource describes a sliver in the testbed, with API URIs to navigate to the slice it is part of and the node it is intended to run on.

Member Type N Default Methods Description
/uri string 1 (auto) The API URI of this sliver.
/id string 1 (auto) The unique ID of this sliver. It always has the form "SLICE_ID@NODE_ID" where SLICE_ID is the ID of the slice this sliver is part of and NODE_ID is the ID of the node this sliver is intended to run on.
/slice ref 1 POST The slice this sliver is part of.
/node ref 1 POST The node this sliver is intended to run on.
/description string 0..1 null POST PUT PATCH An optional free-form textual description of this sliver.
/instance_sn integer 1 (auto) A hint on the number of times this sliver has been instructed to be updated (instance sequence number). Its initial value is specified by the slice's sliver defaults. Automatically incremented by the update function (see below).
/template ref 0..1 null POST PUT PATCH If present, the template to be used by this sliver, instead of the one specified by the slice's sliver defaults.
/data_uri string 0..1 null POST PUT PATCH If present, the URI of a file containing data for this sliver, instead of the one specified by the slice's sliver defaults. Its format and contents depend on the type of the template to be used. This member may be set directly or through the do-upload-data controller API function.
/data_sha256 string 0..1 null POST PUT PATCH The SHA256 hash of the previous file, used to check its integrity. Compulsory when a file has been specified. This member may be set directly or through the do-upload-data controller API function.
/set_state string 0..1 null POST PUT PATCH If present, the state set on this sliver (set state), instead of the one specified by the slice's sliver defaults. Possible values: register (initial) < deploy < start. Please note that the effective set state for the sliver is still limited by the slice's set state (e.g. sliver's register overrides slice's start, but sliver's start does not override slice's register). See slice and sliver states for the full description of set states and possible transitions.
/properties object 1 {} POST PUT PATCH A mapping of arbitrary sliver property names to their (string) values. Names must match the regular expression ^[a-z][_0-9a-z]*[0-9a-z]$.
/resources object[] 0..n [] POST PUT PATCH A list of resource requests for this sliver. A request having the same name as a resource request in the slice's sliver defaults overrides it. Currently only explicit requests for the disk and memory resources are allowed and available in this list.
/interfaces object[] 1..n POST PUT PATCH A list of network interfaces that will be created in this sliver. Besides other optional interfaces, it must contain exactly one private interface. See node architecture. Note: Implementations may impose some additional limitations, thus to limit the variability of configurations and to ease node administration please follow the convention of making the private interface #0, the main management one #1 and the main public one #2.
/interfaces/_/nr integer 1 POST PUT PATCH The unique 8-bit, positive integer number of this interface in this sliver. Interface #0 is always the private interface.
/interfaces/_/name string 1 POST PUT PATCH The unique name of this interface in this sliver. It must match the regular expression ^[a-z]+[0-9]*$ and have no more than 10 characters.
/interfaces/_/type string 1 POST PUT PATCH The type of this interface. Possible values: private, debug, management, public4, public6, isolated. To use the public4 and public6 types the node must have pub_ipv4 and pub_ipv6 resources, respectively. To use the isolated type the slice must have requested a VLAN tag for isolated interfaces. There can only be one interface of type private, and by default it is configured for both IP4 and IPv6 default routes using the RD's internal addresses. The first public4 interface declared is configured for the default IPv4 route using the CD's IPv4 gateway address, and similarly with public6 interfaces for IPv6.
/interfaces/_/parent_name string 0..1 null POST PUT PATCH The name of a direct interface in the research device (see direct_ifaces at Node) to use for this interface's traffic (VLAN-tagged). Only meaningful (and mandatory) for isolated interfaces.
/mgmt_net object 0..1 (yes) Management network configuration for this sliver (see management network configuration). Only available if the sliver has interfaces of type management, in which case the management address is that of the first management interface, with "native" as a backend. Otherwise the whole member is null.
Header Value Description
Link: <URI>; rel="http://confine-project.eu/rel/registry/base" The base URI of the registry API where this resource was retrieved from.
Link: <URI>; rel="http://confine-project.eu/rel/registry/sliver-list" Contains the API URI of the resource list of slivers in the testbed.
Link: <URI>; rel="http://confine-project.eu/rel/registry/do-update" Contains the function URI used to update this sliver. Updating a sliver increments its instance_sn as well as the one in its slice's sliver defaults. POST data: null.
Link: <URI>; rel="http://confine-project.eu/rel/controller/do-upload-data" [controller] Contains the controller API function URI used to upload this sliver's data file to some remote storage. The URI of the stored file will be placed in the data_uri member and its hash in data_sha256. POST data (multipart/form-data): a file field with the name and contents of the file.
Link: <URI>; rel="http://confine-project.eu/rel/controller/state" [controller] Contains the controller API URI used to get the current state of this sliver. Using GET on the URI returns a JSON document with its state. For more information, see state application.

Deletion behaviour: Only authenticated superusers or group and slice administrators for the slice's group can delete this resource, otherwise DELETE results in HTTP error 401 Unauthorized.

Example:

// GET https://[2001:db8:cafe::2]/confine/api/slivers/12345-9876543210
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/slivers/12345-9876543210",
 
    "id": "9876543210@12345",
    "slice": { "uri": "https://[2001:db8:cafe::2]/confine/api/slices/9876543210", "id": 9876543210 },
    "node": { "uri": "https://[2001:db8:cafe::2]/confine/api/nodes/12345", "id": 12345 },
    "description": "This sliver runs the master coordinating process...",
    "instance_sn": 9,
    "template": null,  // use slice default
    "data_uri": null,  // use slice default
    "data_sha256": null,
    "set_state": null,  // use slice default
 
    "properties": {
        "group_master_sliver": "yes",
    },
 
    "resources": [
        // only explicit requests are available
        { "name": "disk", "unit": "MiB", "req": 2048 },
    ],
 
    "interfaces": [
        { "nr": 0, "name": "priv", "type": "private", "parent_name": null },
        { "nr": 2, "name": "pub0", "type": "public4", "parent_name": null },
        { "nr": 1, "name": "mgt0", "type": "management", "parent_name": null },
        { "nr": 4, "name": "dbg0", "type": "debug", "parent_name": null },
        { "nr": 5, "name": "iso0", "type": "isolated", "parent_name": "eth1" },
    ],
 
    "mgmt_net": {
        // from MgmtNetConf
        "addr": "2001:db8:cafe:3039:1001:2:4cb0:16ea",
        "backend": "native",
    },
}
// Link: <https://[2001:db8:cafe::2]/confine/api/>; rel="http://confine-project.eu/rel/registry/base"
// Link: <https://[2001:db8:cafe::2]/confine/api/slivers/>; rel="http://confine-project.eu/rel/registry/sliver-list"
// Link: <https://[2001:db8:cafe::2]/confine/api/slivers/12345-9876543210/ctl/update>; rel="http://confine-project.eu/rel/registry/do-update"
// Link: <https://[2001:db8:cafe::2]/confine/api/slivers/12345-9876543210/ctl/upload-data>; rel="http://confine-project.eu/rel/controller/do-upload-data"
// Link: <https://[2001:db8:cafe::2]/confine/api/slivers/12345-9876543210/ctl/state>; rel="http://confine-project.eu/rel/controller/state"

User at registry

Media type: application/json; profile="http://confine-project.eu/schema/registry/v1/user"

This resource describes a person using the testbed.

Member Type N Default Methods Description
/uri string 1 (auto) The API URI of this user.
/id integer 1 (auto) A positive, non-zero integer number, the unique ID of this user.
/name string 1 POST PUT PATCH The unique name of this user. A single non-empty line of free-form text with no whitespace surrounding it. This member is considered sensitive and may be hidden.
/description string 0..1 null POST PUT PATCH An optional free-form textual description of this user, it can include URLs and other information.
/is_active boolean 1 false PUT PATCH Whether this user is active (i.e. can log in testbed interfaces). Its value can only be changed by testbed superusers.
/is_superuser boolean 1 false PUT PATCH Whether this user is a testbed superuser. Its value can only be changed by testbed superusers.
/auth_tokens string[] 0..n [] POST PUT PATCH A list of authentication tokens like SSH or other kinds of public keys or X.509 certificates to be used for slivers or experiments. The exact valid format depends on the type of token as long as it is non-empty, but some ASCII armor like authorized_keys, RFC 4716 or PEM encoding is also strongly recommended over binary representations.
/sfa object 0..1 null POST PUT PATCH SFA-related data for this user (see SFA support).
/hosts ref[] 0..n [] A list of hosts this user is an owner of.
/group_roles object[] 0..n [] PUT PATCH A list of groups this user is a member of and the roles it has in each one. A user can only remove items from this list, i.e. leave membership of that group. However, it can not leave a group if it is its only group administrator. For other operations, please use the group resource. For more information, see Roles and permissions.
/group_roles/_/group ref 1 A group this user is a member of.
/group_roles/_/is_group_admin boolean 1 false PUT PATCH Whether this user is a group administrator in that group. A group administrator can manage slices and nodes belonging to the group, members in the group and their roles, and the group itself. A user can only change its value to false. However the only group administrator can not drop this role.
/group_roles/_/is_node_admin boolean 1 false PUT PATCH Whether this user is a node administrator in that group. A node administrator can manage nodes belonging to the group. A user can only change its value to false.
/group_roles/_/is_slice_admin boolean 1 false PUT PATCH Whether this user is a slice administrator in that group. A slice administrator can manage slices belonging to the group. A user can only change its value to false.
Header Value Description
Link: <URI>; rel="http://confine-project.eu/rel/registry/base" The base URI of the registry API where this resource was retrieved from.
Link: <URI>; rel="http://confine-project.eu/rel/registry/user-list" Contains the API URI of the resource list of users in the testbed.
Link: <URI>; rel="http://confine-project.eu/rel/controller/do-change-auth" [controller] Contains the controller API function URI used to update the user authentication data. The username or email should be provided in the addition to the password.

Deletion behaviour: Only authenticated superusers or the user itself can delete this resource, otherwise DELETE results in HTTP error 401 Unauthorized. At least one group administrator must exist per group, using DELETE on the group's last administrator results in HTTP error 403 Forbidden.

Example:

// GET https://[2001:db8:cafe::2]/confine/api/users/246
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/users/246",
 
    "id": 246,
    "name": "Bob M. Harley",
    "description": "I'm a researcher at Foo University, visit my home page: http://foo.edu/~bmharley/",
    "is_active": true,
    "is_superuser": false,
 
    "auth_tokens": [
        "ssh-rsa AAAAB3N...D6Q== Bob M. Harley <bob@example.com>",
        "ssh-rsa AAAAB3N...xVw== bob@computer",
        "-----BEGIN RSA PUBLIC KEY-----\n...\n-----END RSA PUBLIC KEY-----",
        "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
    ],
 
    "sfa": null,
 
    "hosts": [
        { "uri": "https://[2001:db8:cafe::2]/confine/api/hosts/56", "id": 56 },
        { "uri": "https://[2001:db8:cafe::2]/confine/api/hosts/789", "id": 789 },
    ],
 
    "group_roles": [
        { "group": { "uri": "https://[2001:db8:cafe::2]/confine/api/groups/12", "id": 12 },
          "is_group_admin": true, "is_node_admin": false, "is_slice_admin": false },
        { "group": { "uri": "https://[2001:db8:cafe::2]/confine/api/groups/35", "id": 35 },
          "is_group_admin": false, "is_node_admin": true, "is_slice_admin": false },
        { "group": { "uri": "https://[2001:db8:cafe::2]/confine/api/groups/711", "id": 711 },
          "is_group_admin": false, "is_node_admin": true, "is_slice_admin": true },
    ],
}
// Link: <https://[2001:db8:cafe::2]/confine/api/>; rel="http://confine-project.eu/rel/registry/base"
// Link: <https://[2001:db8:cafe::2]/confine/api/users/>; rel="http://confine-project.eu/rel/registry/user-list"
// Link: <https://[2001:db8:cafe::2]/confine/api/users/31/ctl/change-auth/>; rel="http://confine-project.eu/rel/controller/do-change-auth"

Group at registry

Media type: application/json; profile="http://confine-project.eu/schema/registry/v1/group"

This resource describes a group of users using the testbed.

Member Type N Default Methods Description
/uri string 1 (auto) The API URI of this group.
/id integer 1 (auto) A positive, non-zero integer number, the unique ID of this group.
/name string 1 POST PUT PATCH The unique name of this group. A single non-empty line of free-form text with no whitespace surrounding it.
/description string 0..1 null POST PUT PATCH An optional free-form textual description of this group, it can include URLs and other information.
/allow_nodes boolean 1 false PUT PATCH Whether nodes belonging to this group can be created or set into production (false by default). Its value can only be changed by testbed superusers.
/allow_slices boolean 1 false PUT PATCH Whether slices belonging to this group can be created or deployed (false by default). Its value can only be changed by testbed superusers.
/sfa object 0..1 null POST PUT PATCH SFA-related data for this group (see SFA support). The public key is used for SFA management and slice authorities.
/user_roles object[] 1..n (auto) PUT PATCH A list of users that are members of this group and the roles of each of them in it (its creator is included by default as a group administrator). Only group administrators can insert, remove or alter items from this list, i.e. change the set of group members and their roles. However, at least one active user must be a group administrator of this group. For more information, see Roles and permissions.
/user_roles/_/user ref 1 PUT PATCH A user that is member of this group.
/user_roles/_/is_group_admin boolean 1 false PUT PATCH Whether that user is a group administrator in this group. A group administrator can manage slices and nodes belonging to the group, members in the group and their roles, and the group itself.
/user_roles/_/is_node_admin boolean 1 false PUT PATCH Whether that user is a node administrator in this group. A node administrator can manage nodes belonging to the group.
/user_roles/_/is_slice_admin boolean 1 false PUT PATCH Whether that user is a slice administrator in this group. A slice administrator can manage slices belonging to the group.
/nodes ref[] 0..n (auto) A list of nodes that belong to this group.
/slices ref[] 0..n (auto) A list of slices that belong to this group.
Header Value Description
Link: <URI>; rel="http://confine-project.eu/rel/registry/base" The base URI of the registry API where this resource was retrieved from.
Link: <URI>; rel="http://confine-project.eu/rel/registry/group-list" Contains the API URI of the resource list of groups in the testbed.

Deletion behaviour: Only authenticated superusers or group administrators for the group can delete this resource, otherwise DELETE results in HTTP error 401 Unauthorized. Deleting a group with users, slices or nodes assigned to it is allowed (but UIs should ask for confirmation), and the deletion cascades to them.

Example:

// GET https://[2001:db8:cafe::2]/confine/api/groups/12
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/groups/12",
 
    "id": 12,
    "name": "ShubNet",
    "description": "The Invisible Distributed Networks group at University of Miskatonic. http://umam.edu/shubnet/",
    "allow_nodes": false,
    "allow_slices": true,
 
    "sfa": null,
 
    "user_roles": [
        { "user": { "uri": "https://[2001:db8:cafe::2]/confine/api/users/246", "id": 246 },
          "is_group_admin": true, "is_node_admin": false, "is_slice_admin": false },
        { "user": { "uri": "https://[2001:db8:cafe::2]/confine/api/users/567", "id": 567 },
          "is_group_admin": false, "is_node_admin": false, "is_slice_admin": true },
        { "user": { "uri": "https://[2001:db8:cafe::2]/confine/api/users/789", "id": 789 },
          "is_group_admin": false, "is_node_admin": false, "is_slice_admin": false },
    ],
 
    "nodes": [],  // no nodes allowed
    "slices": [
        { "uri": "https://[2001:db8:cafe::2]/confine/api/slices/9876543210", "id": 9876543210 },
    ],
}
// Link: <https://[2001:db8:cafe::2]/confine/api/>; rel="http://confine-project.eu/rel/registry/base"
// Link: <https://[2001:db8:cafe::2]/confine/api/groups/>; rel="http://confine-project.eu/rel/registry/group-list"

Host at registry

Media type: application/json; profile="http://confine-project.eu/schema/registry/v1/host"

This resource describes an odd host computer connected to the testbed (through the management network) with a known owner.

Member Type N Default Methods Description
/uri string 1 (auto) The API URI of this host.
/id integer 1 (auto) A 48-bit, positive, non-zero integer number, the unique ID of this host.
/name string 1 POST PUT PATCH The unique name of this host. A single non-empty line of free-form text with no whitespace surrounding it.
/description string 0..1 null POST PUT PATCH An optional free-form textual description of this host.
/mgmt_net object 1 POST PUT PATCH Management network configuration for this host (see management network configuration).
/tinc object 0..1 null POST PUT PATCH Tinc backend configuration data for this host (see tinc host configuration).
/island ref 0..1 null POST PUT PATCH An optional island used to hint where this host is located network-wise.
/owner ref 1 (auto) PUT PATCH The user who owns this host (its creator by default).
Header Value Description
Link: <URI>; rel="http://confine-project.eu/rel/registry/base" The base URI of the registry API where this resource was retrieved from.
Link: <URI>; rel="http://confine-project.eu/rel/registry/host-list" Contains the API URI of the resource list of hosts in the testbed.

Deletion behaviour: Only authenticated superusers or the host's owner can delete this resource, otherwise DELETE results in HTTP error 401 Unauthorized.

Example:

// GET https://[2001:db8:cafe::2]/confine/api/hosts/3
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/hosts/3",
 
    "id": 3,
    "name": "OMF Aggregate Manager (AM)",
    "description": "This host runs an OMF aggregate manager for experiment Foo...",
 
    "mgmt_net": {
        // from MgmtNetConf
        "addr": "2001:db8:cafe:0:2000::3",
        "backend": "tinc",
    },
 
    "tinc": {
        // from TincHost
        "name": "host_3",
        "pubkey": "-----BEGIN RSA PUBLIC KEY-----\n...\n-----END RSA PUBLIC KEY-----",
        "addresses": [],
    },
 
    "island": { "uri": "https://[2001:db8:cafe::2]/confine/api/islands/1", "id": 1 },
    "owner": { "uri": "https://[2001:db8:cafe::2]/confine/api/users/356", "id": 356 },
}
// Link: <https://[2001:db8:cafe::2]/confine/api/>; rel="http://confine-project.eu/rel/registry/base"
// Link: <https://[2001:db8:cafe::2]/confine/api/hosts/>; rel="http://confine-project.eu/rel/registry/host-list"
// Link: <https://[2001:db8:cafe::2]/confine/api/hosts/3/ctl/request-api-cert>; rel="http://confine-project.eu/rel/controller/do-request-mgmt-cert"

Template at registry

Media type: application/json; profile="http://confine-project.eu/schema/registry/v1/template"

This resource describes a template available in the testbed for slices and slivers to use.

Some members in a template description cannot be changed if it is in use, i.e. referenced by a registered slice or sliver. In that case it is advised to instead create a new template (possibly named as a new version) and deactivate the original one if necessary (e.g. if it has some serious bug or security problem).

Member Type N Default Methods Description
/uri string 1 (auto) The API URI of this template.
/id integer 1 (auto) A positive, non-zero integer number, the unique ID of this template.
/name string 1 POST PUT PATCH The unique name of this template. A single non-empty line of free-form text with no whitespace surrounding it, it can include version numbers and other information.
/description string 0..1 null POST PUT PATCH An optional free-form textual description of this template.
/type string 1 POST PUT PATCH The system type of this template. Roughly equivalent to the distribution the template is based on, e.g. debian (Debian, Ubuntu…), fedora (Fedora, RHEL…), suse (openSUSE, SUSE Linux Enterprise…). To deploy a sliver based on a template, the research device must support its type. This member cannot be changed if the template is in use.
/node_archs string[] 1..n POST PUT PATCH The node architectures accepted by this template (as reported by uname -m, non-empty). Slivers using this template should run on nodes whose architecture is listed here. Items cannot be removed from this member if the template is in use.
/is_active boolean 1 true POST PUT PATCH Whether this template is active (i.e. can be used by slivers). Slivers using an inactive template cannot be deployed.
/image_uri string 1 POST PUT PATCH The URI of this template's image file. This member cannot be changed if the template is in use. This member may be set directly or through the do-upload-image controller API function.
/image_sha256 string 1 POST PUT PATCH The SHA256 hash of the previous file, used to check its integrity. This member cannot be changed if the template is in use. This member may be set directly or through the do-upload-image controller API function.
Header Value Description
Link: <URI>; rel="http://confine-project.eu/rel/registry/base" The base URI of the registry API where this resource was retrieved from.
Link: <URI>; rel="http://confine-project.eu/rel/registry/template-list" Contains the API URI of the resource list of templates in the testbed.
Link: <URI>; rel="http://confine-project.eu/rel/controller/do-upload-image" [controller] Contains the controller API function URI used to upload this template's image file to some remote storage. The URI of the stored file will be placed in the image_uri member and its hash in image_sha256. POST data (multipart/form-data): a file field with the name and contents of the file.

Deletion behaviour: Only authenticated superusers can delete this resource, otherwise DELETE results in HTTP error 401 Unauthorized. Deleting a template with sliver or sliver defaults using it is not allowed, using DELETE on such an template results in HTTP error 403 Forbidden. The template can be deactivated, though.

Example:

// GET https://[2001:db8:cafe::2]/confine/api/templates/4
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/templates/4",
 
    "id": 4,
    "name": "debian,squeeze,i386,2012041700",
    "description": "A Debian sliver template with some useful network tools installed like...",
    "type": "debian",
    "node_archs": ["i586", "i686", "x86_64"],
    "is_active": true,
    "image_uri": "http://...",
    // so the template can be retrieved by unsafe means
    "image_sha256": "12774f8541de150504adc11b1fd5791b1238334f80f889f832580510f954678c",
}
// Link: <https://[2001:db8:cafe::2]/confine/api/>; rel="http://confine-project.eu/rel/registry/base"
// Link: <https://[2001:db8:cafe::2]/confine/api/templates/>; rel="http://confine-project.eu/rel/registry/template-list"
// Link: <https://[2001:db8:cafe::2]/confine/api/templates/4/ctl/upload-image>; rel="http://confine-project.eu/rel/controller/do-upload-image"

Island at registry

Media type: application/json; profile="http://confine-project.eu/schema/registry/v1/island"

This resource describes a network island, i.e. a possibly disconnected part of a community network. The usage of islands is mainly orientative: it can be used to signal user interfaces whether a node may see any servers, or whether modifying a gateway may leave some nodes disconnected from the testbed management network.

Member Type N Default Methods Description
/uri string 1 (auto) The API URI of this island.
/id integer 1 (auto) A positive, non-zero integer number, the unique ID of this island.
/name string 1 POST PUT PATCH The unique name of this island. A single non-empty line of free-form text with no whitespace surrounding it.
/description string 0..1 null POST PUT PATCH An optional free-form textual description of this island.
Header Value Description
Link: <URI>; rel="http://confine-project.eu/rel/registry/base" The base URI of the registry API where this resource was retrieved from.
Link: <URI>; rel="http://confine-project.eu/rel/registry/island-list" Contains the API URI of the resource list of islands in the testbed.

Deletion behaviour: Only authenticated superusers can delete this resource, otherwise DELETE results in HTTP error 401 Unauthorized. Deleting an island with nodes, hosts, addresses or API endpoints pointing to it is allowed (but UIs should ask for confirmation), and the deletion results in those references becoming null.

Example:

// GET https://[2001:db8:cafe::2]/confine/api/islands/2
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/islands/2",
 
    "id": 2,
    "name": "guifi.net Castelló",
    "description": "An island of guifi.net covering most of the province of Castelló in Spain.\n\nhttp://castello.guifi.net/",
}
// Link: <https://[2001:db8:cafe::2]/confine/api/>; rel="http://confine-project.eu/rel/registry/base"
// Link: <https://[2001:db8:cafe::2]/confine/api/islands/>; rel="http://confine-project.eu/rel/registry/island-list"

Error at node

Media type: application/json; profile="http://confine-project.eu/schema/node/v1/error"

This is the equivalent in the node API of a registry error document, and its definition is exactly the same.

Resource list at node

Media type: application/json; profile="http://confine-project.eu/schema/node/v1/resource-list"

This is the equivalent in the node API of a resource list document, and its definition is exactly the same.

Example:

// GET https://[2001:db8:cafe:3039::2]/confine/api/slivers/
[
    { "uri": "https://[2001:db8:cafe:3039::2]/confine/api/slivers/9876543210",
      "id": "9876543210@12345",
      "slice": { "uri": "https://[2001:db8:cafe::2]/confine/api/slices/9876543210",
                 "id": 9876543210, "set_state": "start", "sliver_defaults": { "set_state:" "start" } },
      "set_state": "start", "state": "started" },
    { "uri": "https://[2001:db8:cafe:3039::2]/confine/api/slivers/5729459",
      "id": "5729459@12345",
      "slice": { "uri": "https://[2001:db8:cafe::2]/confine/api/slices/5729459",
                 "id": 5729459, "set_state": "start", "sliver_defaults": { "set_state:" "start" } },
      "set_state": "register", "state": "registered" },
]

Base at node

Media type: application/json; profile="http://confine-project.eu/schema/node/v1/base"

This resource is located at the base URI of the node API. It complements the base configuration obtained from the registry with API URIs to navigate to other resources in the testbed as seen from the node, which usually means that they carry additional local state information or they reflect the current state of the node. Members coming from the configuration carry the same meaning as in the registry, but they can not be set here (i.e. no POST, PUT or PATCH methods allowed). Additional or differing members are:

Member Type N Default Methods Description
/uri string 1 The node API URI of this node API base.
Header Value Description
Link: <URI>; rel="http://confine-project.eu/rel/node/source" Contains the registry API URI used as the configuration source of this resource.
Link: <URI>; rel="http://confine-project.eu/rel/node/base" The base URI of the node API where this resource was retrieved from.
Link: <URI>; rel="http://confine-project.eu/rel/node/node" The node API URI of this testbed node.
Link: <URI>; rel="http://confine-project.eu/rel/node/sliver-list" The node API URI of the resource list of slivers that the node knows are intended to run on it.
Link: <URI>; rel="http://confine-project.eu/rel/node/template-list" The node API URI of the resource list of templates currently stored in this node.

Example:

// GET https://[2001:db8:cafe:3039::2]/confine/api/
{
    "uri": "https://[2001:db8:cafe:3039::2]/confine/api/",
 
    // These are common for all CONFINE testbeds and immutable.
    "confine_params": {
        "debug_ipv6_prefix": "fd5f:eee5:e6ad::/48",
        "priv_ipv6_prefix": "fdbd:e804:6aa9::/48",
    },
 
    "testbed_params": {
        "mgmt_ipv6_prefix": "2001:db8:cafe::/48",
    },
 
    "testbed_resources": [
        { "name": "vlan", "unit": "tags", "max_req": 1, "dflt_req": 0, "avail": 3820 },
    ],
}
// Link: <https://[2001:db8:cafe::2]/confine/api/>; rel="http://confine-project.eu/rel/registry/base"
// Link: <https://[2001:db8:cafe::2]/confine/api/servers/>; rel="http://confine-project.eu/rel/registry/server-list",
//       <https://[2001:db8:cafe::2]/confine/api/nodes/>; rel="http://confine-project.eu/rel/registry/node-list",
//       <https://[2001:db8:cafe::2]/confine/api/slices/>; rel="http://confine-project.eu/rel/registry/slice-list",
//       <https://[2001:db8:cafe::2]/confine/api/slivers/>; rel="http://confine-project.eu/rel/registry/sliver-list",
//       <https://[2001:db8:cafe::2]/confine/api/users/>; rel="http://confine-project.eu/rel/registry/user-list",
//       <https://[2001:db8:cafe::2]/confine/api/groups/>; rel="http://confine-project.eu/rel/registry/group-list",
//       <https://[2001:db8:cafe::2]/confine/api/hosts/>; rel="http://confine-project.eu/rel/registry/host-list",
//       <https://[2001:db8:cafe::2]/confine/api/templates/>; rel="http://confine-project.eu/rel/registry/template-list",
//       <https://[2001:db8:cafe::2]/confine/api/islands/>; rel="http://confine-project.eu/rel/registry/island-list",
//       <https://[2001:db8:cafe::2]/api-token-auth/>; rel="http://confine-project.eu/rel/controller/do-get-auth-token"
// Link: <https://[2001:db8:cafe::2]/confine/api/>; rel="http://confine-project.eu/rel/node/source"
// Link: <https://[2001:db8:cafe:3039::2]/confine/api/>; rel="http://confine-project.eu/rel/node/base"
// Link: <https://[2001:db8:cafe:3039::2]/confine/api/node>; rel="http://confine-project.eu/rel/node/node",
// Link: <https://[2001:db8:cafe:3039::2]/confine/api/slivers/>; rel="http://confine-project.eu/rel/node/sliver-list",
//       <https://[2001:db8:cafe:3039::2]/confine/api/templates/>; rel="http://confine-project.eu/rel/node/template-list",

Node at node

Media type: application/json; profile="http://confine-project.eu/schema/node/v1/node"

This resource complements the node configuration obtained from the registry with local state from the node. Members coming from the configuration carry the same meaning as in the registry, but they can not be set here (i.e. no POST, PUT or PATCH methods allowed). Additional or differing members are:

Member Type N Default Methods Description
/uri string 1 The node API URI of this node.
/api object 0..1 Data on the endpoint that can be used to access this node's REST API (see API endpoint data). When accessing the API at the node itself, the value of this member may point to the very node and thus differ from that of the registry if the node's API was delegated there to some external URI (i.e. a caching proxy), or it may even be null if the node does not implement the API by itself.
/soft_version string 1 The version of the CONFINE control software installed in this node (non-empty).
/state string 1 The current state of this node. Possible values: debug, safe, production, failure. See node states for the full description of states and possible transitions.
/errors object[] 0..n A list of errors causing the node state to differ from its set state.
/errors/_/member string 1 A JSON Pointer to the member causing a problem, relative to this document (the empty string means a generic error for the node).
/errors/_/message string 1 A non-empty textual description of the particular problem with the member.
/resources/_/avail integer 0..1 The currently unused amount of units of this resource available in the node to be allocated to slivers (may be null if unknown).
/addrs object 1 Contains the current values for different important node addresses (see node architecture and addressing).
/addrs/mgmt string 1 The node's management address.
/addrs/mgmt_host string 0..1 The node's host address if it uses the native backend for connecting to the management network, null otherwise.
/addrs/debug string 1 The node's debug address.
/addrs/local_mac string 1 The node's local MAC address.
/addrs/local_ipv4 string 0..1 The node's local IPv4 address. Null when IPv4 is not used in the local network.
/addrs/local_ipv6 string 0..1 The node's local IPv6 address. Null when IPv6 is not used in the local network.
/addrs/internal_ipv4 string 1 The node's internal IPv4 address.
/addrs/internal_ipv6 string 1 The node's internal IPv6 address.
/addrs/recovery_ipv4 string 1 The node's fixed recovery IPv4 address.
/addrs/recovery_ipv6 string 1 The node's fixed recovery IPv6 address.
/addrs/recovery_unique string 1 The node's unique recovery IPv6 address.
/slivers ref[] 0..n A list of slivers that the node knows are intended to run on it.

Existing Link: headers coming from the configuration are left untoched (i.e. pointing to the registry API). Additional links are:

Header Value Description
Link: <URI>; rel="http://confine-project.eu/rel/node/source" Contains the registry API URI used as the configuration source of this resource.
Link: <URI>; rel="http://confine-project.eu/rel/node/base" The base URI of the node API where this resource was retrieved from.
Link: <URI>; rel="http://confine-project.eu/rel/node/do-refresh" Contains the function URI used to refresh this node, i.e. to request a pull from the registry of all configuration resources relevant to the node. POST data: null.

Example:

// GET https://[2001:db8:cafe:3039::2]/confine/api/node
{
    "uri": "https://[2001:db8:cafe:3039::2]/confine/api/node",
 
    "id": 12345,
    "description": "This node is sponsored by the CONFINE project.\n\nBlah blah...",
    "arch": "i686",
    "soft_version": "1.2.3rc1",  // local state
    "boot_sn": 22,
    "set_state": "production",
 
    "state": "failure",  // local state
    "errors": [  // local state
        { "member": "", "message": "failed to mount data filesystem: I/O error" },
    ],
 
    "direct_ifaces": [ "eth0", "eth1", "wlan0" ],
    "properties": {
        "allow_fooserv_monitoring": "yes",
    },
 
    "resources": [
        // a single sliver may take all available public IPv4 addresses
        { "name": "pub_ipv4", "unit": "addrs", "max_req": 4, "dflt_req": 0, "avail": 4 },
        { "name": "pub_ipv6", "unit": "addrs", "max_req": null, "dflt_req": 0, "avail": null },
        { "name": "disk", "unit": "MiB", "max_req": 4096, "dflt_req": 512, "avail": 10258 },
        { "name": "memory", "unit": "MiB", "max_req": 1024, "dflt_req": 256, "avail": 768 },
    ],
 
    "api": {
        // from NodeApi
        "type": "node",
        "base_uri": "https://[2001:db8:cafe:3039::2]/confine/api/",
        "cert": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
    },
 
    "mgmt_net": {
        // from MgmtNetConf
        "addr": "2001:db8:cafe:3039::2",
        "backend": "tinc",
    },
 
    "tinc": {
        // from TincHost
        "name": "node_12345",
        "pubkey": "-----BEGIN RSA PUBLIC KEY-----\n...\n-----END RSA PUBLIC KEY-----",
        "addresses": [],
    },
 
    "cn": {
        // from CnHost
        "cndb_uri": "http://guifi.net/cndb/device/38720",
        "app_url": "http://guifi.net/guifi/device/38720",
    },
 
    "sfa": {
        "uuid": "d130b607-b2bc-471d-b2e1-f509981feff8",
        "pubkey": "-----BEGIN RSA PUBLIC KEY-----\n...\n-----END RSA PUBLIC KEY-----",
    },
 
    "addrs": [  // local state
        "mgmt": "2001:db8:cafe:3039::2",
        "mgmt_host": null,  // using tinc backend
        "debug": "fd5f:eee5:e6ad:3039::2",
        "local_mac": "00:11:22:33:44:55",
        "local_ipv4": "10.255.1.2",
        "local_ipv6": null,  // not used in this local network
        "internal_ipv4": "192.168.157.126",
        "internal_ipv6": "fdbd:e804:6aa9::1",
        "recovery_ipv4": "192.168.157.130",
        "recovery_ipv6": "fdbd:e804:6aa9:1::2",
        "recovery_unique": "fdbd:e804:6aa9:2:211:22ff:fe33:4455",
    ],
 
    "island": { "uri": "https://[2001:db8:cafe::2]/confine/api/islands/1", "id": 1 },
    "group": { "uri": "https://[2001:db8:cafe::2]/confine/api/groups/35", "id": 35 },
 
    // these link to local sliver descriptions
    "slivers": [
        { "uri": "https://[2001:db8:cafe:3039::2]/confine/api/slivers/9876543210", "id": "9876543210@12345" },
        { "uri": "https://[2001:db8:cafe:3039::2]/confine/api/slivers/5729459", "id": "5729459@12345" },
    ],
}
// Link: <https://[2001:db8:cafe::2]/confine/api/>; rel="http://confine-project.eu/rel/registry/base"
// Link: <https://[2001:db8:cafe::2]/confine/api/nodes/>; rel="http://confine-project.eu/rel/registry/node-list"
// Link: <https://[2001:db8:cafe::2]/confine/api/nodes/12345/ctl/reboot>; rel="http://confine-project.eu/rel/registry/do-reboot"
// Link: <https://[2001:db8:cafe::2]/confine/api/nodes/12345/ctl/request-api-cert>; rel="http://confine-project.eu/rel/controller/do-request-mgmt-cert"
// Link: <https://[2001:db8:cafe::2]/confine/api/nodes/12345/ctl/firmware>; rel="http://confine-project.eu/rel/controller/firmware"
// Link: <https://[2001:db8:cafe::2]/confine/api/nodes/12345>; rel="http://confine-project.eu/rel/node/source"
// Link: <https://[2001:db8:cafe:3039::2]/confine/api/>; rel="http://confine-project.eu/rel/node/base"
// Link: <https://[2001:db8:cafe:3039::2]/confine/api/node/ctl/refresh>; rel="http://confine-project.eu/rel/node/do-refresh"

Sliver at node

Media type: application/json; profile="http://confine-project.eu/schema/node/v1/sliver"

This resource shows the sliver configuration obtained from the registry for a sliver intended to be run on a node and complements it with local state from the node. Members coming from the configuration carry the same meaning as in the registry, but they can not be set here (i.e. no POST, PUT or PATCH methods allowed). Additional or differing members are:

Member Type N Default Methods Description
/uri string 1 The node API URI of this sliver.
/node ref 1 The node this sliver is intended to run on.
/template ref 1 The template to be used for this sliver, as specified in the sliver configuration or, if missing, in the sliver defaults in the slice configuration. Null when the sliver is not yet deployed.
/data_uri string 0..1 The URI of a file containing data for this sliver, as specified in the sliver configuration or, if missing, in the sliver defaults in the slice configuration.
/data_sha256 string 0..1 The SHA256 hash of the previous file, used to check its integrity.
/set_state string 1 The state set on this sliver (set state), as a result of considering the sliver configuration, the sliver defaults in the slice configuration and the slice's own set state, i.e. the sliver's effective set state. See Slice and sliver states for the computation of this value.
/nr integer 0..1 An 8-bit, positive, non-zero integer number used by the node to temporarily identify deployed slivers (see addressing). Null when the sliver is not yet deployed.
/state string 1 The current state of this sliver (from its set state). Possible values: registered, deployed, started, fail_allocate, fail_deploy, fail_start. See slice and sliver states for the full description of states and possible transitions.
/errors object[] 0..n A list of errors causing the last deploy or start attempt of this sliver to fail.
/errors/_/member string 1 A JSON Pointer to the member causing a problem, relative to this document. The empty string means a generic error for the sliver.
/errors/_/message string 1 A textual description of the particular problem with the member.
/resources object[] 0..n A list of resource requests currently allocated to this sliver, whether they derive from explicit requests in the sliver configuration, implicit ones like addresses from public interfaces, or explicit default requests in the slice configuration.
/resources/_/alloc integer 0..1 The amount of the requested resource currently allocated to the sliver. Null whent the sliver is not yet deployed.
/interfaces/_/vlan_tag integer 0..1 The VLAN tag used by this isolated interface. Null when the sliver is not yet deployed or the interface is not of the isolated type.
/interfaces/_/mac_addr string 0..1 The MAC address of this interface. Null when the sliver is not yet deployed.
/interfaces/_/ipv4_addr string 0..1 The IPv4 address of this interface. Only available for private and public4 interfaces. Null when the sliver is not yet deployed.
/interfaces/_/ipv6_addr string 0..1 The IPv6 address of this interface. Only available for private, debug, management and public6 interfaces. Null when the sliver is not yet deployed.

Existing Link: headers coming from the configuration are left untouched (i.e. pointing to the registry API). Additional links are:

Header Value Description
Link: <URI>; rel="http://confine-project.eu/rel/node/source" Contains the registry API URI used as the configuration source of this resource.
Link: <URI>; rel="http://confine-project.eu/rel/node/base" The base URI of the node API where this resource was retrieved from.
Link: <URI>; rel="http://confine-project.eu/rel/node/sliver-list" Contains the node API URI of the resource list of slivers in the node.
// GET https://[2001:db8:cafe:3039::2]/confine/api/slivers/9876543210
{
    "uri": "https://[2001:db8:cafe:3039::2]/confine/api/slivers/9876543210",
 
    "id": "9876543210@12345",
    // slice description always comes from the registry
    "slice": { "uri": "https://[2001:db8:cafe::2]/confine/api/slices/9876543210", "id": 9876543210 },
    // this links to local node description
    "node": { "uri": "https://[2001:db8:cafe:3039::2]/confine/api/node", "id": 12345 },
    "nr": 4,  // local state
    "description": "This sliver runs the master coordinating process...",
    "instance_sn": 9,
    "template": { "uri": "https://[2001:db8:cafe:3039::2]/confine/api/templates/4", "id": 4 },
    "data_uri": "http://.../sliver-data.tar.gz",
    "data_sha256": "114d003d0f04d0d39c0051709f72997ca30a11052ebab49b9f995e74225e0581",
    "set_state": "start",
 
    "state": "started",  // local state
    "errors": [],  // local state
 
    "properties": {
        "group_master_sliver": "yes",
    },
 
    "resources": [
        // allocations are local state
        { "name": "disk", "unit": "MiB", "req": 2048, "alloc": 2048 },
        // an allocation coming from sliver defaults
        { "name": "memory", "unit": "MiB", "req": 128, "alloc": 128 },
        // an implicit allocation because of public IPv4 interfaces
        { "name": "pub_ipv4", "unit": "addrs", "req": 1, "alloc": 1 },
    ],
 
    "interfaces": [
        // addresses are local state
        { "nr": 0, "name": "priv", "type": "private",
          "parent_name": null, "vlan_tag": null,
          "mac_addr": "06:ab:30:39:04:00", "ipv4_addr": "192.168.157.4",
          "ipv6_addr": "fdbd:e804:6aa9:0:1000:2:4cb0:16ea" },
        { "nr": 2, "name": "pub0", "type": "public4",
          "parent_name": null, "vlan_tag": null,
          "mac_addr": "06:ab:30:39:04:01", "ipv4_addr": "10.228.203.56",
          "ipv6_addr": null },
        { "nr": 1, "name": "mgt0", "type": "management",
          "parent_name": null, "vlan_tag": null,
          "mac_addr": "06:ab:30:39:04:01", "ipv4_addr": null,
          "ipv6_addr": "2001:db8:cafe:3039:1001:2:4cb0:16ea" },
        { "nr": 4, "name": "dbg0", "type": "debug",
          "parent_name": null, "vlan_tag": null,
          "mac_addr": "06:ab:30:39:04:04", "ipv4_addr": null,
          "ipv6_addr": "fd5f:eee5:e6ad:3039:1004:2:4cb0:16ea" },
        { "nr": 5, "name": "iso0", "type": "isolated",
          "parent_name": "eth1", "vlan_tag": 420,
          "mac_addr": "01:23:45:67:89:ab", "ipv4_addr": null,
          "ipv6_addr": null },
    ],
 
    "mgmt_net": {
        // from MgmtNetConf
        "addr": "2001:db8:cafe:3039:1001:2:4cb0:16ea",
        "backend": "native",
    },
}
// Link: <https://[2001:db8:cafe::2]/confine/api/>; rel="http://confine-project.eu/rel/registry/base"
// Link: <https://[2001:db8:cafe::2]/confine/api/slivers/>; rel="http://confine-project.eu/rel/registry/sliver-list"
// Link: <https://[2001:db8:cafe::2]/confine/api/slivers/12345-9876543210/ctl/update>; rel="http://confine-project.eu/rel/registry/do-update"
//       <https://[2001:db8:cafe::2]/confine/api/slivers/12345-9876543210/ctl/upload-data>; rel="http://confine-project.eu/rel/controller/do-upload-data"
// Link: <https://[2001:db8:cafe::2]/confine/api/slivers/12345-9876543210>; rel="http://confine-project.eu/rel/node/source"
// Link: <https://[2001:db8:cafe:3039::2]/confine/api/>; rel="http://confine-project.eu/rel/node/base"
// Link: <https://[2001:db8:cafe:3039::2]/confine/api/slivers/>; rel="http://confine-project.eu/rel/node/sliver-list"

Template at node

Media type: application/json; profile="http://confine-project.eu/schema/node/v1/template"

This resource describes a template that is currently stored in a node. It basically mirrors the template description obtained from the registry. Additional or differing members are:

Member Type N Default Methods Description
/uri string 1 The node API URI of this template.

Existing Link: headers coming from the configuration are left untouched (i.e. pointing to the registry API). Additional links are:

Header Value Description
Link: <URI>; rel="http://confine-project.eu/rel/node/source" Contains the registry API URI used as the configuration source of this resource.
Link: <URI>; rel="http://confine-project.eu/rel/node/base" The base URI of the node API where this resource was retrieved from.
Link: <URI>; rel="http://confine-project.eu/rel/node/template-list" Contains the node API URI of the resource list of templates in the node.

Example:

// GET https://[2001:db8:cafe:3039::2]/confine/api/templates/4
{
    "uri": "https://[2001:db8:cafe:3039::2]/confine/api/templates/4",
 
    "id": 4,
    "name": "debian,squeeze,i386,2012041700",
    "description": "A Debian sliver template with some useful network tools installed like...",
    "type": "debian",
    "node_archs": ["i586", "i686", "x86_64"],
    "is_active": true,
    "image_uri": "http://...",
    // so the template can be retrieved by unsafe means
    "image_sha256": "12774f8541de150504adc11b1fd5791b1238334f80f889f832580510f954678c",
}
// Link: <https://[2001:db8:cafe::2]/confine/api/>; rel="http://confine-project.eu/rel/registry/base"
// Link: <https://[2001:db8:cafe::2]/confine/api/templates/>; rel="http://confine-project.eu/rel/registry/template-list"
// Link: <https://[2001:db8:cafe::2]/confine/api/templates/4/ctl/upload-image>; rel="http://confine-project.eu/rel/controller/do-upload-image"
// Link: <https://[2001:db8:cafe::2]/confine/api/templates/4>; rel="http://confine-project.eu/rel/node/source"
// Link: <https://[2001:db8:cafe:3039::2]/confine/api/>; rel="http://confine-project.eu/rel/node/base"
// Link: <https://[2001:db8:cafe:3039::2]/confine/api/templates/>; rel="http://confine-project.eu/rel/node/template-list"

Interaction examples

Controller authentication

When running some of the operations below against a controller, it may require the user to be authenticated. To get an authentication token from a controller, the user must locate the link marked with the http://confine-project.eu/rel/controller/do-get-auth-token it the controller API base, then POST a user name and password to it:

// POST https://[2001:db8:cafe::2]/api-token-auth/
{
    "username": "foo",
    "password": "secret"
}
 
// 200 OK
{ "token": "63dba7274cc1087c1125e555e811a66f0876ba6a" }

The user may post an email address instead of a user name:

// POST https://[2001:db8:cafe::2]/api-token-auth/
{
    "username": "foo@bar.com",
    "password": "secret"
}
 
// 200 OK
{ "token": "63dba7274cc1087c1125e555e811a66f0876ba6a" }

The response contains an authentication token that may be provided in subsequent requests as the Authorization: Token TOKEN header.

If bad credentials are provided, an error is returned:

// POST https://[2001:db8:cafe::2]/api-token-auth/
{
    "username": "foo",
    "password": "badpassword"
}
 
// 400 Bad Request
{ "non_field_errors": [ "Unable to login with provided credentials." ] }

Node addition

A node administrator in some group calls GET on API base URL:

// GET https://[2001:db8:cafe::2]/confine/api/
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/",
 
    "confine_params": {
        "debug_ipv6_prefix": "fd5f:eee5:e6ad::/48",
        "priv_ipv6_prefix": "fdbd:e804:6aa9::/48",
    },
 
    "testbed_params": {
        "mgmt_ipv6_prefix": "2001:db8:cafe::/48",
    },
 
    "testbed_resources": [
        { "name": "vlan", "unit": "tags", "max_req": 1, "dflt_req": 0, "avail": 3820 },
    ],
}
// Link: <https://[2001:db8:cafe::2]/confine/api/>; rel="http://confine-project.eu/rel/registry/base"
// Link: <https://[2001:db8:cafe::2]/confine/api/servers/>; rel="http://confine-project.eu/rel/registry/server-list",
//       <https://[2001:db8:cafe::2]/confine/api/nodes/>; rel="http://confine-project.eu/rel/registry/node-list",
//       <https://[2001:db8:cafe::2]/confine/api/slices/>; rel="http://confine-project.eu/rel/registry/slice-list",
//       <https://[2001:db8:cafe::2]/confine/api/slivers/>; rel="http://confine-project.eu/rel/registry/sliver-list",
//       <https://[2001:db8:cafe::2]/confine/api/users/>; rel="http://confine-project.eu/rel/registry/user-list",
//       <https://[2001:db8:cafe::2]/confine/api/groups/>; rel="http://confine-project.eu/rel/registry/group-list",
//       <https://[2001:db8:cafe::2]/confine/api/hosts/>; rel="http://confine-project.eu/rel/registry/host-list",
//       <https://[2001:db8:cafe::2]/confine/api/templates/>; rel="http://confine-project.eu/rel/registry/template-list",
//       <https://[2001:db8:cafe::2]/confine/api/islands/>; rel="http://confine-project.eu/rel/registry/island-list",
//       <https://[2001:db8:cafe::2]/api-token-auth/>; rel="http://confine-project.eu/rel/controller/do-get-auth-token"

The node administrator uses node parameters and testbed_params together with the URL of one of the groups it is a node administrator in (not shown here) to fill the description of the new node, then uses this description in a POST call on the node list URL (the one linked with the http://confine-project.eu/rel/registry/node-list relation type). The members missing below are not allowed during node addition:

// POST https://[2001:db8:cafe::2]/confine/api/nodes/
{
    "name": "MyCampus NE rooftop",
    "description": "This node is sponsored by the CONFINE project.\n\nBlah blah...",
    "arch": "i686",
 
    "direct_ifaces": [ "eth0", "eth1", "wlan0" ],
    "properties": {
        "allow_fooserv_monitoring": "yes",
    },
 
    "resources": [
        // no more than 4 public IPv4 addresses per sliver
        { "name": "pub_ipv4", "unit": "addrs", "max_req": 4, "dflt_req": 0 },
        // public IPv6 addresses are unbound
        { "name": "pub_ipv6", "unit": "addrs", "max_req": null, "dflt_req": 0 },
        // default disk per sliver is 512 MiB, 4 GiB maximum
        { "name": "disk", "unit": "MiB", "max_req": 4096, "dflt_req": 512 },
        // default memory per sliver is 256 MiB, 1 GiB maximum
        { "name": "memory", "unit": "MiB", "max_req": 1024, "dflt_req": 256 },
    ],
 
    "api": null,  // to be filled later when the node ID is known
 
    "mgmt_net": {
        "backend": "tinc",
    },
 
    "tinc": {
        "pubkey": "-----BEGIN RSA PUBLIC KEY-----\n...\n-----END RSA PUBLIC KEY-----",
    },
 
    "cn": {
        "cndb_uri": "http://guifi.net/cndb/device/38720",
        "app_url": "http://guifi.net/guifi/device/38720",
    },
 
    "sfa": {
        "uuid": "d130b607-b2bc-471d-b2e1-f509981feff8",
        "pubkey": "-----BEGIN RSA PUBLIC KEY-----\n...\n-----END RSA PUBLIC KEY-----",
    },
 
    "island": { "uri": "https://[2001:db8:cafe::2]/confine/api/islands/1", "id": 1 },
    "group": { "uri": "https://[2001:db8:cafe::2]/confine/api/groups/35", "id": 35 },
}

Assuming the given group has /allow_nodes=true, the registry server responds with code 201 Created and a Location header with the URL of the node. Retrieving that node URL results in the almost full node description:

// GET https://[2001:db8:cafe::2]/confine/api/nodes/12345
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/nodes/12345",
 
    "id": 12345,
    "name": "MyCampus NE rooftop",
    "description": "This node is sponsored by the CONFINE project.\n\nBlah blah...",
    "arch": "i686",
    "boot_sn": 0,
    "set_state": "debug",  // some keys are still missing
 
    "direct_ifaces": [ "eth0", "eth1", "wlan0" ],
    "properties": {
        "allow_fooserv_monitoring": "yes",
    },
 
    "resources": [
        { "name": "pub_ipv4", "unit": "addrs", "max_req": 4, "dflt_req": 0 },
        { "name": "pub_ipv6", "unit": "addrs", "max_req": null, "dflt_req": 0 },
        { "name": "disk", "unit": "MiB", "max_req": 4096, "dflt_req": 512 },
        { "name": "memory", "unit": "MiB", "max_req": 1024, "dflt_req": 256 },
    ],
 
    "api": null,
 
    "mgmt_net": {
        "addr": "2001:db8:cafe:3039::2",
        "backend": "tinc",
    },
 
    "tinc": {
        "name": "node_12345",
        "pubkey": "-----BEGIN RSA PUBLIC KEY-----\n...\n-----END RSA PUBLIC KEY-----",
        "addresses": [],
    },
 
    "cn": {
        "cndb_uri": "http://guifi.net/cndb/device/38720",
        "app_url": "http://guifi.net/guifi/device/38720",
    },
 
    "sfa": {
        "uuid": "d130b607-b2bc-471d-b2e1-f509981feff8",
        "pubkey": "-----BEGIN RSA PUBLIC KEY-----\n...\n-----END RSA PUBLIC KEY-----",
    },
 
    "island": { "uri": "https://[2001:db8:cafe::2]/confine/api/islands/1", "id": 1 },
    "group": { "uri": "https://[2001:db8:cafe::2]/confine/api/groups/35", "id": 35 },
 
    "slivers": [],
}
// Link: <https://[2001:db8:cafe::2]/confine/api/>; rel="http://confine-project.eu/rel/registry/base"
// Link: <https://[2001:db8:cafe::2]/confine/api/nodes/>; rel="http://confine-project.eu/rel/registry/node-list"
// Link: <https://[2001:db8:cafe::2]/confine/api/nodes/12345/ctl/reboot>; rel="http://confine-project.eu/rel/registry/do-reboot"
// Link: <https://[2001:db8:cafe::2]/confine/api/nodes/12345/ctl/request-api-cert>; rel="http://confine-project.eu/rel/controller/do-request-mgmt-cert"
// Link: <https://[2001:db8:cafe::2]/confine/api/nodes/12345/ctl/firmware>; rel="http://confine-project.eu/rel/controller/firmware"

Now that the node has a basic configuration which includes its ID and tinc public key, the node administrator can push it to the node together with some management network gateway descriptions (not shown here) so it can run its tinc daemon (which tries to connect to the other given daemons in the management network) and start polling registry servers. The node administrator then calls PATCH on the node URL to enable the node in the registry:

// PATCH https://[2001:db8:cafe::2]/confine/api/nodes/12345
[
    { "op": "replace", "path": "/set_state", "value": "production" },
]

The registry server performs the state change successfully and responds with code 204 No Content. Retrieving the node URL shows the change:

// GET https://[2001:db8:cafe::2]/confine/api/nodes/12345
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/nodes/12345",
 
    "id": 12345,
    "set_state": "production",
    // ...
    "api": null,
    // ...
}

Please note that the node is still lacking a base URI and certificate for its API. This means that its state cannot be monitored by external hosts. However, now that the node ID and its management address are known, the node administrator may ask the testbed CA for a certificate and configure the node to serve its API on its management address:

// PATCH https://[2001:db8:cafe::2]/confine/api/nodes/12345
[
    { "op": "replace", "path": "/api", "value": {
        "type": "node",
        "base_uri": "https://[2001:db8:cafe:3039::2]/confine/api/",
        "cert": "value": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
       }
    }
]

The node administrator may as well configure a caching proxy (which may or may not be a host in the management network) to lessen the load on the node:

// PATCH https://[2001:db8:cafe::2]/confine/api/nodes/12345
[
    { "op": "replace", "path": "/api/base_uri", "value": "http://my-caching-proxy/node/12345/" },
]

In the example plain HTTP access is used, which may not be desirable. HTTPS and a certificate expected to be recognised by node API clients may be used instead.

Slice creation

The slice administrator calls GET on the API base URL and obtains the template list and slice list URLs (the ones linked with the http://confine-project.eu/rel/registry/template-list and http://confine-project.eu/rel/registry/slice-list relation types). From the template list it gets the URL of the template to use and from member /group_roles in the user's own description it gets the URL of one of the groups it is a slice administrator in (not shown here), then calls POST on the slice list URL with the new slice description. The description includes a request by the slice for a VLAN to be used by isolated sliver interfaces and default resource requests for slivers in the slice for 1 GiB of disk space and XXXX MiB of memory, as well as a default template and data file for slivers. The members missing below are not allowed during slice creation:

// POST https://[2001:db8:cafe::2]/confine/api/slices/
{
    "name": "foobar",
    "description": "This slice runs an experiment for P2P foobar, see http://...",
    "allow_isolated": true,  // asks for tag on deployment
 
    "properties": {
        "omf_foo_cookie": "0x1a2b3c4d",
    },
 
    "sliver_defaults": {
        "template": { "uri": "https://[2001:db8:cafe::2]/confine/api/templates/4", "id": 4 },
        "data_uri": "http://.../sliver-data.tar.gz",
        "data_sha256": "114d003d0f04d0d39c0051709f72997ca30a11052ebab49b9f995e74225e0581",
        "set_state": "start",  // limited by slice's set state
        "resources": [
            // default requests for slivers
            { "name": "disk", "unit": "MiB", "req": 1024 },
            { "name": "memory", "unit": "MiB", "req": 128 },
        ],
    },
 
    "sfa": {
        "uuid": "43b7dde3-1b65-4879-9fb1-846f1c85fb93",
        "pubkey": "-----BEGIN RSA PUBLIC KEY-----\n...\n-----END RSA PUBLIC KEY-----",
    },
 
    "group": { "uri": "https://[2001:db8:cafe::2]/confine/api/groups/12", "id": 12 },
}

Assuming the given group has /allow_slices=true, the registry server responds with code 201 Created and a Location header with the URL of the slice. Retrieving that slice URL results in the full slice description:

// GET https://[2001:db8:cafe::2]/confine/api/slices/9876543210
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/slices/9876543210",
 
    "id": 9876543210,
    "name": "foobar",
    "description": "This slice runs an experiment for P2P foobar, see http://...",
    "expires_on": "2012-07-20T11:25:33Z",  // some time in the future
    "instance_sn": 0,  // not reset yet
    "allow_isolated": true,
    "isolated_vlan_tag": null,  // not deployed yet
    "set_state": "register",  // not deployed yet
 
    "properties": {
        "omf_foo_cookie": "0x1a2b3c4d",
    },
 
    "resources": [
        // an implicit request for a VLAN tag, not allocated yet
        { "name": "vlan", "unit": "tags", "req": 1, "alloc": null },
    ],
 
    "sliver_defaults": {
        "instance_sn": 0,  // slivers not updated yet
        "template": { "uri": "https://[2001:db8:cafe::2]/confine/api/templates/4", "id": 4 },
        "data_uri": "http://.../sliver-data.tar.gz",
        "data_sha256": "114d003d0f04d0d39c0051709f72997ca30a11052ebab49b9f995e74225e0581",
        "set_state": "start",
        "resources": [
            { "name": "disk", "unit": "MiB", "req": 1024 },
            { "name": "memory", "unit": "MiB", "req": 128 },
        ],
    },
 
    "sfa": {
        "uuid": "43b7dde3-1b65-4879-9fb1-846f1c85fb93",
        "pubkey": "-----BEGIN RSA PUBLIC KEY-----\n...\n-----END RSA PUBLIC KEY-----",
    },
 
    "group": { "uri": "https://[2001:db8:cafe::2]/confine/api/groups/12", "id": 12 },
 
    "slivers": [],
}
// Link: <https://[2001:db8:cafe::2]/confine/api/>; rel="http://confine-project.eu/rel/registry/base"
// Link: <https://[2001:db8:cafe::2]/confine/api/slices/>; rel="http://confine-project.eu/rel/registry/slice-list"
// Link: <https://[2001:db8:cafe::2]/confine/api/slices/9876543210/ctl/renew>; rel="http://confine-project.eu/rel/registry/do-renew",
//       <https://[2001:db8:cafe::2]/confine/api/slices/9876543210/ctl/reset>; rel="http://confine-project.eu/rel/registry/do-reset"
//       <https://[2001:db8:cafe::2]/confine/api/slices/9876543210/ctl/upload-data>; rel="http://confine-project.eu/rel/controller/do-upload-data"

The slice administrator now wants to create in this slice a new sliver with 2 GiB of disk space and public IPv4 and IPv6 addresses. After obtaining from the API base the node list URL (the one linked with the http://confine-project.eu/rel/registry/node-list relation type), the slice administrator looks there for a node that satisfies the needs of the sliver (not shown here). Node 12345 seems to cover them:

// GET https://[2001:db8:cafe::2]/confine/api/nodes/12345
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/nodes/12345",
 
    "id": 12345,
    // ...
    "resources": [
        { "name": "pub_ipv4", "unit": "addrs", "max_req": 4, "dflt_req": 0 },
        { "name": "pub_ipv6", "unit": "addrs", "max_req": null, "dflt_req": 0 },
        { "name": "disk", "unit": "MiB", "max_req": 4096, "dflt_req": 512 },
        { "name": "memory", "unit": "MiB", "max_req": 1024, "dflt_req": 256 },
    ],
    // ...
}

After obtaining from the API base the sliver list URL (the one linked with the http://confine-project.eu/rel/registry/sliver-list relation type), the slice administrator calls POST on it with the new sliver description. The sliver will use the template, data file and resource requests declared by its parent slice's sliver defaults, and it will have some public interfaces. In particular, it will use its first (and only) IPv4 public interface for its default IPv4 route. The members missing below are not allowed during sliver creation:

// POST https://[2001:db8:cafe::2]/confine/api/slivers/
{
    "slice": { "uri": "https://[2001:db8:cafe::2]/confine/api/slices/9876543210", "id": 9876543210 },
    "node": { "uri": "https://[2001:db8:cafe::2]/confine/api/nodes/12345", "id": 12345 },
    "description": "This sliver runs the master coordinating process...",
    "template": null,  // use slice's sliver default
    "data_uri": null,  // use slice's sliver default
 
    "properties": {
        "group_master_sliver": "yes",
    },
 
    "resources": [
        { "name": "disk", "unit": "MiB", "req": 2048 },
    ],
 
    "interfaces": [
        { "nr": 0, "name": "priv", "type": "private" },
        { "nr": 1, "name": "pub6", "type": "public6" },
        { "nr": 2, "name": "pub4", "type": "public4" },
    ],
}

After creating this and other slivers, the slice administrator calls PATCH on the slice URL to deploy it:

// PATCH https://[2001:db8:cafe::2]/confine/api/slices/9876543210
[
    { "op": "replace", "path": "/set_state", "value": "deploy" },
]

The registry server responds with code 204 No Content. Calling GET on the slice URL shows that a VLAN tag has been allocated (as shown in /resources) and made available in the /isolated_vlan_tag member. The default disk and memory requests only get allocated in slivers, so they show no allocation:

// GET https://[2001:db8:cafe::2]/confine/api/slices/9876543210
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/slices/9876543210",
 
    "id": 9876543210,
    // ...
    "allow_isolated": true,
    "isolated_vlan_tag": 420,  // allocated on deployment
    "set_state": "deploy",
 
    "resources": [
        // an implicit request for a VLAN tag, allocated on deployment
        { "name": "vlan", "unit": "tags", "req": 1, "alloc": 1 },
    ],
 
    "sliver_defaults": {
        // ...
        "resources": [
            // default requests for slivers
            { "name": "disk", "unit": "MiB", "req": 1024 },
            { "name": "memory", "unit": "MiB", "req": 128 },
        ],
    },
    // ...
}

After running experiments, the slice administrator calls PATCH on the slice URL to stop it:

// PATCH https://[2001:db8:cafe::2]/confine/api/slices/9876543210
[
    { "op": "replace", "path": "/set_state", "value": "register" },
]

The registry server responds with code 204 No Content. Calling GET on the slice URL shows that its VLAN tag has been deallocated and no longer available in the /isolated_vlan_tag member:

// GET https://[2001:db8:cafe::2]/confine/api/slices/9876543210
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/slices/9876543210",
 
    "id": 9876543210,
    // ...
    "allow_isolated": true,
    "isolated_vlan_tag": null,  // not deployed
    "set_state": "register",
    // ...
}

Sliver deployment failures

In the previous example the slice administrator didn't check that the sliver in the slice was actually deployed. After changing the slice's set state to deploy the sliver state is retrieved from its node, yielding the following result:

// GET https://[2001:db8:cafe:3039::2]/confine/api/slivers/9876543210
{
    "uri": "https://[2001:db8:cafe:3039::2]/confine/api/slivers/9876543210",
 
    "id": "9876543210@12345",
    "slice": { "uri": "https://[2001:db8:cafe::2]/confine/api/slices/9876543210", "id": 9876543210 },
    "node": { "uri": "https://[2001:db8:cafe:3039::2]/confine/api/node", "id": 12345 },
    // ...
    "state": "fail_allocate",
    "errors": [
        { "member": "/interfaces/2/type", "message": "not enough public IPv4 addresses available" },
    ],
 
    "resources": [
        { "name": "disk", "unit": "MiB", "req": 2048, "alloc": null },
        { "name": "memory", "unit": "MiB", "req": 128, "alloc": 128 },
        { "name": "pub_ipv6", "unit": "addrs", "req": 1, "alloc": null },
        { "name": "pub_ipv4", "unit": "addrs", "req": 1, "alloc": null },
    ],
 
    "interfaces": [
        { "nr": 0, "name": "priv", "type": "private",
          "parent_name": null, "vlan_tag": null,
          "mac_addr": null, "ipv4_addr": null, "ipv6_addr": null },
        { "nr": 1, "name": "pub6", "type": "public6",
          "parent_name": null, "vlan_tag": null,
          "mac_addr": null, "ipv4_addr": null, "ipv6_addr": null },
        { "nr": 2, "name": "pub4", "type": "public4",
          "parent_name": null, "vlan_tag": null,
          "mac_addr": null, "ipv4_addr": null, "ipv6_addr": null },
    ],
    //...
}

The sliver's state being fail_allocate indicates that the sliver hasn't been deployed because resources could not be allocated, in this case public IPv4 addresses that were temporarily unavailable, as stated in errors. This kind of failure can go away as soon as other slivers in the node release the needed resource, in which case the sliver will be deployed or started (depending on the value of set_state in the slice).

Failures caused by a sliver configuration that cannot possibly be applied are also flagged by the fail_allocate state, for instance:

// GET https://[2001:db8:cafe:3039::2]/confine/api/slivers/9876543210
{
    "uri": "https://[2001:db8:cafe:3039::2]/confine/api/slivers/9876543210",
 
    // ...
    "state": "fail_allocate",
    "errors": [
        { "member": "/interfaces/4/parent_name", "message": "no such direct interface" },
    ],
    //...
}

Once the sliver's resources have been allocated, failures that take place while deploying the sliver are flagged by the fail_deploy state, for instance:

// GET https://[2001:db8:cafe:3039::2]/confine/api/slivers/9876543210
{
    "uri": "https://[2001:db8:cafe:3039::2]/confine/api/slivers/9876543210",
 
    // ...
    "state": "fail_deploy",
    "errors": [
        { "member": "", "message": "failed to download data file" },
    ],
    //...
}

Finally, failures that take place while starting the sliver are flagged by the fail_start state.

Node reboot

Given the following configuration of a node:

// GET https://[2001:db8:cafe::2]/confine/api/nodes/12345
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/nodes/12345",
 
    // ...
    "boot_sn": 23,
    // ...
}
// Link: ..., <https://[2001:db8:cafe::2]/confine/api/nodes/12345/ctl/reboot>; rel="http://confine-project.eu/rel/registry/do-reboot", ...

To reboot the node, the node administrator calls POST on the node's do-reboot function URI with a null value:

// POST https://[2001:db8:cafe::2]/confine/api/nodes/12345/ctl/reboot
null

The registry server responds with code 303 See Other and a Location header with the URL of the node. Retrieving the node URL shows that the node's boot sequence number member has been incremented:

// GET https://[2001:db8:cafe::2]/confine/api/nodes/12345
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/nodes/12345",
 
    // ...
    "boot_sn": 24,
    // ...
}

When the node notices an increment in that member, it reboots.

Slice renewal

Given the following configuration of a slice:

// GET https://[2001:db8:cafe::2]/confine/api/slices/9876543210
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/slices/9876543210",
 
    "id": 9876543210,
    // ...
    "expires_on": "2012-07-20T11:25:33Z",
    // ...
}
// Link: ..., <https://[2001:db8:cafe::2]/confine/api/slices/9876543210/ctl/renew>; rel="http://confine-project.eu/rel/registry/do-renew", ...

To renew the sliver the user with the adequate permission (see Roles and permissions) calls POST on the slice's do-renew URI with a null value:

// POST https://[2001:db8:cafe::2]/confine/api/slices/9876543210/ctl/renew
null

The registry server responds with code 303 See Other and a Location header with the URL of the slice. Retrieving the slice URL shows that its expiration time has been changed to some time in the future:

// GET https://[2001:db8:cafe::2]/confine/api/slices/9876543210
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/slices/9876543210",
 
    "id": 9876543210,
    // ...
    "expires_on": "2012-10-20T11:25:33Z",
    // ...
}

The registry may only accept renewal requests happening within a given time span before the expiration date (e.g. 15 days) to avoid repeated renewal requests to extend the slice's expiration time without limits.

Slice reset

Given the following configuration of a slice:

// GET https://[2001:db8:cafe::2]/confine/api/slices/9876543210
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/slices/9876543210",
 
    "id": 9876543210,
    // ...
    "instance_sn": 2,
    "set_state": "start",
    // ...
}
// Link: ..., <https://[2001:db8:cafe::2]/confine/api/slices/9876543210/ctl/reset>; rel="http://confine-project.eu/rel/registry/do-reset", ...

To reset the slice (i.e. redeploy all of its slivers without changing their configuration nor reallocating their resources) the user with the adequate permission (see Roles and permissions) calls POST on the slice's do-reset URI with a null value:

// POST https://[2001:db8:cafe::2]/confine/api/slices/9876543210/ctl/reset
null

The registry server responds with code 303 See Other and a Location header with the URL of the slice. Retrieving the slice URL shows that its instance sequence number member has been incremented:

// GET https://[2001:db8:cafe::2]/confine/api/slices/9876543210
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/slices/9876543210",
 
    "id": 9876543210,
    // ...
    "instance_sn": 3,
    "set_state": "start",
    // ...
}

When a node already hosting one of the slivers of that slice notices an increment in that member, it stops the sliver (if running), then redeploys it with the same configuration and starts it (because of set_state = start). That means that the node must keep all source data and configuration of all the slivers it currently hosts.

Sliver update

Given the following configuration of a sliver:

// GET https://[2001:db8:cafe::2]/confine/api/slivers/12345-9876543210
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/slivers/12345-9876543210",
 
    "id": "9876543210@12345",
    "slice": { "uri": "https://[2001:db8:cafe::2]/confine/api/slices/9876543210", "id": 9876543210 },
    "node": { "uri": "https://[2001:db8:cafe::2]/confine/api/nodes/12345", "id": 12345 },
    "instance_sn": 9,
    // ...
}
// Link: ..., <https://[2001:db8:cafe::2]/confine/api/slivers/12345-9876543210/ctl/update>; rel="http://confine-project.eu/rel/registry/do-update", ...

and its slice:

// GET https://[2001:db8:cafe::2]/confine/api/slices/9876543210
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/slices/9876543210",
 
    "id": 9876543210,
    // ...
    "new_sliver_instance_sn": 12,
    // ...
}

To update the sliver (i.e. reallocate and redeploy it, possibly with a new configuration) a user with the adequate permission (see Roles and permissions) calls POST on the sliver's do-update URI with a null value:

// POST https://[2001:db8:cafe::2]/confine/api/slivers/12345-9876543210/ctl/update
null

The registry server responds with code 303 See Other and a Location header with the URL of the sliver. Retrieving the sliver URL shows that its instance sequence number member has been incremented:

// GET https://[2001:db8:cafe::2]/confine/api/slivers/12345-9876543210
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/slivers/12345-9876543210",
 
    "id": "9876543210@12345",
    "slice": { "uri": "https://[2001:db8:cafe::2]/confine/api/slices/9876543210", "id": 9876543210 },
    "node": { "uri": "https://[2001:db8:cafe::2]/confine/api/nodes/12345", "id": 12345 },
    "instance_sn": 10,
    // ...
}

The new sliver instance sequence number in the slice has been incremented as well:

// GET https://[2001:db8:cafe::2]/confine/api/slices/9876543210
{
    "uri": "https://[2001:db8:cafe::2]/confine/api/slices/9876543210",
 
    "id": 9876543210,
    // ...
    "new_sliver_instance_sn": 13,
    // ...
}

When the node hosting the sliver notices an increment in the sliver's sequence number, it stops the sliver (if running), then tries to reallocate its resources and redeploy it with the given configuration and starts it (always according to set_state in the slice description).

If the sliver configuration changes without increasing its instance sequence number, the node may choose whether to apply the changes or not. If both the instance sequence number and configuration change and there are not enough resources available for the new configuration, the node may not accept the sliver yet.

Please note how the new sliver sequence number in the slice description was automatically incremented as well on sliver update. In this way, deleting a sliver description and creating it anew never rolls its sequence number back to an old value (e.g. any new sliver in the slice above would get 13 as its initial serial number).

arch/rest-api.txt · Last modified: 2015/05/27 11:49 by ivilata