phenix (0.0.0)

Download OpenAPI specification:

phenix API

Configs

Config details and controls

Get all phenix configs

query Parameters
kind
string
Default: "all"
Enum: "all" "topology" "scenario" "experiment" "image" "user" "role"

limit configs to specified kind (defaults to all)

Responses

Response samples

Content type
application/json
{
  • "configs": [
    ]
}

Create new phenix config

Needs configs create on the config the body names, by its kind and name (such as Topology/lab). The server replaces each ${BRANCH_NAME} placeholder with a value from its environment. It stores every other ${NAME} placeholder as written.

Request Body schema:
required

phenix config creation parameters

apiVersion
required
string
kind
required
string
required
object
required
object

Responses

Request samples

Content type
{
  • "apiVersion": "string",
  • "kind": "string",
  • "metadata": {
    },
  • "spec": { }
}

Response samples

Content type
application/json
{
  • "message": "string",
  • "cause": "string",
  • "metadata": {
    }
}

Get existing phenix config

path Parameters
kind
required
string

kind of phenix config to get

name
required
string

name of phenix config to get

header Parameters
Accept
string
Default: application/json
Enum: "application/json" "application/x-yaml"

content format for response

Responses

Response samples

Content type
{
  • "apiVersion": "string",
  • "kind": "string",
  • "metadata": {
    },
  • "spec": { }
}

Update existing phenix config

Can also be used to rename a config by changing the name in the metadata portion of the config header and using the old name in the request path. Renaming a Topology, or changing its kind, removes the Builder documents published under its old name, as deleting it does. The builder-doc annotation of the renamed config loses the id and the digest that Publish wrote. The annotation keeps a path, and the digest beside that path. The server removes the annotation when it is empty (see BuilderDocumentReference). Needs configs update on the config of the path and, when the body names another kind or name, on that config too. The server replaces each ${BRANCH_NAME} placeholder with a value from its environment. It stores every other ${NAME} placeholder as written.

path Parameters
kind
required
string

kind of phenix config to get

name
required
string

name of phenix config to get

Request Body schema:
required

phenix config update parameters

apiVersion
required
string
kind
required
string
required
object
required
object

Responses

Request samples

Content type
{
  • "apiVersion": "string",
  • "kind": "string",
  • "metadata": {
    },
  • "spec": { }
}

Response samples

Content type
application/json
{
  • "message": "string",
  • "cause": "string",
  • "metadata": {
    }
}

Delete existing phenix config

path Parameters
kind
required
string

kind of phenix config to delete

name
required
string

name of phenix config to delete

Responses

Schemas

Config spec schemas

Get full schema (all config specs) for specific version

Each version's schema file holds the schemas of the config kinds stored at that version, and a config is validated against the file of its own apiVersion: v0 holds Workflow; v1 holds Topology, Experiment, Image, User and Role; v2 holds Scenario.

path Parameters
version
required
string
Enum: "v0" "v1" "v2"

version of phenix config schema to get

header Parameters
Accept
string
Default: application/json
Enum: "application/json" "application/x-yaml"

content format for response

Responses

Response samples

Content type
{ }

Get schema for specific config spec kind/version

A kind's schema exists only in the version it is stored at, the version its configs are validated against: Workflow in v0, Scenario in v2, and every other kind in v1.

path Parameters
kind
required
string
Enum: "topology" "scenario" "experiment" "image" "user" "role" "workflow"

kind of phenix config schema to get

version
required
string
Enum: "v0" "v1" "v2"

version of phenix config schema to get

header Parameters
Accept
string
Default: application/json
Enum: "application/json" "application/x-yaml"

content format for response

Responses

Response samples

Content type
{ }

Get the JSON Schema of Builder documents

Requires builder use.

Responses

Response samples

Content type
application/json
{ }

Get the JSON Schema of Builder template files

Requires builder use, as the document schema does. A template file holds one collection of device templates, in YAML or JSON. The Node Templates tab exports and imports this file. At start, phenix reads the template files in its template directory (--base-dir.builder-templates) as read-only server collections.

Responses

Response samples

Content type
application/json
{ }

Get the JSON Schema of Builder layer set files

Requires builder use, as the document schema does. A layer set file holds one layer set, in YAML or JSON, with copies of the custom icons that it names. The Layers tab of the Drafts page downloads and uploads this file.

Responses

Response samples

Content type
application/json
{ }

Get the JSON Schema of Builder packages

Requires builder use, as the document schema does. A Builder package is one JSON or YAML file (POST /builder/package makes one). It holds a Builder document, and the list of what the diagram needs on a phenix server. It also holds the Scenario and Topology configs and custom icons that the document names, when the request that made the package selected them.

Responses

Response samples

Content type
application/json
{ }

Experiments

Experiments details and controls

Get all phenix experiments

query Parameters
screenshot
string

whether or not to include VM screenshots (value is size to grab)

Responses

Response samples

Content type
application/json
{
  • "experiments": [
    ]
}

Create new phenix experiment

Request Body schema: application/json
required

phenix experiment creation parameters

name
string
topology
string
apps
Array of strings
vlan_min
integer
vlan_max
integer

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "topology": "string",
  • "apps": [
    ],
  • "vlan_min": 0,
  • "vlan_max": 0
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "topology": "string",
  • "apps": [
    ],
  • "start_time": "2019-08-24T14:15:22Z",
  • "running": true,
  • "vm_count": 0,
  • "vlan_min": 0,
  • "vlan_max": 0,
  • "vlan_count": 0,
  • "vlans": [
    ],
  • "vms": {
    }
}

Get existing phenix experiment

path Parameters
name
required
string

name of phenix experiment to get

query Parameters
screenshot
string

whether or not to include VM screenshots (value is size to grab)

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "topology": "string",
  • "apps": [
    ],
  • "start_time": "2019-08-24T14:15:22Z",
  • "running": true,
  • "vm_count": 0,
  • "vlan_min": 0,
  • "vlan_max": 0,
  • "vlan_count": 0,
  • "vlans": [
    ],
  • "vms": {
    }
}

Delete existing phenix experiment

path Parameters
name
required
string

name of phenix experiment to delete

Responses

Start existing phenix experiment

path Parameters
name
required
string

name of phenix experiment to start

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "topology": "string",
  • "apps": [
    ],
  • "start_time": "2019-08-24T14:15:22Z",
  • "running": true,
  • "vm_count": 0,
  • "vlan_min": 0,
  • "vlan_max": 0,
  • "vlan_count": 0,
  • "vlans": [
    ],
  • "vms": {
    }
}

Stop existing phenix experiment

path Parameters
name
required
string

name of phenix experiment to stop

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "topology": "string",
  • "apps": [
    ],
  • "start_time": "2019-08-24T14:15:22Z",
  • "running": true,
  • "vm_count": 0,
  • "vlan_min": 0,
  • "vlan_max": 0,
  • "vlan_count": 0,
  • "vlans": [
    ],
  • "vms": {
    }
}

Get current schedule for existing experiment

path Parameters
name
required
string

name of phenix experiment to get schedule for

Responses

Response samples

Content type
application/json
{
  • "schedule": [
    ]
}

Update current schedule for existing experiment

path Parameters
name
required
string

name of phenix experiment to update schedule for

Request Body schema: application/json
required

scheduling algorithm to use

algorithm
string

Responses

Request samples

Content type
application/json
{
  • "algorithm": "string"
}

Response samples

Content type
application/json
{
  • "schedule": [
    ]
}

Get captures for existing experiment

path Parameters
name
required
string

name of phenix experiment to get captures for

Responses

Response samples

Content type
application/json
{
  • "captures": [
    ]
}

Get list of files for experiment

path Parameters
name
required
string

name of phenix experiment to get files for

Responses

Response samples

Content type
application/json
{
  • "files": [
    ]
}

Download experiment file

path Parameters
name
required
string

name of phenix experiment to get file from

filename
required
string

name of file download

Responses

Virtual Machines

Experiment VM details and controls

get all VMs in existing experiment

path Parameters
exp_name
required
string

name of phenix experiment to get VMs for

query Parameters
screenshot
string

whether or not to include VM screenshots (value is size to grab)

Responses

Response samples

Content type
application/json
{
  • "vms": [
    ]
}

get given VM in existing experiment

path Parameters
exp_name
required
string

name of phenix experiment to get VM from

vm_name
required
string

name of phenix experiment VM to get

query Parameters
screenshot
string

whether or not to include VM screenshots (value is size to grab)

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "experiment": "string",
  • "host": "string",
  • "ipv4": [
    ],
  • "cpus": 0,
  • "ram": 0,
  • "disk": "string",
  • "dnb": true,
  • "networks": [
    ],
  • "taps": [
    ],
  • "captures": [
    ],
  • "running": true,
  • "uptime": 0.1,
  • "screenshot": "string"
}

Update existing VM settings in existing experiment

path Parameters
exp_name
required
string

name of phenix experiment to modify

vm_name
required
string

name of phenix virtual machine to modify

Request Body schema: application/json
required

phenix virtual machine patch parameters

host
string
cpus
integer
ram
integer
disk
string
dnb
boolean
object

Responses

Request samples

Content type
application/json
{
  • "host": "string",
  • "cpus": 0,
  • "ram": 0,
  • "disk": "string",
  • "dnb": true,
  • "interface": {
    }
}

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "experiment": "string",
  • "host": "string",
  • "ipv4": [
    ],
  • "cpus": 0,
  • "ram": 0,
  • "disk": "string",
  • "dnb": true,
  • "networks": [
    ],
  • "taps": [
    ],
  • "captures": [
    ],
  • "running": true,
  • "uptime": 0.1,
  • "screenshot": "string"
}

Delete phenix experiment VM

path Parameters
exp_name
required
string

name of phenix experiment

vm_name
required
string

name of phenix virtual machine to delete

Responses

start VM in experiment

path Parameters
exp_name
required
string

name of phenix experiment

vm_name
required
string

name of phenix VM to start

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "experiment": "string",
  • "host": "string",
  • "ipv4": [
    ],
  • "cpus": 0,
  • "ram": 0,
  • "disk": "string",
  • "dnb": true,
  • "networks": [
    ],
  • "taps": [
    ],
  • "captures": [
    ],
  • "running": true,
  • "uptime": 0.1,
  • "screenshot": "string"
}

stop VM in experiment

path Parameters
exp_name
required
string

name of phenix experiment

vm_name
required
string

name of phenix VM to stop

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "experiment": "string",
  • "host": "string",
  • "ipv4": [
    ],
  • "cpus": 0,
  • "ram": 0,
  • "disk": "string",
  • "dnb": true,
  • "networks": [
    ],
  • "taps": [
    ],
  • "captures": [
    ],
  • "running": true,
  • "uptime": 0.1,
  • "screenshot": "string"
}

redeploy VM in experiment

path Parameters
exp_name
required
string

name of phenix experiment

vm_name
required
string

name of phenix VM to redeploy

Responses

Response samples

Content type
application/json
{
  • "id": 0,
  • "name": "string",
  • "experiment": "string",
  • "host": "string",
  • "ipv4": [
    ],
  • "cpus": 0,
  • "ram": 0,
  • "disk": "string",
  • "dnb": true,
  • "networks": [
    ],
  • "taps": [
    ],
  • "captures": [
    ],
  • "running": true,
  • "uptime": 0.1,
  • "screenshot": "string"
}

Get screenshot of running VM in experiment

path Parameters
exp_name
required
string

name of phenix experiment

vm_name
required
string

name of phenix virtual machine to get screenshot from

query Parameters
size
string

size of screenshot to grab

base64
boolean

whether or not to base64 encode the screenshot image

Responses

Tunnel to VNC of running VM using a WebSocket

path Parameters
exp_name
required
string

name of phenix experiment

vm_name
required
string

name of phenix virtual machine to connect to

Responses

get phenix experiment VM packet captures

path Parameters
exp_name
required
string

name of phenix experiment

vm_name
required
string

name of phenix VM to get captures for

Responses

Response samples

Content type
application/json
{
  • "captures": [
    ]
}

start phenix experiment VM packet capture

path Parameters
exp_name
required
string

name of phenix experiment

vm_name
required
string

name of phenix VM to start capture on

Request Body schema: application/json
required

phenix VM packet capture parameters

interface
integer
filename
string

Responses

Request samples

Content type
application/json
{
  • "interface": 0,
  • "filename": "string"
}

stop phenix experiment VM packet captures

path Parameters
exp_name
required
string

name of phenix experiment

vm_name
required
string

name of phenix VM to stop captures on

Responses

get phenix experiment VM snapshots

path Parameters
exp_name
required
string

name of phenix experiment

vm_name
required
string

name of phenix VM to get snapshots for

Responses

Response samples

Content type
application/json
{
  • "snapshots": [
    ]
}

create phenix experiment VM snapshot

path Parameters
exp_name
required
string

name of phenix experiment

vm_name
required
string

name of phenix VM to snapshot

Request Body schema: application/json
required

phenix VM snapshot parameters

filename
string

Responses

Request samples

Content type
application/json
{
  • "filename": "string"
}

restore phenix experiment VM to snapshot

path Parameters
exp_name
required
string

name of phenix experiment

vm_name
required
string

name of phenix VM to restore

snapshot
required
string

name of snapshot to restore VM to

Responses

Get all running VMs

query Parameters
screenshot
string

whether or not to include VM screenshots (value is size to grab)

Responses

Response samples

Content type
application/json
{
  • "vms": [
    ]
}

Hosts

Cluster host details

Get all cluster hosts

Responses

Response samples

Content type
application/json
{
  • "hosts": [
    ]
}

Applications

Available phenix user applications

Get all available user applications

Responses

Response samples

Content type
application/json
{
  • "applications": [
    ]
}

Topologies

Available phenix topologies

Get all available topologies

Responses

Response samples

Content type
application/json
{
  • "topologies": [
    ]
}

Disks

Available phenix disk images

Get all available disk images

Responses

Response samples

Content type
application/json
{
  • "disks": [
    ]
}

Users

User details and controls

Get all users

Responses

Response samples

Content type
application/json
{
  • "users": [
    ]
}

Create a new user

Request Body schema: application/json
required

user details

username
string
password
string
first_name
string
last_name
string
role_name
string
resource_names
Array of strings

Responses

Request samples

Content type
application/json
{
  • "username": "string",
  • "password": "string",
  • "first_name": "string",
  • "last_name": "string",
  • "role_name": "string",
  • "resource_names": [
    ]
}

Response samples

Content type
application/json
{
  • "username": "string",
  • "first_name": "string",
  • "last_name": "string",
  • "role": {
    }
}

Get a specific user

path Parameters
username
required
string

username of user to get

Responses

Response samples

Content type
application/json
{
  • "username": "string",
  • "first_name": "string",
  • "last_name": "string",
  • "role": {
    }
}

Update existing user

path Parameters
username
required
string

username of user to modify

Request Body schema: application/json
required

user parameters

first_name
string
last_name
string
role_name
string
resource_names
Array of strings

Responses

Request samples

Content type
application/json
{
  • "first_name": "string",
  • "last_name": "string",
  • "role_name": "string",
  • "resource_names": [
    ]
}

Response samples

Content type
application/json
{
  • "username": "string",
  • "first_name": "string",
  • "last_name": "string",
  • "role": {
    }
}

Delete existing user

path Parameters
username
required
string

username of user to delete

Responses

Signup as a new user

Request Body schema: application/json
required

user details

username
string
password
string
first_name
string
last_name
string

Responses

Request samples

Content type
application/json
{
  • "username": "string",
  • "password": "string",
  • "first_name": "string",
  • "last_name": "string"
}

Response samples

Content type
application/json
{
  • "username": "string",
  • "first_name": "string",
  • "last_name": "string",
  • "role": "string",
  • "token": "string"
}

Login a user

query Parameters
user
string

login username

pass
string

login password

Responses

Response samples

Content type
application/json
{
  • "username": "string",
  • "first_name": "string",
  • "last_name": "string",
  • "role": "string",
  • "token": "string"
}

Login a user

Request Body schema: application/json
required

login credentials

user
string
pass
string

Responses

Request samples

Content type
application/json
{
  • "user": "string",
  • "pass": "string"
}

Response samples

Content type
application/json
{
  • "username": "string",
  • "first_name": "string",
  • "last_name": "string",
  • "role": "string",
  • "token": "string"
}

Logout a user

Responses

Workflow

Workflow config upserts and applies, and the server options clients read

Create or update a phenix config for a workflow branch

Creates the config if it does not exist and updates it otherwise. The server sets BRANCH_NAME to the branch before parsing the body, so ${BRANCH_NAME} placeholders expand to the branch name. The server stores every other ${NAME} placeholder as written. The Content-Type header must be exactly application/json or application/x-yaml. A Topology is also checked for a node an experiment could not use, such as a hostname used twice or a reserved hostname, before it is stored. With dryRun=true it runs the same checks, returns what it would do, and stores nothing. Needs configs create or update before the body is parsed, then configs create on a new config or update on a stored one, by the kind and name the body gives (such as Topology/lab), dry run or not.

path Parameters
branch
required
string

workflow branch name

query Parameters
dryRun
boolean
Default: false

Checks the config as a real request would (placeholder expansion, the create or update decision, permissions, schema validation and, for a Topology, the node checks an experiment would fail on) and returns the result without storing the config or running config hooks. For an Experiment config only the schema is checked; the experiment checks run when the config is stored. The parameter's name is matched exactly, so a request that spells it differently is carried out for real.

Request Body schema:
required

phenix config of a storable kind (e.g. Topology or Scenario)

apiVersion
required
string
kind
required
string
required
object
required
object

Responses

Request samples

Content type
{
  • "apiVersion": "string",
  • "kind": "string",
  • "metadata": {
    },
  • "spec": { }
}

Response samples

Content type
application/json
{
  • "action": "create",
  • "kind": "string",
  • "name": "string",
  • "dryRun": true,
  • "pending": "string"
}

Apply a phenix workflow config to a workflow branch

Validates the workflow config against the Workflow schema, finds the experiment mapped to the branch (phenix.workflow/branch annotation), plans an action, and checks the default bridge and the topology and scenario the action would use, including a stored topology's nodes, as creating an experiment would. Only then does it create, update, start, or restart the experiment. A failed check leaves a running experiment running. With dryRun=true the plan is returned after the same checks, and nothing is changed; a dry run before a first deploy names the configs the caller will store with pending. The server sets BRANCH_NAME to the branch before parsing the body, so ${BRANCH_NAME} placeholders expand to the branch name. The server keeps every other ${NAME} placeholder as written. The Content-Type header must be exactly application/json or application/x-yaml.

path Parameters
branch
required
string

workflow branch name

query Parameters
tag
Array of strings

key=value tag stored on the experiment, joined with commas into the phenix.workflow/tags annotation; repeat the parameter for more tags

dryRun
boolean
Default: false

Runs every check, a stored topology's node checks included, and returns the plan without creating, updating, starting, or stopping anything. The parameter's name is matched exactly, so a request that spells it differently is treated as a real apply, and refused with 400 when it also carries pending.

pending
Array of strings

A config the caller will create or update before the real apply, usually the pending value a dry run of POST /workflow/configs/{branch} returned: /, such as Topology/helloworld, optionally followed by "?" and the config's references, such as Scenario/helloworld?from=helloworld-base&topology=helloworld (url-encode the value). The kind may be in any case. Repeat the parameter for more configs. A pending topology or scenario is not looked up, decoded or merged, so a first deploy can be checked before its configs are stored; the references listed after "?" are checked instead, with the errors the real apply gives (on a create, a scenario's topology annotation; each fromScenario, which must be pending or stored and annotated for the topology; each included topology, which must be pending, stored or a file on the server). An include that is neither pending nor stored is looked up as a file on the server, as the real apply does, so the answer shows whether that path exists on the server; grant workflow:create only to roles trusted with that (the default policies give it to Global Admin only). Only allowed with dryRun=true; otherwise, or for a value that is not a config name, the request is a 400.

expect
string
Enum: "none" "create" "createAndStart" "update" "updateAndStart" "restart"

The action the caller expects, usually the action a previous dry run returned. If the server plans a different action, it returns 409 and changes nothing. It is checked on dry runs as well as real applies. A value that is not an action is a 400 with the message invalid expect value "" and the cause unknown workflow action "".

Request Body schema:
required

phenix workflow config

apiVersion
required
string (API Version)
Value: "phenix.sandia.gov/v0"

The config API version; a workflow config is phenix.sandia.gov/v0.

kind
required
string (Kind)
Value: "Workflow"

The config kind, which is always Workflow.

metadata
object or null (Metadata)

Not read by the server; it is accepted so a workflow config has the same four top-level keys as every other phenix config, and so a later version can carry a name or annotations without a breaking change.

required
object (Workflow Spec)

What an apply may do and the experiment settings it sets; an empty spec applies every default.

Responses

Request samples

Content type
{
  • "apiVersion": "phenix.sandia.gov/v0",
  • "kind": "Workflow",
  • "metadata": { },
  • "spec": {
    }
}

Response samples

Content type
application/json
{
  • "action": "none",
  • "experiment": "string",
  • "reason": "string",
  • "dryRun": true
}

Get server-side options

Server-side settings that clients read: every phenix CLI command fetches them over the unix socket when it starts, to inherit the server's bridge-mode, deploy-mode and use-gre-mesh, and the web UI's Experiments page reads them too. workflow-dry-run is true when POST /workflow/configs/{branch} and POST /workflow/apply/{branch} both support dryRun, and apply supports pending and expect. An older server ignores dryRun on /workflow/configs/{branch} and stores the config, so phenix workflow apply refuses servers without it.

Responses

Response samples

Content type
application/json
{
  • "bridge-mode": "string",
  • "deploy-mode": "string",
  • "use-gre-mesh": true,
  • "base-dir.injects": "string",
  • "workflow-dry-run": true
}

Builder

Builder drafts, snapshots, generation and publication. Every operation needs the one Builder permission: the verb use on the resource builder. A role that holds it may read, change and delete every draft, template, icon and layer set, whoever made them. No permission applies to one draft, template, icon or layer set. Some operations read or write phenix configs: publish, import, export, sources, packages, preflight checks and published documents. Each of these operations also needs the config permissions that its description names. The icon library belongs to the server. Each icon has a name that is unique, ignoring case. Any caller may rename or delete an uploaded icon. No caller may rename or delete an icon of the server template files. The template library belongs to the server. Built-in templates and the items of the server template files are read only. Every response of a Builder operation carries X-Content-Type-Options: nosniff and Cache-Control: no-store, whatever its status, 304 included. OPTIONS on the path of any Builder operation answers 204 with the Allow header of that path. It reads and changes nothing.

Get the JSON Schema of Builder documents

Requires builder use.

Responses

Response samples

Content type
application/json
{ }

Get the JSON Schema of Builder template files

Requires builder use, as the document schema does. A template file holds one collection of device templates, in YAML or JSON. The Node Templates tab exports and imports this file. At start, phenix reads the template files in its template directory (--base-dir.builder-templates) as read-only server collections.

Responses

Response samples

Content type
application/json
{ }

Get the JSON Schema of Builder layer set files

Requires builder use, as the document schema does. A layer set file holds one layer set, in YAML or JSON, with copies of the custom icons that it names. The Layers tab of the Drafts page downloads and uploads this file.

Responses

Response samples

Content type
application/json
{ }

Get the JSON Schema of Builder packages

Requires builder use, as the document schema does. A Builder package is one JSON or YAML file (POST /builder/package makes one). It holds a Builder document, and the list of what the diagram needs on a phenix server. It also holds the Scenario and Topology configs and custom icons that the document names, when the request that made the package selected them.

Responses

Response samples

Content type
application/json
{ }

List Builder drafts

Requires builder use. Returns every draft, the most recently changed first, each with the user who created it. Also lists separately, as damaged, the drafts whose metadata this server can no longer read (for example, drafts that a newer phenix wrote). A caller can delete a damaged draft, but cannot open it. No row has experiment. limits says how many drafts the server holds at most.

Responses

Response samples

Content type
application/json
{
  • "drafts": [
    ],
  • "damaged": [
    ],
  • "limits": {
    }
}

Create a Builder draft

Requires builder use. The caller is the creator of the draft. The draft holds the document as its first snapshot. The operation publishes nothing. With forkOf, the ID of a draft, that draft must exist. With a sourceToken that names a published document, the caller must hold configs get for the config that the document was published to. With a sourceToken that names the Builder file of a topology, the server reads the file as GET /builder/topologies/{topology}/document reads it, with the same permission. The answers are the same when the server cannot use the file. The server refuses the draft with 409 when the file no longer holds the document that the token names. It also refuses with 409 when the server no longer reads the topology from its file. The server stamps the metadata of the document before it stores it. createdBy and createdAt stay as they are when the document has them. Otherwise they are the caller and the current time. updatedBy and updatedAt are always the caller and the current time. The server replaces the values sent in these two fields. The server stores one document as it is: the document that a sourceToken of the builder-doc/ or builder-file/ form names, returned unchanged. Thus the draft holds exactly what the caller opened, with the same digest. A value that is not valid in one of the four fields refuses the request (422). The response has no document. Its stamp holds the four values of the stored document. A draft opened from a published document, or a draft that forks a draft, has experiment when that publication made an experiment. The experiment must still exist, and the caller must hold experiments get for it. The server writes the draft and its document in one transaction, so a refused request stores nothing.

Request Body schema: application/json
required
title
string
summary
string

summary of the first snapshot

sourceToken
string

where the draft comes from. One of:

  • <kind>/<name>: the config that the draft was imported from.
  • uploaded/<kind>/<name>: an uploaded config. Or uploaded/legacy-xml: an uploaded legacy Builder diagram that came without a Topology. These two name no stored config, so they do not let the draft update a stored Topology or Experiment.
  • builder-doc/<document id>: the published document that the draft was opened from. The caller must be able to read it (404 otherwise).
  • builder-file/<topology name>/<digest>: the Builder file of a topology that the draft was opened from, with the digest that GET /builder/topologies/{topology}/document returned. The caller must be able to read the file, and the file must still have that digest (409 otherwise)
sourceFile
string <= 255 characters

the name of the uploaded file that the document came from, kept only for display. It is a file name of at most 255 bytes without / or \, not . or .., with no control characters (422 otherwise). The server never opens anything by it.

forkOf
string

the ID of a draft that the new draft forks. The draft must exist (404 otherwise). The new draft takes its source token in place of sourceToken. It records the last publication of that draft as forked. Thus a publish of the new draft can update what that draft published or was opened from. It records no source file: not the file of that draft, and not a sourceFile sent with it.

required
object (Builder Document)

A Builder document: the diagram of a topology, with its nodes, networks and connections, and how the canvas shows them. Under metadata, it has what the document says about itself. This component lists every property of the document, and gives the outline of the nested properties. GET /schemas/builder/v1 serves the complete JSON Schema that the server checks every document against. Each property in it has a title, a description and examples. A document holds no other property. The server refuses a document with another property, such as a metadata field at the root. layout, iconSize, templates and icons are for presentation only. The server never writes them to a config.

Responses

Request samples

Content type
application/json
{
  • "title": "string",
  • "summary": "string",
  • "sourceToken": "string",
  • "sourceFile": "string",
  • "forkOf": "string",
  • "document": {
    }
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "createdBy": "string",
  • "title": "string",
  • "sourceToken": "string",
  • "sourceFile": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "updated": "2019-08-24T14:15:22Z",
  • "lastModifiedBy": "string",
  • "cursor": 0,
  • "snapshots": 0,
  • "snapshotId": "string",
  • "digest": "string",
  • "size": 0,
  • "historyBytes": 0,
  • "dirty": true,
  • "canUndo": true,
  • "canRedo": true,
  • "etag": "string",
  • "document": {
    },
  • "stamp": {
    },
  • "history": [
    ],
  • "publication": {
    },
  • "forked": {
    },
  • "experiment": "string"
}

Get a Builder draft with its current document

Requires builder use. experiment names an experiment that the draft published. For a draft opened from a published diagram, it can also name an experiment that the diagram published. It is present while that experiment exists and the caller holds experiments get for it.

path Parameters
draft
required
string^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$

draft ID

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "createdBy": "string",
  • "title": "string",
  • "sourceToken": "string",
  • "sourceFile": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "updated": "2019-08-24T14:15:22Z",
  • "lastModifiedBy": "string",
  • "cursor": 0,
  • "snapshots": 0,
  • "snapshotId": "string",
  • "digest": "string",
  • "size": 0,
  • "historyBytes": 0,
  • "dirty": true,
  • "canUndo": true,
  • "canRedo": true,
  • "etag": "string",
  • "document": {
    },
  • "stamp": {
    },
  • "history": [
    ],
  • "publication": {
    },
  • "forked": {
    },
  • "experiment": "string"
}

Delete a Builder draft

Requires builder use. Any caller may delete any draft, also a draft whose metadata this server can no longer read. The delete does not change published configs. A delete of a draft during its publication waits until the publication ends. Then it answers 412 with the draft's new ETag.

path Parameters
draft
required
string^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$

draft ID

header Parameters
If-Match
required
string

The ETag of the draft revision that the change is based on: exactly one strong, quoted entity tag, such as "3". A missing header, a wildcard or a weak tag gets 400. A tag that names any other revision gets 412.

Responses

Response samples

Content type
application/json
{
  • "message": "string",
  • "cause": "string",
  • "metadata": {
    },
  • "code": "publish.blocked",
  • "issues": [
    ]
}

List the snapshots of a Builder draft

Requires builder use. The list starts with the oldest snapshot. cursor is the index of the current snapshot.

path Parameters
draft
required
string^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$

draft ID

Responses

Response samples

Content type
application/json
{
  • "snapshots": [
    ],
  • "cursor": 0
}

Save a Builder draft

Requires builder use. Appends the document as a new snapshot, discards all snapshots after the cursor (the redo branch), and moves the cursor to the new snapshot. A draft keeps at most 50 snapshots, of at most 50 MiB in total. The server removes the oldest snapshots to make room for the new snapshot. The server stamps the metadata of the document before it stores it. createdBy and createdAt are the values from the draft create. updatedBy and updatedAt are the caller and the current time. The server replaces the values sent in the four fields. A value that is not valid refuses the request (422). The response has no document. Its stamp holds the four values written.

path Parameters
draft
required
string^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$

draft ID

header Parameters
If-Match
required
string

The ETag of the draft revision that the change is based on: exactly one strong, quoted entity tag, such as "3". A missing header, a wildcard or a weak tag gets 400. A tag that names any other revision gets 412.

Request Body schema: application/json
required
summary
string
required
object (Builder Document)

A Builder document: the diagram of a topology, with its nodes, networks and connections, and how the canvas shows them. Under metadata, it has what the document says about itself. This component lists every property of the document, and gives the outline of the nested properties. GET /schemas/builder/v1 serves the complete JSON Schema that the server checks every document against. Each property in it has a title, a description and examples. A document holds no other property. The server refuses a document with another property, such as a metadata field at the root. layout, iconSize, templates and icons are for presentation only. The server never writes them to a config.

opId
string^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$

the client's id for this save, kept with the snapshot, so a client that never saw the response can tell that the server stored it

Responses

Request samples

Content type
application/json
{
  • "summary": "string",
  • "document": {
    },
  • "opId": "string"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "createdBy": "string",
  • "title": "string",
  • "sourceToken": "string",
  • "sourceFile": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "updated": "2019-08-24T14:15:22Z",
  • "lastModifiedBy": "string",
  • "cursor": 0,
  • "snapshots": 0,
  • "snapshotId": "string",
  • "digest": "string",
  • "size": 0,
  • "historyBytes": 0,
  • "dirty": true,
  • "canUndo": true,
  • "canRedo": true,
  • "etag": "string",
  • "document": {
    },
  • "stamp": {
    },
  • "history": [
    ],
  • "publication": {
    },
  • "forked": {
    },
  • "experiment": "string"
}

Get one snapshot of a Builder draft with its document

Requires builder use.

path Parameters
draft
required
string^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$

draft ID

snapshot
required
string

snapshot ID, or current for the snapshot that the cursor identifies

Responses

Response samples

Content type
application/json
{
  • "snapshot": {
    },
  • "document": {
    }
}

Delete one snapshot of a Builder draft

Requires builder use. Removes the snapshot from the history and deletes its content. A caller cannot delete the snapshot that the cursor identifies (the current version). The cursor stays on it. When the last publication names the deleted snapshot, the publication record stays, and the draft is then dirty.

path Parameters
draft
required
string^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$

draft ID

snapshot
required
string

snapshot ID, or current for the snapshot that the cursor identifies

header Parameters
If-Match
required
string

The ETag of the draft revision that the change is based on: exactly one strong, quoted entity tag, such as "3". A missing header, a wildcard or a weak tag gets 400. A tag that names any other revision gets 412.

Responses

Response samples

Content type
application/json
{
  • "id": "string",
  • "createdBy": "string",
  • "title": "string",
  • "sourceToken": "string",
  • "sourceFile": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "updated": "2019-08-24T14:15:22Z",
  • "lastModifiedBy": "string",
  • "cursor": 0,
  • "snapshots": 0,
  • "snapshotId": "string",
  • "digest": "string",
  • "size": 0,
  • "historyBytes": 0,
  • "dirty": true,
  • "canUndo": true,
  • "canRedo": true,
  • "etag": "string",
  • "document": {
    },
  • "stamp": {
    },
  • "history": [
    ],
  • "publication": {
    },
  • "forked": {
    },
  • "experiment": "string"
}

Move the cursor of a Builder draft (undo and redo)

Requires builder use. The move discards no snapshot.

path Parameters
draft
required
string^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$

draft ID

header Parameters
If-Match
required
string

The ETag of the draft revision that the change is based on: exactly one strong, quoted entity tag, such as "3". A missing header, a wildcard or a weak tag gets 400. A tag that names any other revision gets 412.

Request Body schema: application/json
required
index
integer >= 0

index of the snapshot to move to, oldest first

snapshotId
string

Responses

Request samples

Content type
application/json
{
  • "index": 0,
  • "snapshotId": "string"
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "createdBy": "string",
  • "title": "string",
  • "sourceToken": "string",
  • "sourceFile": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "updated": "2019-08-24T14:15:22Z",
  • "lastModifiedBy": "string",
  • "cursor": 0,
  • "snapshots": 0,
  • "snapshotId": "string",
  • "digest": "string",
  • "size": 0,
  • "historyBytes": 0,
  • "dirty": true,
  • "canUndo": true,
  • "canRedo": true,
  • "etag": "string",
  • "document": {
    },
  • "stamp": {
    },
  • "history": [
    ],
  • "publication": {
    },
  • "forked": {
    },
  • "experiment": "string"
}

Publish a Builder draft to phenix configs

The only Builder operation that creates or updates configs. (DELETE /builder/documents/{document} deletes a published topology.) It publishes the current snapshot of the draft. The request carries only the intent. Requires builder use. The caller must also have its own configs create or update on each target config, as the action of the target requires. An experiment target also requires experiments create or update. A draft imported from a stored Topology or Experiment also needs configs get on it, and topologies get (or experiments get) on its name. The server uses them to check that the source did not change since the import. In both modes, a draft whose document lists scenarios has a scenario stage before the experiment stage. Each listed Scenario config must exist and be readable (configs get and scenarios list). Otherwise the answer is 422 and names the scenario. The stage adds the topology to the topology annotation of each scenario that does not name it yet. This needs configs update on that scenario (otherwise 403). The stage does not write a scenario that already names the topology. The stage message tells which scenarios it changed. A publish never creates or replaces the spec of a scenario. A repeat of a publication that completed, with the same If-Match, gets 200 with every stage skipped. A draft updates an existing topology or experiment only in two cases. In the first case, the draft was imported from it. In the second case, the draft published it (or was opened from the published diagram that did), and nothing else changed it since then. The server refuses all other updates with 409. Only the draft imported from a topology updates a topology that has a legacy Builder diagram (builder-xml). A draft imported from an experiment built from that topology does not. Also, the diagram must be the one that the import read. The server refuses with 409 a diagram that someone changed, added or removed since, as for a changed spec. The update removes builder-xml, writes builder-doc, and adds a warning to the result. The warning says that the update replaced the diagram or, if the import could not read it, removed it. The server reads some topologies from the Builder file that their builder-doc annotation names. Only a draft opened from that file updates such a topology. The file must still hold what the draft was opened from, and the topology must still be what the file publishes. Such a draft updates the topology in no other way. It does not update it as a draft imported from the topology, even when the document of the file was imported from the topology. A publish never writes the file. The topology keeps its path, and the result has a warning that the file is now behind. A published experiment records in its builder-experiment annotation which draft and published document published it. After the configure stage of its apps ran, it also records its digest there. An experiment update runs that stage, as an update through /configs does. When a stage fails after the server wrote earlier stages, the response is 409 or 500, with a result whose status is partial. Unless the draft changed meanwhile, the warnings of that result then have publish.retry.available. The same request, with the same If-Match, then finishes the publication. The stages that are already done answer skipped. When the server stored the published document but could not remove the content that it replaces, the publication continues. The answer then has a Warning header and a warning in the result. With "dryRun": true, the request is a dry run. A dry run needs the same permissions, and makes every check of the publication on the current snapshot of the draft. It writes nothing (no published document, config, scenario annotation, experiment or draft record), and needs no If-Match. It answers 200 with a BuilderPublishPreview. The preview holds what the publication would change and the warnings it would give. Its errors hold the refusal that a publication would answer with 400, 409 or 422. A 403, a 404, a body that is not a publish request (400) and a server failure keep their status. The dry run takes no lock. Thus what it reports may change before the caller sends the publication. The Publish dialog shows it as What publishing changes.

path Parameters
draft
required
string^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$

draft ID

header Parameters
If-Match
string

The ETag of the draft revision that the publication is based on, as for every Builder mutation (BuilderIfMatch). Every request needs it, except a dry run, which writes nothing and ignores it. A missing or malformed ETag gets 400 before the server decodes the body, unless the body asks for a dry run.

Request Body schema: application/json
required
mode
required
string
Enum: "topology" "topology-experiment"
required
object (BuilderPublishTarget)
object (BuilderPublishScenario)

the scenario that a topology-experiment publication creates or updates the experiment with: one of the scenarios that the draft's document lists, by name

object (BuilderPublishTarget)
dryRun
boolean
Default: false

make every check of the publication, write nothing, and answer with what it would change (BuilderPublishPreview). A dry run needs no If-Match.

Responses

Request samples

Content type
application/json
{
  • "mode": "topology",
  • "topology": {
    },
  • "scenario": {
    },
  • "experiment": {
    },
  • "dryRun": false
}

Response samples

Content type
application/json
Example
{
  • "status": "succeeded",
  • "stages": [
    ],
  • "warnings": [
    ],
  • "errors": [
    ],
  • "topology": {
    },
  • "scenario": {
    },
  • "experiment": {
    },
  • "removedHostPins": [
    ],
  • "draft": {
    }
}

Run preflight checks on a Builder draft

Runs the checks that the request names on the current document of the draft, in the request order and all at the same time. Reports each check as passed, failed or unavailable, with a summary and its issues.

  • capacity compares the CPUs and memory of the devices that phenix starts with the free CPUs and memory of the schedulable cluster hosts. These devices are all devices except external devices. A device uses hardware.vcpus and hardware.memory, or 1 and 512 MB when the device does not set them. The check also makes sure that each device fits on one host. The vCPUs and memory of the device must both fit within the CPUs and memory of that host.
  • network compares the VLANs that the devices use, and the VLAN aliases of the networks, with the VLAN range of the named experiment. No range applies without an experiment, or when the experiment sets no range. The check compares the aliases with the VLANs that running experiments hold. It compares the bridges that the interfaces name with the Open vSwitch bridges of the schedulable hosts. It also compares the default bridge of the experiment, or phenix when there is no default bridge. It lists these bridges with ovs-vsctl list-br through the minimega shell command, which changes nothing.
  • disks finds each drive image by file name among the disk images of the server. It checks the image kind: a VM or ISO image for a kvm device, and a container image for a container.
  • apps reads each Scenario config that the document lists. It finds each app that the scenario does not disable among the default, built-in and user apps. A listed scenario that does not exist is the error preflight.app.scenario-missing. A check fails when one of its issues is an error. A check is unavailable when nothing failed, but the server could not make the check, or a part of it. The causes are:
  • The role of the caller does not have hosts list (capacity and bridges), disks list, applications list, or experiments list (VLANs in use).
  • The role does not have read access to the experiment (configs get and experiments get) or to a scenario (configs get and scenarios list).
  • The server cannot reach minimega.
  • The server lists no disk images, or does not list them within 10 seconds.
  • The check took more than 20 seconds. An issue tells why (code preflight.unavailable, or preflight.app.scenario-unreadable as a warning for a scenario). One check never stops the other checks. Requires builder use and configs get. The route writes nothing, and starts no VM or experiment.
path Parameters
draft
required
string^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$

draft ID

Request Body schema: application/json
required
checks
required
Array of strings (BuilderPreflightCheckName) non-empty
Items Enum: "capacity" "network" "disks" "apps"

the checks to make, in the order of the report. Each at most once

experiment
string

the experiment whose VLAN range and default bridge the network check uses. Empty or not present for none

Responses

Request samples

Content type
application/json
{
  • "checks": [
    ],
  • "experiment": "lab-exp"
}

Response samples

Content type
application/json
{
  • "checks": [
    ],
  • "passed": [
    ],
  • "failed": [
    ],
  • "unavailable": [
    ]
}

List the configs Builder can use as sources

Requires builder use and configs list. POST /builder/generate can import topologies and experiments. Scenarios and images are for selection only. The server filters each config by configs list for its name. For topologies, experiments and scenarios, it also filters by the list permission of that resource. A topology also reports how many topologies it includes (includeCount), to a caller who holds configs get for its name.

Responses

Response samples

Content type
application/json
{
  • "topologies": [
    ],
  • "experiments": [
    ],
  • "scenarios": [
    ],
  • "images": [
    ]
}

Import a Builder document from a Topology or Experiment config

Converts a stored config (source) or an uploaded config (content) into a document and returns it. The operation writes nothing. Requires builder use and configs get. A stored source also needs configs get for its name, and the topologies or experiments list permission for it. Uploaded content needs configs create, the permission of POST /configs, which also takes a config file. Unlike POST /configs, the server keeps each ${NAME} and ${NAME:default} placeholder in the content as written. It never reads its environment for them. The server converts a Topology that has the builder-xml annotation and no builder-doc from its legacy Builder diagram, as POST /builder/legacy converts one. Its source then has builder builder-xml. The server reads the topologies that a Topology includes (includeTopologies) from the config store with the permissions of the caller, never from a file. With includes keep (the default), their nodes are in the document, marked includedFrom and read only. The document lists the includes that the server could not read in its source.unresolvedIncludes. With includes combine, their nodes are nodes of the document. Only the includes that the server could not read stay in its source.includeTopologies. copy asks for the same document as a plain import, not linked to the topology. A combined document and a copy name no config. Their source.kind is manual, and the document name is the name of the new topology. A draft made from such a document publishes a new topology, and never updates the topology it was imported from. Their metadata.notes end with the note Copied from <name>, where <name> is the name in the metadata of the source config. The new name is name, or else the source name with -combined or -copy added. The server does not search for a name that no topology has. The source of the response is still the config that the server read. The device nodes keep the order of the config's nodes, then the nodes of each included topology in the order phenix merges them. A publish writes the nodes in that order. From an Experiment, each node spec loses what phenix added to it when it created the experiment. The spec loses bridge_set_in_topo, and a bridge that phenix set to the default bridge of the experiment. It loses each field that phenix reads as unset: empty or null, and 0 or false in a field that cannot be null. A nullable field such as snapshot keeps an explicit 0 or false. The spec also loses each value equal to the default that phenix gives the field, such as vm_type kvm or memory 512. os_type, and the fields the topology schema requires, stay. The specs then read like the nodes of a topology. The scenario of an Experiment is its scenario annotation. It becomes the scenarios of the document when this server stores a Scenario config of that name, and the caller may list it. To list it, the caller needs configs list and scenarios list for it. Otherwise, the document lists no scenario, and a warning says so. The scenario that an Experiment holds never goes into the document. For uploaded content, a listed scenario also adds a warning. The warning says that the scenario is the Scenario config of that name on this server, not the copy in the file. Errors:

  • 400 when includes has a different value, or when the request gives name without copy or includes combine.
  • 422 when the request asks for copy or includes combine of an Experiment. The same status applies when the new name is not a config name of 1 to 512 bytes (import.name.invalid). It also applies when the new name is the name of the stored topology of the import (import.name.source).
  • 500 when the server cannot read the config store, for example for the Scenario config that an Experiment names.
Request Body schema: application/json
required
source
string

a stored Topology or Experiment config, as <Kind>/<name>

content
string

a Topology or Experiment config as JSON or YAML text

includes
string
Enum: "keep" "combine"

what happens to the nodes of the topologies that a Topology includes. keep (the default, also when not present or empty) shows them read only. combine copies them into the document and makes it a new topology. The server refuses combine for an Experiment.

copy
boolean
Default: false

make the document a copy that is not linked to the Topology that it is generated from. includes combine implies it. The copy gets the diagram note Copied from <name> in metadata.notes, where <name> is the name in the metadata of the source config. The server refuses it for an Experiment.

name
string <= 512 characters ^[A-Za-z0-9_@.-]*$

the name of the new topology, and of the document. The server accepts it only with copy or includes combine. When empty, the source's name with -combined (for combine) or -copy added. It must not be the name of the stored Topology that the request imports.

Responses

Request samples

Content type
application/json
{
  • "source": "string",
  • "content": "string",
  • "includes": "keep",
  • "copy": false,
  • "name": "string"
}

Response samples

Content type
application/json
{
  • "document": {
    },
  • "warnings": [
    ],
  • "source": {
    }
}

Convert a legacy Builder diagram into a Builder document

Converts a diagram of the legacy Builder (the editor that phenix had before the Builder) and returns the document. The operation writes nothing. The server reads from the store only the topologies that a topology includes. content is the text of a file. The file is the mxGraph XML of the diagram, whose root element is mxGraphModel or root. Or the file is a Topology config, in YAML or JSON, that has the builder-xml annotation. The server reads no encoded or compressed form of the XML. For a diagram alone, the node settings in the diagram are the nodes. Its $NAME placeholders get values from its own variables and the legacy defaults. The source of the document is manual, so a draft made from it publishes a new topology. For a Topology, its spec defines every node, and the diagram only places the nodes, matched by hostname. The response has its source, with stored false. Requires builder use, configs get and configs create, because the content can be a config file, as for POST /configs. The server keeps each ${NAME} placeholder in it as written. content holds at most 5242880 bytes. Its XML nests at most 32 elements deep and holds at most 10000 cells. The server refuses a DOCTYPE or any other declaration. A refusal repeats nothing of the content but the name and kind of a config, or the name of the root element of the XML.

Request Body schema: application/json
required
content
required
string

the text of a legacy Builder diagram file: mxGraph XML, or a Topology config as YAML or JSON that has the builder-xml annotation. At most 5242880 bytes

name
string

the name of the document of a diagram that comes without a Topology (legacy-diagram when not present or blank). At most 512 bytes, without control characters. The server ignores it for a Topology, which uses its own name.

Responses

Request samples

Content type
application/json
{
  • "content": "string",
  • "name": "string"
}

Response samples

Content type
application/json
{
  • "document": {
    },
  • "warnings": [
    ],
  • "source": {
    }
}

Export a Builder document as the Topology config Publish writes

Projects the document onto the phenix Topology config that a publish of it would write, and returns that config as YAML. The operation reads nothing and writes nothing. Requires builder use and configs get. The server checks the document as a draft save checks it, within the same size limits. The config has no builder-doc annotation. It names the included topologies of the document in includeTopologies, and does not merge them. When the phenix config validation refuses the document, the answer is 422, as for a publish. A publish names these reasons in this order, before any other reason. First, it names interfaces without a VLAN, then addresses that interfaces share. Then it names hostnames that phenix refuses, then device settings that make the experiment fail to start. An export names interfaces without a VLAN only when a vlan is missing or null. It names hostnames only when one is a single character, which the validation also refuses. Otherwise it gives the reason of the validation. publishBlockers reports what only a publish refuses. Examples are an interface with a blank VLAN, and interfaces that share an IP or MAC address. Another example is a hostname that phenix refuses only when it creates an experiment (all, all digits, or phenix on a Windows node). A device setting that makes the experiment fail to start is also an example. One such setting is an ntp-server label that names no interface with an address.

Request Body schema: application/json
required
required
object (Builder Document)

A Builder document: the diagram of a topology, with its nodes, networks and connections, and how the canvas shows them. Under metadata, it has what the document says about itself. This component lists every property of the document, and gives the outline of the nested properties. GET /schemas/builder/v1 serves the complete JSON Schema that the server checks every document against. Each property in it has a title, a description and examples. A document holds no other property. The server refuses a document with another property, such as a metadata field at the root. layout, iconSize, templates and icons are for presentation only. The server never writes them to a config.

name
string

the name of the topology. When empty, the server uses the document name, as the Publish dialog proposes it. The name then has - in place of each run of characters that a config name may not hold. If that leaves no characters, the name is topology

Responses

Request samples

Content type
application/json
{
  • "document": {
    },
  • "name": "string"
}

Response samples

Content type
application/json
{
  • "name": "string",
  • "yaml": "string",
  • "warnings": [
    ],
  • "publishBlockers": [
    ]
}

Make a Builder package of a document

Returns the package of the document in the request, with the edits not saved yet. The package holds the document, the sections that include names, and the requirements. The requirements list the items that follow, whatever the package carries. They list the scenarios of the document, its included topologies, its templates and its custom icons. They also list the apps of the scenarios that the server could read. They also list the files that the devices of the document and the packaged configs name (injection sources, app asset directories). Requires builder use and configs get. The server reads from the config store each Scenario config that the document names, and, with topologies, each included topology. It reads them with the permissions of the caller (configs get on it, and scenarios or topologies list). The requirements name a config that does not exist, or that the caller may not read, but the package does not carry it. A warning says so, in the same words for both cases. The server never reads an include that is a file path. The icons section gives the document a copy of each custom icon that it names, from the icon library. Configs go in the package without their times and Builder annotations (builder-*). The package never holds the content of a file, a script or an app. The operation writes nothing. POST /builder/package/resolve always accepts the package in the answer. The server omits from the requirements an entry that the package format refuses. A warning names that entry. Such an entry is blank or longer than 4096 bytes. Or it holds control characters (such as a newline in an injection source), or it comes after the first 1000 entries of its list. Each warning is an issue with its code (package.config.unreadable, package.include.file-path, package.icon.missing, package.icons.too-many, package.requirement.left-out, package.requirements.truncated). Anything else that would refuse the package, such as a stored config without a spec, gets 422 with the code package.invalid and the issues. A package larger than 5242880 bytes gets 413 with the code package.too-large.

Request Body schema: application/json
required
required
object (Builder Document)

A Builder document: the diagram of a topology, with its nodes, networks and connections, and how the canvas shows them. Under metadata, it has what the document says about itself. This component lists every property of the document, and gives the outline of the nested properties. GET /schemas/builder/v1 serves the complete JSON Schema that the server checks every document against. Each property in it has a title, a description and examples. A document holds no other property. The server refuses a document with another property, such as a metadata field at the root. layout, iconSize, templates and icons are for presentation only. The server never writes them to a config.

include
Array of strings
Items Enum: "scenarios" "topologies" "icons" "images"

the sections that the package carries, each at most once. scenarios holds the Scenario configs that the document names. topologies holds the topologies that it includes. icons holds a copy of each custom icon that it names. images lists in the requirements the disk images that the devices use, with the hosts that use each image

Responses

Request samples

Content type
application/json
{
  • "document": {
    },
  • "include": [
    ]
}

Response samples

Content type
application/json
{
  • "package": { },
  • "warnings": [
    ]
}

Check what a Builder package's diagram needs on this server

Reports, for each entry of the requirements of the package, whether this server has it. Requires builder use and configs get. The package is the request body, at most 5242880 bytes. A larger body gets 413 with the code package.too-large. The server decodes the package strictly (it refuses unknown fields) and checks it as the package schema describes. Otherwise the answer is 422 with the code package.invalid. For a package that does not validate, issues has each problem. The server also refuses a carried config with a Builder annotation (builder-*).

  • A Scenario or Topology config is present when the server has one of that name with the spec of the package. It is also present when the package carries no spec. It is different when its spec is not the same, and missing when there is none. It is unknown when the caller may not read it (configs get on it, and scenarios or topologies list). Thus the answer does not disclose whether it exists.
  • The server compares a custom icon by its bytes the same way, under configs list.
  • The server searches for disk images among the images that GET /disks lists the caller (disks list, then by name). Thus an image that the caller may not see is missing, as an absent image is. A drive matches by the name or full path of the image, else by its file name. The detail then tells this (Matched by file name pkg.qc2. This server's image is /phenix/images/pkg.qc2.).
  • Apps need applications list, also for the name.
  • Without disks list or applications list, or when the server cannot list the disk images, they are unknown.
  • Templates travel in the document, so they are present.
  • The server never checks files, so they are unknown. The operation writes nothing. The Builder creates a missing config that the user selects through POST /configs.
Request Body schema: application/json
required
property name*
additional property
any

Responses

Request samples

Content type
application/json
{ }

Response samples

Content type
application/json
{
  • "dependencies": [
    ]
}

Clean up Builder storage

Requires builder use, as deleting any draft does. Deletes every draft that is published and unchanged. For such a draft, its current snapshot is the one it last published, and no newer snapshot follows it. Also, the topology it published to still references the document it published. A draft stays when its topology no longer exists, or references another document. Each delete names the revision that the cleanup read, so a draft changed in the meantime stays. The published configs and documents stay. A cleanup waits for a publication in progress, so it never deletes a draft while a publication of that draft is in progress. Then it removes the orphaned storage that the server also removes when it starts and every hour after that. Orphaned storage is published documents that no topology references, and stored content that no draft or document names. It keeps what the server stored within the last hour, because a save or a publication may still be about to reference it. With dryRun=true it removes nothing, and answers with what it would remove. The request has no body. A draft or a record that the server could not remove, or could not read, does not fail the request. The Warning header then says that removing some of it failed.

query Parameters
dryRun
boolean

true counts what the cleanup would remove and removes nothing. The server refuses a value that is not a boolean.

Responses

Response samples

Content type
application/json
{
  • "dryRun": true,
  • "drafts": [
    ],
  • "documents": 0,
  • "content": 0
}

List published Builder documents

Requires builder use and configs list. Lists the documents that configs reference now in their builder-doc annotation, filtered by configs list for the config that each document was published to. The list shows a topology whose annotation names a Builder file (path), and no current stored document, with source file and the path only. The listing reads no file, so it lists such a row whether or not the server can use the file. A row with source store has experiment when the publication of the document made an experiment, and the caller holds experiments get for it. That experiment must still exist, and its topology must be the topology of the row.

Responses

Response samples

Content type
application/json
{
  • "documents": [
    ]
}

Get a published Builder document

Requires builder use, and configs get for the config that the document was published to. A document that the caller may not read, or that no config references any more, gets 404.

path Parameters
document
required
string

published document ID

Responses

Response samples

Content type
application/json
{
  • "source": "store",
  • "id": "string",
  • "digest": "string",
  • "size": 0,
  • "target": "string",
  • "kind": "string",
  • "config": "string",
  • "path": "string",
  • "draftId": "string",
  • "snapshotId": "string",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "createdBy": "string",
  • "etag": "string",
  • "topologyDiffers": true,
  • "experiment": "string",
  • "document": {
    }
}

Delete a published Builder topology

Deletes the Topology config that the document is current for, as DELETE /configs/Topology/{name} does. Then deletes every published document of that topology. Drafts and experiments made from it do not change. Requires builder use, and configs delete for the topology. A document that the caller may not get, or that is no longer current, gets 404. A document is no longer current when the topology changed to reference another document, was published again, or was deleted. A published experiment gets 422. To delete an experiment, use the Experiments page. If-Match must name the etag of the document as the caller read it. A topology that changed since then, in any way, gets 412 with the current tag. The list does not show a document whose stored metadata this server cannot read (for example one a newer phēnix wrote). The server logs its ID. Deleting it removes only that record and its content, and changes no config. When the record still names its config, the caller needs configs get and delete for it. Otherwise the caller needs them for every config (*/*). If-Match must name the tag of the stored record, which a 412 gives in its ETag header.

path Parameters
document
required
string

published document ID

header Parameters
If-Match
required
string

The etag of the published document, as listed or read: exactly one strong, quoted entity tag. A missing header, a wildcard or a weak tag gets 400. A tag of another state of the topology gets 412.

Responses

Response samples

Content type
application/json
{
  • "message": "string",
  • "cause": "string",
  • "metadata": {
    },
  • "code": "publish.blocked",
  • "issues": [
    ]
}

Get the Builder document a topology references

Returns the document that the builder-doc annotation of the topology names, wherever the server keeps it. The stored published document has priority: the document that the id or digest of the annotation names for this topology. Without one, the server reads the Builder file at the path of the annotation, on every request. The file must:

  • be below the phenix base directory (--base-dir.phenix), and outside the directory that holds the mounted VM file systems
  • be a regular file of at most 5 MiB
  • be reached through no symbolic link that leaves the base directory or has an absolute target
  • hold a valid Builder document as JSON or YAML A digest beside path pins the file. The server refuses a file whose document has another digest. Requires builder use, and configs get for the topology, which says nothing about the file. A caller who may create or update any one topology can name in it any Builder file below the base directory. That caller can then read the file here. Three cases get the same 404. They are a topology that the caller may not get, a topology that does not exist, and a topology that references no document. When the server cannot use a file, the answer is a fixed sentence that names the path, never anything that the file holds.
path Parameters
topology
required
string

topology name

Responses

Response samples

Content type
application/json
{
  • "source": "store",
  • "id": "string",
  • "digest": "string",
  • "size": 0,
  • "target": "string",
  • "kind": "string",
  • "config": "string",
  • "path": "string",
  • "draftId": "string",
  • "snapshotId": "string",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "createdBy": "string",
  • "etag": "string",
  • "topologyDiffers": true,
  • "experiment": "string",
  • "document": {
    }
}

List the icons of the Builder icon library

Requires builder use. Returns every icon of the icon library of the server, sorted by name, ignoring case, without its image. Each icon has the ID of its image, its uploader, its aliases, its revision and its entity tag. The aliases are the earlier names from its renames, which still name it. Each icon also tells whether a caller may rename or delete it. A caller may not rename or delete an icon of the server template files. GET /builder/icons/{icon} gives the image of one icon. The ID is the hash of the image, so a client needs the image of an ID once. The response also tells the most icons that the library holds, and the entity tag of the list. A request whose If-None-Match names that tag (weak comparison) gets 304, with no body, while the list is the same. The server sends an image only as base64 inside JSON, never as an image. Every response of the icon operations also carries Content-Security-Policy: default-src 'none'; frame-ancestors 'none'.

header Parameters
If-None-Match
string

the entity tag of the list as last read

Responses

Response samples

Content type
application/json
{
  • "icons": [
    ],
  • "maxIcons": 0,
  • "etag": "string"
}

Add an icon to the Builder icon library

Requires builder use. Adds a PNG under a name that the caller selects. The name has 1 to 64 letters, digits, _, @, . and -. It is not . or .., and no icon or alias has it, ignoring case. Takes a PNG of at most 96 by 96 pixels and 65536 bytes, as base64. Only the bytes tell what the image is. The server reads no file name, extension or declared type, and refuses all images that are not PNG (SVG, JPEG, GIF, WebP). The server stores a PNG as it is when all these conditions are true. The PNG holds only the chunks IHDR, PLTE, tRNS, IDAT and IEND. It has a PLTE or tRNS only where its color type uses one. It has nothing after its pixels, and it is at most 40960 bytes. The server encodes all other PNGs again. This keeps the pixels and removes all else (text, metadata, color profiles, more frames, an unused palette, data after the pixels). Thus use the data that the response returns. A name that already names an icon with the same bytes gets 200 with that icon. A name of another icon, or an alias of another icon, gets 409. The library holds at most 2000 icons, of all users together.

Request Body schema: application/json
required
name
required
string^[A-Za-z0-9_@.-]{1,64}$

the icon's name: 1 to 64 letters, digits, _, @, . and -, not . or ... No icon and no alias has it, ignoring case. Nodes and templates name the icon by it.

data
required
string

a PNG of at most 96 by 96 pixels and 65536 bytes, in standard base64 with padding and without line breaks

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "data": "string"
}

Response samples

Content type
application/json
{
  • "name": "string",
  • "id": "string",
  • "owner": "string",
  • "width": 0,
  • "height": 0,
  • "bytes": 0,
  • "created": "2019-08-24T14:15:22Z",
  • "updated": "2019-08-24T14:15:22Z",
  • "createdBy": "string",
  • "updatedBy": "string",
  • "aliases": [
    ],
  • "canRename": true,
  • "canDelete": true,
  • "revision": 0,
  • "etag": "string",
  • "data": "string"
}

Read an icon of the Builder icon library

Requires builder use. Returns the icon that the path names, with its image. name is the current name of the icon. A request whose If-None-Match names the icon's etag gets 304, with no body.

path Parameters
icon
required
string

the name of the icon, or one of its aliases, in any case. A path that names no icon gets 404, whatever its form.

header Parameters
If-None-Match
string

the entity tag of the icon as last read

Responses

Response samples

Content type
application/json
{
  • "name": "string",
  • "id": "string",
  • "owner": "string",
  • "width": 0,
  • "height": 0,
  • "bytes": 0,
  • "created": "2019-08-24T14:15:22Z",
  • "updated": "2019-08-24T14:15:22Z",
  • "createdBy": "string",
  • "updatedBy": "string",
  • "aliases": [
    ],
  • "canRename": true,
  • "canDelete": true,
  • "revision": 0,
  • "etag": "string",
  • "data": "string"
}

Rename an icon of the Builder icon library

Requires builder use. An icon of the server template files gets 403. Gives the icon that the path names a new name. No other icon, and no alias of another icon, may have that name, ignoring case. The old name becomes an alias, so diagrams and templates that name it continue to show the icon. A change of case renames the icon in place. A rename to one of its aliases makes that alias its name again. An icon keeps at most 16 old names. A rename that would give it more gets 422, and the icon keeps all its old names.

path Parameters
icon
required
string

the name of the icon, or one of its aliases, in any case. A path that names no icon gets 404, whatever its form.

Request Body schema: application/json
required
name
required
string^[A-Za-z0-9_@.-]{1,64}$

the new name of the icon, by the rules for the name of a new icon. The old name becomes an alias

Responses

Request samples

Content type
application/json
{
  • "name": "string"
}

Response samples

Content type
application/json
{
  • "name": "string",
  • "id": "string",
  • "owner": "string",
  • "width": 0,
  • "height": 0,
  • "bytes": 0,
  • "created": "2019-08-24T14:15:22Z",
  • "updated": "2019-08-24T14:15:22Z",
  • "createdBy": "string",
  • "updatedBy": "string",
  • "aliases": [
    ],
  • "canRename": true,
  • "canDelete": true,
  • "revision": 0,
  • "etag": "string",
  • "data": "string"
}

Delete an icon from the Builder icon library

Requires builder use. An icon of the server template files gets 403. Deletes the icon that the path names, by its name or an alias, with all its aliases. Diagrams and templates that name it show their built-in icon. A downloaded document keeps its own copy. The server also removes a record of that name that it cannot read. When the server could not remove an alias, the answer is still 204, with a Warning: 199 header. If-Match must name the etag of the icon. A rename gives the icon a new tag, so a delete with the tag from before the rename gets 412 with the current tag. A record that the server cannot read has the tag of its record revision, which a 412 gives.

path Parameters
icon
required
string

the name of the icon, or one of its aliases, in any case. A path that names no icon gets 404, whatever its form.

header Parameters
If-Match
required
string

The etag of the icon, as listed or read: exactly one strong, quoted entity tag, such as "12". A missing header, a wildcard or a weak tag gets 400. A tag of another revision gets 412.

Responses

Response samples

Content type
application/json
{
  • "message": "string",
  • "cause": "string",
  • "metadata": {
    },
  • "code": "publish.blocked",
  • "issues": [
    ]
}

List the device templates

Requires builder use. Returns the template library of the server, the built-in templates and the collections of the template files of the server. Every caller gets the same response. A template names its custom icon, which the icon library resolves. templates and collections are the template library of the server (source library), in the order that callers added their items. Every user with Builder access changes the same library: no item has an owner. A server whose library never changed has an empty library. When this server cannot read the library record, the response has damaged true and none of its items. The server then refuses every change of it with 409. builtins are the five built-in templates (server, workstation, router, firewall, external, source builtin, version 1). preloaded lists the collections that the server read at start from the template files of its template directory (--base-dir.builder-templates). There is one collection per file, with its templates (source preloaded, version 1). Built-in and preloaded items are read only. A write route that names one gets 409 with the code template.item.read-only. A caller can change a copy in the library. A template that a diagram copied names its source in the diagram (templates[].source of the Builder document: kind, id and version). When the version of the item with that source and id here is higher, the library holds a newer version.

Responses

Response samples

Content type
application/json
{
  • "templates": [
    ],
  • "collections": [
    ],
  • "builtins": [
    ],
  • "preloaded": [
    ],
  • "damaged": true,
  • "limits": {
    }
}

Add device templates to the template library

Requires builder use. Adds 1 to 200 templates in one write, each with a new ID. With collection, the same write also makes a new collection that holds exactly those templates. The custom icon of a template (device.icon) is an icon name. The icon library resolves it, whether or not it holds that icon now. A template of the library has no source.

Request Body schema: application/json
required
required
Array of objects [ 1 .. 200 ] items
object

a new collection to hold exactly the new templates

Responses

Request samples

Content type
application/json
{
  • "templates": [
    ],
  • "collection": {
    }
}

Response samples

Content type
application/json
{
  • "created": [
    ],
  • "collection": {
    }
}

Replace a device template of the template library

Requires builder use. Any user with Builder access may replace any template of the library. Replaces the name, the description and the device of one template. The template keeps its ID, and its version increases by one. Content that is equal to the stored content changes nothing and keeps the entity tag. Devices already made from the template do not change. A diagram's copy of the template changes only when its user updates it.

path Parameters
template
required
string^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$

template ID

header Parameters
If-Match
required
string

The etag of the template or collection that the change is based on: exactly one strong, quoted entity tag, such as "3". A missing header, a wildcard or a weak tag gets 400. A tag that does not name the current content gets 412.

Request Body schema: application/json
required
name
required
string

1 to 128 bytes, not blank, without control characters

description
string

at most 1024 bytes, without control characters

required
object (BuilderTemplateDevice)

What a template sets: every field of a device node except its hostname, its connection points and where it was included from. The editor names a device made from the template after spec.general.hostname, and makes that name unique in the diagram.

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "description": "string",
  • "device": {
    }
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "source": "library",
  • "name": "string",
  • "description": "string",
  • "device": {
    },
  • "version": 0,
  • "etag": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "updated": "2019-08-24T14:15:22Z",
  • "createdBy": "string",
  • "updatedBy": "string",
  • "collections": [
    ]
}

Add a collection to the template library

Requires builder use. A collection is a named group of templates of the library. A template can be in more than one collection. Every ID in templateIds must name a template of the library, one time. A built-in template or a template of a template file gets 409.

Request Body schema: application/json
required
name
required
string

1 to 128 bytes, not blank, without control characters

description
string

at most 1024 bytes, without control characters

templateIds
Array of strings <= 200 items

templates of the library, each named once

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "description": "string",
  • "templateIds": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "source": "library",
  • "name": "string",
  • "description": "string",
  • "templateIds": [
    ],
  • "version": 0,
  • "etag": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "updated": "2019-08-24T14:15:22Z",
  • "createdBy": "string",
  • "updatedBy": "string"
}

Replace a collection of the template library

Requires builder use. Replaces the name, the description and the templates of one collection. The collection keeps its ID. To add a template to a collection, or to remove one from it, send this request with the changed list. Content that is equal to the stored content changes nothing and keeps the entity tag.

path Parameters
collection
required
string^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$

collection ID

header Parameters
If-Match
required
string

The etag of the template or collection that the change is based on: exactly one strong, quoted entity tag, such as "3". A missing header, a wildcard or a weak tag gets 400. A tag that does not name the current content gets 412.

Request Body schema: application/json
required
name
required
string

1 to 128 bytes, not blank, without control characters

description
string

at most 1024 bytes, without control characters

templateIds
Array of strings <= 200 items

templates of the library, each named once

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "description": "string",
  • "templateIds": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "string",
  • "source": "library",
  • "name": "string",
  • "description": "string",
  • "templateIds": [
    ],
  • "version": 0,
  • "etag": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "updated": "2019-08-24T14:15:22Z",
  • "createdBy": "string",
  • "updatedBy": "string"
}

Delete templates and collections of the template library

Requires builder use. Deletes the named templates and collections in one write. Each item names the etag of the content that the caller read, as a PUT names it in If-Match. An item without a strong, quoted tag gets 400. When the library holds any item at another tag, the whole request gets 412 with template.item.stale and the current tag of that item. The server then deletes nothing. The server ignores an ID that the library does not hold, so a repeat of the request is harmless. A deleted template leaves every collection that held it. A deleted collection leaves its templates. A built-in template or an item of a template file gets 409. Diagrams do not change: a diagram's copy of a deleted template stays, and its editor says that the library template was deleted.

Request Body schema: application/json
required
Array of objects (BuilderTemplateRef)
Array of objects (BuilderTemplateRef)

Responses

Request samples

Content type
application/json
{
  • "templates": [
    ],
  • "collections": [
    ]
}

Response samples

Content type
application/json
{
  • "deleted": {
    }
}

List the layer sets of the Builder layer set library

Requires builder use. The layer set library belongs to the server, and every user of the Builder sees every set. The built-in sets come first (the Purdue Model set, ID builtin:purdue). The other sets follow by name, ignoring case. defaultId is the default set of the server for new diagrams, or null. defaultEtag is the entity tag that a change of that choice names in If-Match. damaged counts the records that the server cannot read, which the list does not show.

Responses

Response samples

Content type
application/json
{
  • "layerSets": [
    ],
  • "defaultId": "string",
  • "defaultEtag": "\"0\"",
  • "damaged": 0,
  • "limits": {
    }
}

Add a layer set to the Builder layer set library

Requires builder use. Adds a set under a new ID, at version 1. Every user of the Builder sees every set. The library holds at most 200 sets, apart from the built-in sets. To duplicate a set, read it and send its content here.

Request Body schema: application/json
required
name
required
string [ 1 .. 128 ] characters

not blank, at most 128 bytes, with no control characters

description
string <= 1024 characters

at most 1024 bytes, with no control characters

iconKey
string

the built-in icon of the set. Empty for none

icon
string

a custom icon name, shown in place of iconKey. Empty for none

matchConflict
string
Enum: "" "lowest" "highest"

the layer that a device gets when the node matchers of more than one layer match it: the lowest ID or the highest ID. Empty is lowest

layerOutlines
boolean

when true, the editor draws the outline of a node in the color of its layer, unless the node has its own outline color

required
Array of objects (BuilderLayer) [ 1 .. 32 ] items

1 to 32 layers, each with an ID that no other layer has

Responses

Request samples

Content type
application/json
{
  • "name": "Plant levels",
  • "description": "Levels of the water plant network.",
  • "iconKey": "plc",
  • "icon": "string",
  • "matchConflict": "lowest",
  • "layerOutlines": false,
  • "layers": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "builtin:purdue",
  • "name": "string",
  • "description": "string",
  • "iconKey": "string",
  • "icon": "string",
  • "matchConflict": "lowest",
  • "layerOutlines": true,
  • "layers": [
    ],
  • "builtin": true,
  • "version": 0,
  • "etag": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "updated": "2019-08-24T14:15:22Z",
  • "createdBy": "string",
  • "updatedBy": "string"
}

Read the default layer set of the server

Requires builder use. Returns the set that new diagrams of all users start with, or null. The server has one default set for all users. A selection of a set that no longer exists is null. A new blank diagram copies the default set and links to it. With no default, a new diagram shows the placeholder layers 0 to 6. etag is the entity tag of the selection, which a change of it names in If-Match.

Responses

Response samples

Content type
application/json
{
  • "id": "builtin:purdue",
  • "etag": "\"0\""
}

Select the default layer set of the server

Requires builder use. Selects the set that the new diagrams of all users copy. Each Builder user can change it. id null or empty removes the selection. If-Match must name the etag of the current selection. Another tag gets 412 (layerset.stale) with the current tag. A set that does not exist gets 422 with the code layerset.default.unknown.

header Parameters
If-Match
required
string

The etag of the default selection, as listed or read, such as "0". A missing header, a wildcard or a weak tag gets 400. A tag that does not name the current selection gets 412 (layerset.stale).

Request Body schema: application/json
required
id
string or null

the ID of a layer set, or null for none

Responses

Request samples

Content type
application/json
{
  • "id": "builtin:purdue"
}

Response samples

Content type
application/json
{
  • "id": "builtin:purdue",
  • "etag": "\"0\""
}

Read a layer set of the Builder layer set library

Requires builder use. Returns the set with its entity tag.

path Parameters
layerset
required
string

the ID of the layer set. A path that names no set gets 404, whatever its form

Responses

Response samples

Content type
application/json
{
  • "id": "builtin:purdue",
  • "name": "string",
  • "description": "string",
  • "iconKey": "string",
  • "icon": "string",
  • "matchConflict": "lowest",
  • "layerOutlines": true,
  • "layers": [
    ],
  • "builtin": true,
  • "version": 0,
  • "etag": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "updated": "2019-08-24T14:15:22Z",
  • "createdBy": "string",
  • "updatedBy": "string"
}

Replace a layer set of the Builder layer set library

Requires builder use. Any user with this permission may change any set, but nobody may change a built-in set (403, layerset.read-only). Replaces the content of the set. A change increases the version by one. Content that is equal to the stored content changes nothing and keeps the entity tag. Diagrams that copied the set keep their copies, and the editor offers them the update.

path Parameters
layerset
required
string

the ID of the layer set. A path that names no set gets 404, whatever its form

header Parameters
If-Match
required
string

The etag of the layer set that the change is based on: exactly one strong, quoted entity tag, such as "3". A missing header, a wildcard or a weak tag gets 400. A tag that does not name the current content gets 412 (layerset.stale).

Request Body schema: application/json
required
name
required
string [ 1 .. 128 ] characters

not blank, at most 128 bytes, with no control characters

description
string <= 1024 characters

at most 1024 bytes, with no control characters

iconKey
string

the built-in icon of the set. Empty for none

icon
string

a custom icon name, shown in place of iconKey. Empty for none

matchConflict
string
Enum: "" "lowest" "highest"

the layer that a device gets when the node matchers of more than one layer match it: the lowest ID or the highest ID. Empty is lowest

layerOutlines
boolean

when true, the editor draws the outline of a node in the color of its layer, unless the node has its own outline color

required
Array of objects (BuilderLayer) [ 1 .. 32 ] items

1 to 32 layers, each with an ID that no other layer has

Responses

Request samples

Content type
application/json
{
  • "name": "Plant levels",
  • "description": "Levels of the water plant network.",
  • "iconKey": "plc",
  • "icon": "string",
  • "matchConflict": "lowest",
  • "layerOutlines": false,
  • "layers": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "builtin:purdue",
  • "name": "string",
  • "description": "string",
  • "iconKey": "string",
  • "icon": "string",
  • "matchConflict": "lowest",
  • "layerOutlines": true,
  • "layers": [
    ],
  • "builtin": true,
  • "version": 0,
  • "etag": "string",
  • "created": "2019-08-24T14:15:22Z",
  • "updated": "2019-08-24T14:15:22Z",
  • "createdBy": "string",
  • "updatedBy": "string"
}

Delete a layer set from the Builder layer set library

Requires builder use. Any user with this permission may delete any set, but nobody may delete a built-in set (403, layerset.read-only). Diagrams that copied the set keep their copies. A default selection of the set becomes null. If-Match must name the etag of the current content. A record that the server cannot read has the tag of its record revision, "<revision>", which a 412 gives.

path Parameters
layerset
required
string

the ID of the layer set. A path that names no set gets 404, whatever its form

header Parameters
If-Match
required
string

The etag of the layer set that the change is based on: exactly one strong, quoted entity tag, such as "3". A missing header, a wildcard or a weak tag gets 400. A tag that does not name the current content gets 412 (layerset.stale).

Responses

Response samples

Content type
application/json
{
  • "message": "string",
  • "cause": "string",
  • "metadata": {
    },
  • "code": "publish.blocked",
  • "issues": [
    ]
}