Skip to content

Configuration system

magnusfeuer edited this page Apr 13, 2012 · 12 revisions

TODO

  • Document how access profiles controls descriptors, instances and devices.
  • Document how the config system notifies local erlang code and other systems on device. See Tony's doc.
  • Document how RPC code, specified by config descriptors, are invoked
  • Do how Monitors, specified by config descriptors, are started
  • See if there is a way to get the "code" keyword in configuration descriptor YANG compliant
  • Document how Monitor code is specified in a configuration descriptor.
  • Add schematics for the config data's path from the server to the device.
  • Document list edits (add/merge/replace). Look at YANG solution.

Configuration system for Exosense

This document describes the configuration system of the Exosense server and device.

The internal structures and the JSON based API are the main objects described.

Layout

Schematic of Configuration System

Access Profile

TBD

Configuration Descriptor

A configuration descriptor contains the configuration specification and erlang code for RPCs and Monitors. Config descriptors are written in YANG. Often configuration descriptors include other descriptors to form an aggregate of many fragments. An example of a fragment is a configuration descriptor is a tty, which is always aggregated into a larger configuration descriptor specifying an entire device.

The descriptor also contains erlang code in the form of RPCs and monitors that can be executed on a device. The erlang code is specified in a "code" section that YANG is extended with. The main application of a device is written as a monitor provided through a specific "application" configuration descriptor.

Below is a configuration descriptor for a tty together with an RPC to send a break.

container tty {
  leaf port {
    type string;
   }
   rpc send-break { 
    input {
      leaf MSec {
        type uint16;
     },
     code {
       fun(Msec) -> serctl:tcsendbreak(Msec).
     }
  }
}

A Fox20 board descriptor can aggregate a list copies of the tty descriptor. In addition to the serial ports, a list of A/D ports specific for the fox20 board are specified as well.

container fox20 {
  leaf some_value {
    type: uint32;
  }

  list serial-ports {
    key "port";
    uses tty;
  }

  list daq-ports {
    key "port_no";
    leaf port_no {
      type uint16;
    }
    leaf sample_hz {
      type uint16;
    }
  }
}

The fox20 configuraiton descriptor can then be used as a template when creating a configuration instance.

Configuration Instance

A configuration instance is an aggregate of one or more instantiated configuratiopn descriptors. The instance contains the actual configuration data that is to be installed on devices. RPCs and monitors specified by the used configuration descriptors will be available in the devices receiving the configuration data instance.

The configuration instance is created through a JSON call, where the descriptors and the config data values are specified:

{
  "jsonrpc": "2.0", 
  "method": "create-config-instance", 
  "id": 3,
  "params": {
    "name": "customer_x_fox20_rev_1.0",
    "descriptors": [ "fox20" ]

    "values": {
      "some_value": 1234;

      "serial-ports": [ 
        { "port": "/dev/ttyS0" },
        { "port": "/dev/ttyS1" }
      ],

      "daq-ports": [
        { 
          "port_no": 0;
          "sample_hz": 50;
        },
        { 
          "port_no": 1;
          "sample_hz": 250; 
        }
      ]
    }
  }
}

Values in the configuration instance can then be modified using JSON RPC calls:

{
  "jsonrpc": "2.0", 
  "method": "set-config-instance-value", 
  "id": 3,
  "params": {
    "config-instance": "customer_x_fox20_rev_1.0",
     "values": {
       "some_value": 9999;
     }
  }
}

Devices

Devices specify a physical device, each with their own customer-unique device id. A device is provisioned using the call below:

{
  "jsonrpc": "2.0", 
  "method": "provision-device", 
  "id": 3
  "params": {
    "device-id": 4711,
  }, 
}

Adding devices to a configuration instance

Once created, devices can be added as members of one or more configuration instances using the JSON RPC call below. Please note that multiple devices and configuration instances can be specified. All listed devices will be added as members of all listed configuration instances

{
  "jsonrpc": "2.0", 
  "method": "add-configuration-instance-members", 
  "id": 3,
  "params": {
    "configuration-instance": [ "customer_x_fox20_rev_1" ],
    "device-id": [ 4711, 4712, 4713 ]
   }
}

After the call above completes. Updates to the configuration instance "customer_x_fox20_rev_1" will be pushed to devices 4711, 4712 and 4713 as described below.

Copying Configuration Instance to its member devices

Once devices have been added to a configuration instance, the actual configuration values can be pushed to to all member devices:

{
  "jsonrpc": "2.0", 
  "method": "push-config", 
  "id": 3,
  "params": {
    "config-instance": "customer_x_fox20_rev_1.0",
  }
}

The command above will start distributing all the config data and the RPC/Monitor code of "customer_x_fox20_rev_1.0" to the devices associated with the configuration instance.

The config data's path to a device

When a config instance is pushed to its members, the data will reach each device through three separate phases: staging, pending and active. These phases are processed on a per-device basis, meaning that different member devices can be in different phases at any given time depending on their connectivity.

The initial phase, staging, is entered for each device when the push-config JSON RPC is executed.

The staging phase

The staging phase represents the data before it has been transmitted to the target device. The configuration data is available on the server and describes what will eventually be copied to the device. When a data link has been established to the device, the staging data will be copied to the pending area inside the device.

At any time the staging configuration data for a device can be inspected through JSON RPC calls.

The pending phase

The pending phase is entered for a device when the first configuration value is copied from the server's staging area to the device's pending area. Once all data has been copied from the server staging config data to the device pending config area, the pending data can be activated atomically on the device through a specific JSON request.

At any time, a JSON RPC call can be made to the server to retrieve the pending configuration data in order to inspect what configuration elements have actually been copied to the device. Any elements whose value differs between the staging data and the pending data has yet to be copied.

The active phase

Once the staging and pending configuration data are identical, indicating that all configuration elements have been copied from the server's staging area to the pending area of the device, the pending data can be activated atomitcally through a JSON call. This call will copy all data in the pending set on the device to the running set. The same operation will also be carried out on the active configuration data copy hosted on the server.

Once the configuration data has been copied to the active set, the code running on the device will be notified of the updated data.

Modifying the configuration data of individual devices

Each device often carry individual configuration data elements that needs to be modified directly, thus bypassing configuration data instances the device is a member of.

This can be done by directly setting configuration values the staging area configuration data for the given device:

{
  // TODO: List edits.
  "jsonrpc": "2.0", 
  "method": "set-device-config-value", 
  "id": 3,
  "params": {
    "device-id": 4711,
     "values": {
       "some_value": 9999;
     }
  }
}

Mixing in additional configuration data on one or more devices.

If a specific device needs to have additional configuraiton data (and code) added to it, it can be handled by adding the device as a member of the configuration instance hosting the desired data.

For example, a yaws web server configuration descriptor may look like this.

containier yaws {
  leaf listen-port {
    type uint16;
  }
}

The descriptor above is then instantiated into a configuration instance, with the listening port set to 80:

{
  "jsonrpc": "2.0", 
  "method": "create-config-instance", 
  "id": 3,
  "params": {
    "name": "yaws-cfg-instance",
    "descriptors": [ "yaws" ]

    "values": {
      "listen-port": 80;
    }
  }
}

All devices that should have this configuration data are then added to the configuration instance. In this example only device 4711 will be added.

{
  "jsonrpc": "2.0", 
  "method": "add-configuration-instance-members", 
  "id": 3,
  "params": {
    "configuration-instance": [ "yaws-cfg-instance" ],
    "device-id": [ 4711 ]
   }
}

When data is pushed to the devvice, using a push-config JSON RPC, the values of "yaws-cfg-instance" will be copied to the server's pending area for device 4711. From there the data will be copied out to the device in the phases described above.

Clone this wiki locally