Protocol
This page documents the data model/protocol used by VILLAScontroller to control and monitor infrastructure components (IC). The protocol uses AMQP to transport JSON encoded objects which are specified in the following document.
VILLAScontroller is implemented in Python and using the Kombo messaging package.
The Git repository is available at: http://github.com/VILLASframework/controller
The purpose of VILLAScontroller is the orchestration of IC in distributed lab setups. This includes the following tasks:
- management: instantiation, deletion & discovery
- monitoring: status?
- control: start, stop, pause, reset, resume, shutdown
Entities
For the purpose of addressing the ICs, we introduce the following categories (1st level) and types (2nd level):
simulator
dpsim
generic
rtlab
rtds
dummy
kubernetes
(a Kubernetes Job)
gateway
villas-node
villas-relay
manager
villas-node
villas-relay
generic
kubernetes
These component types are implemented by the following class hierarchy in VILLAScontroller's Python code:
Exchange
All messages processed by VILLAScontroller are sent via an AMQP headers
exchange.
The exchange is named villas
.
Routing
The following headers are used to identify and route messages to the recipients:
realm
describes the entity which is responsible for operating the equipment. The realm should be a fully qualified domain name (FQDN) in reverse order.- Examples:
de.rwth-aachen.eonerc.acs
gov.inl
- Examples:
category
describes the classes of equipment.- Examples:
simulator
manager
(manages ICs, e.g. Kubernetes Jobs, VILLAS WebSocket endpoints)gateway
(e.g. VILLASnode, e.g. VILLASrelay)
- Examples:
type
further defines the type/vendor of a device within its class.- For
simulator
:dummy
(implemented)generic
(implemented)dpsim
(WIP)rtlab
(planned)rscad
(planned)
- For
gateway
:villas-node
(implemented)villas-relay
(implemented)
- For
controller
:kubernetes
villas-controller
- For
service
: ems
custom
?- For
equipment
: chroma-emulator
chroma-loads
sma-sunnyboy
fleps
sonnenbatterie
- For
uuid
is a globally unique identifier- Examples:
56babc1e-0476-11e8-9375-471525328a77
- Examples:
Example of an application header:
{
"realm" : "de.rwth-aachen.eonerc.acs",
"category" : "simulator",
"type" : "rtlab",
"uuid" : "56babc1e-0476-11e8-9375-471525328a77"
}
Important: Note that at least one of the headers must be provided. Otherwise no component will receive it.
It is also valid to just provide a single header (e.g. uuid
to address a specific component or type
to address a class of components).
State Machine
Management
Discovery
In a messaging protocol like AMQP, brokers do not store message contents in a persistent way. They only temporarily queue messages until they have been delivered. Therefore, the broker cannot keep track of the state or presence of entities.
This section describes a simple discovery mechanism to work around this limitation.
Each entity must react on action = ping
messages and respond immediately with a status response message.
{
"action" : "ping"
}
After receiving such a message, each entity shall send a status update message as described below.
Status Update
{
"status" : {
/* Generic state */
"state" : "running",
"version" : "0.1.0", /* VILLAScontroller version */
"uptime" : 123124.0, /* in seconds since initialization (float) */
"error": { /* only present if state == "error" */
"message": "This is an error message",
"code": 1234
},
"managed_by": "4af1cf3a-7e80-11eb-a7f4-b700f4a4f18d", /* link to managing IC of category 'manager' */
/* Custom state (depending on IC type) */
"villas_node_version": "v0.11.0",
"kernel": ["Linux", "villas-node-594f8c7bff-wmznc", "5.0.0-29-generic", "#31~18.04.1-Ubuntu SMP Thu Sep 12 18:29:21 UTC 2019", "x86_64"],
"host": "villas-node-594f8c7bff-wmznc"
},
"properties": { /* fixed configuration of IC as provided by user */
/* Generic properties */
"name" : "OP5600",
"description" : "some optional description",
"location" : "OPAL-RT Rack, ACS Real-time Lab, EONERC, RWTH",
"owner" : "post@steffenvogel.de",
"ws_url" : "https://villas.k8s.eonerc.rwth-aachen.de/ws/relay/node_1",
"api_url" : "https://villas.k8s.eonerc.rwth-aachen.de/ws/relay/api/node_1",
/* Custom properties (depending on IC type) */
"opal_hostname": "opal-op5600.acs-lab.eonerc.rwth-aachen.de"
"namespace": "villas"
"job_name": "My_Kubernetes_Simulator"
"pod_names": ["pod_number_1", "pod_number_2"]
/* Signal description in the same format as used by VILLASnode:
* https://github.com/VILLASframework/node/blob/master/doc/openapi/components/schemas/config/signal_list.yaml
*/
"signals": [
{ "name": "voltage_bus123_phase1", "unit": "V", "type": "float" },
{ "name": "voltage_bus123_phase2", "unit": "V", "type": "float" },
{ "name": "voltage_bus123_phase3", "unit": "V", "type": "float" }
]
},
"schema": {
"start": {
/* JSON-Schema describing start parameters. */
},
"create": {
/* JSON-Schema describing properties of new ICs created via create action (targeted at ICs of category=manager). */
}
},
"when" : 1234567890 /* timestamp in seconds (UTC / Unix epoch / since 1970-01-01) (float) */
}
Used values for state
:
gone
(issued once afteraction = delete
)error
idle
starting
running
pausing
paused
resuming
stopping
resetting
shuttingdown
shutdown
Management
Creation of new components
Important: This action type must be directed at a component of category manager
!
{
"action": "create",
"when": 1234567890,
"parameters": {
"name": "DPsim simulator",
"location": "ACS lab",
"realm": "de.rwth-aachen.eonerc.acs",
"category": "simulator",
"type": "dpsim"
"uuid": "c487a470-6af6-11eb-beee-7fa268050404",
"properties": {
"myproperty": 1234
}
}
}
The uuid
parameter is optional. If not provided, the managing component will generate a random one.
Deletion of components
Important: This action type must be directed at a component of category manager
!
{
"action": "delete",
"parameters": {
"uuid": "c487a470-6af6-11eb-beee-7fa268050404"
}
"when": 1234567890,
}
Control
Reset
{
"action" : "reset",
"when" : 1234567890
}
Shutdown
{
"action" : "shutdown",
"when" : 1234567890
}
Start
Start the simulation at a specific point in time.
{
"action" : "start",
"parameters" : {
"timestep" : 50e-6,
"duration" : 10,
"domain" : "dp",
"downsample" : 1
},
"model" : { // HTTP GET for model download
"type": "url-list",
"url" : [
"https://villas.k8s.eonerc.rwth-aachen.de/api/v2/files/123421",
"https://villas.k8s.eonerc.rwth-aachen.de/api/v2/files/123422"
],
"token": "Xwlsjkdlfksjhdfglskdfg"
},
"results" : { // HTTP POST for results upload
"type" : "url"
"url" : "https://villas.k8s.eonerc.rwth-aachen.de/api/v2/runs/3452345234/results"
"token": "Xwlsjkdlfksjhdfglskdfg"
},
"when" : 1234567890
}
Another example for type = generic
:
{
"action" : "start",
"parameters" : {
"executable" : "ping",
"argv" : [
"google.de",
"-c", "10"
],
"working_directory" : "/tmp/simulationX",
"shell" : false,
"environment" : [
"DEBUG" : "1"
]
},
"when" : 1234567890
}
Stop
Stop the simulation at a specific point in time.
{
"action" : "stop",
"when" : 1234567890
}
Pause
Pause the simulation at a specific point in time.
{
"action" : "pause",
"when" : 1234567890
}
Resume
Resume the simulation at a specific point in time.
{
"action" : "resume",
"when" : 1234567890
}