Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[mihini-dev] Design: unification of device tree and asset tree

The device tree / asset tree APIs need to be overhauled and unified. Here's a summary of how it currently works, and an improvement proposal.

Currently, we have two trees accessed through two different APIs:
  • the device tree, accessed through module racon.devicetree, allows to access arbitrary variables, handled through mountable drivers by the agent, through a get/set/register API (register allows to be notified about any change of variable values within a subtree)
  • the asset tree allows applications to describe how an asset should react to incoming data from the server. A set of handler functions are attached to nodes, within a subtree whose root is the asset itself.
We want to provide the latter service as a variant of the former: an asset would have a node in the device tree, e.g. server.<asset_name>, and applications would be free to register for some of the data. For instance, if the asset greenhouse needs to react to an order to open/close a window, it could be implemented as follows

local function window_control(is_open) 
    if is_open then gpio.write(WINDOW, 1) 
    else gpio.write(WINDOW, 0) end 
end 
 
devicetree.register('server.greenhouse.window', window_control)

About the mapping between server communications and device tree API:
  • register() allows to easily be notified about incoming server data. 
  • One could expect, one day, get() to translate into some query to the server. Today however, the server supports no such notion, and it's not completely obvious how useful it would be in practice
  • set() would be naturally interpreted as a way to write data to the server, but with a huge caveat: it wouldn't handle policies. As such it couldn't replace :pushdata(), and of course not the advanced SDB table API. Having 3 significantly overlapping APIs sounds like an awful anti-pattern; getting rid of :pushdata() would marginalize policy usage, which we might not want either; and SDB tables are necessary for advanced users.
Moreover, if assets are casually accessed through the device tree API, access control on the tree becomes highly desirable. A simple yet good enough API would be to have a set of (node * user * permissions) triplets, and each connection to the agent having a user identity determining what it's authorized to read/write. Those triplets would themselves be encoded inside the device tree, only writable by some super user, and maybe even closed for reading. A node's permission would be determined by its closest parent having explicitly set permissions. For practical purposes, an "everybody" user should be usable for permission specification. For instance, a non-paramoid setup for the example above would be:

{ "server.greenhouse": { "everybody": "RO" },
  "server.greenhouse.window": { "greenhouse": "RW" } }

A given identity's permissions are therefore decided by the parent permissions associated either to this identity, or to the special "everybody" identity. More refined groups management might fall deep into over-engineering, and should only be considered if/when practice shows them to be necessary. On of the goals of the device tree is to remain a simple and generic API, making it as complicated as a filesystem or as SNMP would defeat this key purpose.

The meaning of permissions is straightforward for get() and set() operations. For register(), it's a bit less obvious. On can register for a whole subtree, with many nodes in it possibly having different permissions. The simplest solution would be that everyone would be allowed to register everything, but would only be actually notified about data for which they have reading rights. Whether a warning is needed at registration time should be decided after some real-life feedback IMO.

--
Fabien Fleutot


Back to the top