OTA Plugins
MADS Version 1.3.0 introduces the possibility to load plugins Over-The-Air (OTA): plugin files can be provided to agents by the broker. This allows to centralize the management of plugins and to update them without the need to manually copy compiled plugins to the devices running the agents.
Motivation
Suppose that you have a MADS network made by a relatively large number of devices, each running one or more agents. You want to update the plugins loaded by the agents. If you have only a few devices (say 2–3), you can manually copy the plugin files to each device. But if you have many devices, this is not practical and it is also error prone, because you need to keep track of which devices have been updated and which haven’t.
This use case is where the idea of being able to load plugins OTA comes from. The broker can provide the plugin files to the agents, which can then load them dynamically. This allows you to update the plugins without having to manually copy the files to each device: only the broker needs to have the plugin files, and the agents will load them automatically. There is only one copy of each plugin, and no risk of mismatching versions.
How it works
Upon launch, each agent needs to load its settings file. By default, the agent assumes that it is running on the same device of the broker, so it tries and load the mads.ini file from the MADS prefix directory (equivalent to $(mads -p)/etc). If the agent is running on a different device, it must load the settings from the broker. This is done by providing the -s command line option to the agent, which specifies the broker address and port that provides the settings file (typ. port 9093). For example:
mads source -s tcp://mads-broker.local:9093 my_datasource.pluginWhen the -s option contains a TCP URI address, the agent opens a special ZeroMQ communication channel to the broker, requesting for settings. To this request, the broker replies with a copy of the mads.ini file as loaded by the broker itself.
Starting from MADS 1.3.0, the mads.ini file can contain, for each section, a new option called attachment. When this option is provided for an agent, the broker attaches to the INI file copy a binary attachment, read form the file path specified in the option. For example, the following mads.ini file:
[my_datasource]
attachment = "/path/to/my_datasource.plugin"will cause the broker to attach the file /path/to/my_datasource.plugin to the mads.ini file copy sent to the agent. The agent will then save the attached plugin to a temporary folder and load it dynamically.
Implementation details
There are a number of things to keep in mind when using this feature:
- how to define the plugin and the agent name
- how to deal with plugins compiled for different architectures
- what happens if a plugin is provided as attachment and also on the command line
Plugin and agent names
In MADS, there are three agents able to load plugins: source, filter, and sink. As for any agent, the INI section to be loaded is defined by the agent name. In turn, the latter is defined as:
- the name of the agent executable for monolithic plugins
- the name of the plugin for
source,filter, andsink
In reality, there is also the worker agent (see here), which behaves as a filter agent but it is designed for a 1 dealer / n worker scenario for parallel computing, where a single dealer agent dispatches a list of computations to a number of identical workers in a round-robin fashion. The agent name for a worker is mandatory (no default).
Also, note that source, filter, and sink agents can be called without a plugin: in this case, they run as general-purpose agents that deal with input and output data (as valid JSON strings) via pipes. When this happen, the agent names are publish for the source agent, bridge for the filter agent, and feedback for the sink agent.
The name of an agent can be always be overridden by the -n command line option, which allows to specify a custom name for the agent. This is useful, for example, when you want to run multiple instances of the same agent with different settings.
Now, since the OTA loading of the plugin happens after the agent has loaded its settings, the agent name must be specified with the -n CLI option, otherwise would simply launch as general purpose agent with default names.
For example, if the mads.ini file contains the [my_datasource] section as above, the agent must be launched as:
mads source -s tcp://mads-broker.local:9093 -n my_datasourceDealing with architectures
When the plugin is provided as an attachment, the broker will send a copy of the file to the agent, which will save it to a temporary folder and load it dynamically. This means that the plugin must be compatible with the architecture of the device running the agent.
Now suppose that we want to run the same plugin on different devices, some of which are ARM-based and some are x86-based. If the plugin is compiled for a specific architecture, it will not work on the other architecture.
The solution follows these steps:
compile two plugin versions, one for each architecture, and copy both files on the broker filesystem. Call them, for example,
my_datasource_arm.pluginandmy_datasource_x86.pluginin the
mads.inifile, define two sections, one for each architecture with different names:[my_datasource_arm] attachment = "/path/to/my_datasource_arm.plugin" [my_datasource_x86] attachment = "/path/to/my_datasource_x86.plugin"when launching the agent, specify the correct section name with the
-noption, depending on the architecture of the device running the agent:mads source -s tcp://mads-broker.local:9093 -n my_datasource_arm
Note that, when compiling a plugin, the CMakeLists.txt file in the plugin project has an option to append an architecture suffix to the generated plugin file: if you configure the project as:
cmake -Bbuild -DPLUGIN_SUFFIX=arm -DCMAKE_INSTALL_PREFIX=$(mads -p)then the plugin will be compiled as my_datasource_arm.plugin (assuming the plugin name is my_datasource). Of course, versions for non-native architectures must be cross-compiled or compiled in a virtual machine or on the target device itself.
Command line vs. attachment
Note that command line options always override the settings in the mads.ini file, so if you also specify the plugin name, the broker attachment will be ignored. For example, the following command will not load the plugin from the broker, but will use the one specified on the command line (on the local filesystem):
mads source -s tcp://mads-broker.local:9093 -n my_datasource my_datasource.pluginPython agent
This feature is only available from MADS v1.3.1 onwards.
The attachment feature can be also exploited by the python_agent monolithic agent. In this case, the attachment option must be the path of a valid and MADS-compatible Python module in the broker filesystem, and the remote agent will receive a copy of that file and load it upon launch. Note that the virtual environment still needs to be set up on the remote agents, exactly as if the agent was loading the Python module from the local filesystem.
Note that by default, attachments are saved as temporary files with the .plugin extension, which would normally prevent the Python agent from loading them. For this reason, the INI file also supports an attachment_ext option, which specifies the extension of the attachment file. For example:
[my_python_agent]
attachment = "/path/to/my_python_agent.py"
attachment_ext = "py" # WARNING: NO LEADING DOT!The attachment_ext option is mandatory unless you are giving a plugin file with the .plugin extension, which is the default. It must not contain the leading dot, so for example if you want to load a Python module called my_python_agent.py, you must specify attachment_ext = "py".