Writing Plugins

OCS supports adding external Agents via a plugin system. The underlying mechanism uses the package metadata, as described in the PyPA Documentation. Making a package into an ocs plugin requires the creation of a plugin file, which tells OCS how to import new Agents, as well as the addition of an entry point in the package’s setup.py file.

Plugin File

The plugin file can be added anywhere in the package, i.e. <package>.plugin. The contents are simple, just a single string with the name of the package and a dict with an entry for each Agent describing the module and its entry point. For example here is the plugin file for the core ocs repository:

package_name = 'ocs'
agents = {
    'RegistryAgent': {'module': 'ocs.agents.registry.agent', 'entry_point': 'main'},
    'AggregatorAgent': {'module': 'ocs.agents.aggregator.agent', 'entry_point': 'main'},
    'HostManager': {'module': 'ocs.agents.host_manager.agent', 'entry_point': 'main'},
    'FakeDataAgent': {'module': 'ocs.agents.fake_data.agent', 'entry_point': 'main'},
    'InfluxDBAgent': {'module': 'ocs.agents.influxdb_publisher.agent', 'entry_point': 'main'},
    'BarebonesAgent': {'module': 'ocs.agents.barebones.agent', 'entry_point': 'main'},
}

The keys of the agents dictionary should match the names of the Agents set in the Agent and used in the SCF.

Warning

Conflicting Agent names are not handled well across plugins. Use a unique Agent name when adding new Agents until this is improved.

Note that each Agent needs to have an entry point that can be called to run the Agent. In the above example each Agent defines a main method that is used. If undefined, OCS will default to trying to use main as the entry point. Before the introduction of this plugin system this was typically handled within the __main__ block.

Package Entry Point

After you have created the plugin file, you need to add an entry point to setup.py. This will register your package for discovery by ocs. This looks like (assuming the plugin file is called plugin.py and lives at the top level of the package):

entry_points={
    'ocs.plugins': [
        '<plugin name> = <package name>.plugin',
        ],
},

Plugin name should just match the package name, however the group name must always be ocs.plugins in order for OCS to recognize the plugin. For example, if your package was called my_ocs_pkg this would be:

entry_points={
    'ocs.plugins': [
        'my_ocs_pkg = my_ocs_pkg.plugin',
        ],
},

Agent Entry Point

OCS needs to know the entry point function used to launch each Agent in your plugin. By default ocs will try to use main as the entrypoint. If your Agent entrypoint has a different name you must list it in plugin.py. This function must take a single parameter for passing arguments through to the Agent. This looks something like:

def main(args=None):
    parser = add_agent_args()
    args = site_config.parse_args(agent_class='BarebonesAgent',
                                  parser=parser,
                                  args=args)

    agent, runner = ocs_agent.init_site_agent(args)

    barebone = BarebonesAgent(agent)

    runner.run(agent, auto_reconnect=True)

This example leaves out some other boilerplate from the Barebones Agent, but the important part is the args=None argument to main(), and passing those args to site_config.parse_args().

Testing

You should now be able to start the new Agents through ocs-agent-cli. However, if you’d like to search for the plugin more directly you can do so by running:

import sys
if sys.version_info < (3, 10):
    from importlib_metadata import entry_points
else:
    from importlib.metadata import entry_points

discovered_plugins = entry_points(group='ocs.plugins')
print(discovered_plugins)
# [EntryPoint(name='ocs', value='ocs.plugin', group='ocs.plugins')]

Deploying + Docker

Your plugin can now be deployed by installing the package with pip. It can also be built into a Docker image, which can then be used to run all of the Agents included in the plugin. For details on how to build a Docker image for your plugin see Docker.

List of OCS Plugins

Here is a list of known OCS plugins. If you have written an OCS plugin, and would like to include it in this list, we encourage you to submit a PR adding it here.

  • socs - The Simons Observatory OCS plugin