Skip to content

Conversation

@bekiralti
Copy link
Contributor

Integrates the existing load_config method from the villas-node
library into VILLASnodeManager to enable configuration loading
via RabbitMQ messages.

Example

Example (tx.py) Python Code to send messages to villas-controller via RabbitMQ:

import argparse
import json
import kombu

# CLI
parser = argparse.ArgumentParser()
parser.add_argument("action", type=str)
parser.add_argument("config", type=str, nargs="?", default=None)
args = parser.parse_args()

# Broker connection
connection = kombu.Connection("amqp://guest:guest@localhost/%2F")
exchange = kombu.Exchange(name="villas", type="headers", durable=True)
producer = connection.Producer()

# Message
payload = {"action": args.action}
if args.config:
    with open(args.config, "r", encoding="utf-8") as f:
        config = json.load(f)
    payload["config"] = config
producer.publish(payload, exchange=exchange, headers={"type": "villas-node"})

Minimal (example_ctl.json) configuration for villas-controller:

{
  "broker": {
    "url": "amqp://guest:guest@localhost/%2F"
  },
  "components": [
    {
      "category": "manager",
      "type": "villas-node"
    }
  ]
}

Minimal (example_node.json) configuration to sent via RabbitMQ to villas-controller, then villas-controller reloads the running villas-node with this configuration.

{
  "nodes": {
    "my_sig": {
      "type": "signal.v2",
      "rate": 1,
      "in": {
        "signals": [
          {
            "signal": "constant",
            "amplitude": 1
          }
        ]
      }
    }
  },
  "paths": [
    {
      "in": "my_sig",
      "hooks": [
        {
          "type": "print"
        }
      ]
    }
  ]
}
  1. Start RabbitMQ: docker run -p 5672:5672 -p 15672:15672 -d rabbitmq:management
  2. Start villas-node: villas-node
  3. Start villas-controller: villas-controller -c example_ctl.json -d DEBUG daemon
  4. Send example_node.json: python tx.py load_config example_node.json

Signed-off-by: Bekir Altindal <bekir.altindal@rwth-aachen.de>
@stv0g
Copy link
Contributor

stv0g commented Jan 5, 2026

Hi @bekiralti,

I am wondering, isnt this already handled by the start action?

One of the design goals of VILLAScontroller has been to harmonize control and configuration of different components via a common set of control actions (start, stop, pause, resume, ...).

Hence, if possible, I would argue we should try to avoid introducing any new actions targeted at single component types and instead try to generalize.

The reasoning behind this is, also that the VILLASweb interface can currently only send this standard control actions. Adding support for new ones, will require a lot of custom code for the web-interface. And I am not sure if we really want to do this for every type of component.

@bekiralti
Copy link
Contributor Author

bekiralti commented Jan 5, 2026

Hi @stv0g,

thanks for your reply! Yeah, that is quite troublesome. For now, I would like to try and clarify my intentions and thought process.

While experimenting with VILLASnodeManager, a few questions and observations came up:

  • In VILLASnodeManager.__init__, there is a line like self._status = self.node.status. This sends a request to the VILLASnode HTTP API and therefore assumes that a villas node process is already running and listening on a port (for example http://localhost:8080). If no process is running, this call results in an urllib.error.URLError in VILLAScontroller.
  • In order to avoid the above error, a villas node process can be started manually before villas controller, but I have not found a way to let VILLAScontroller reconfigure this manually started villas node process.
  • The villas-node Python module exposes a load_config method, which can be used to restart a running villas node instance with a new configuration, but it does not seem to be used at the moment, neither in the villas-node Python module itself nor in the VILLAScontroller code.
  • My intention with the PR was to reuse this existing load_config mechanism in order to reconfigure an already running villas node instance.

To better understand the current behavior, I tried the following:

  1. Start villas node manually without a config.
  2. Start villas controller with a configuration that creates a VILLASnodeManager component and passes a config_filename to the corresponding Node object.
  3. Send {"action": "start"} to this VILLASnodeManager. This successfully starts a second villas node process that uses the configuration specified via config_filename.
  4. This works, but the first, manually started villas node process stays running and unused.

This left me a bit unsure what the intended model for VILLAScontroller is in the case of VILLASnode:

  • Is VILLAScontroller supposed to manage an already running villas node instance or
  • is VILLAScontroller supposed to spawn new villas node instances with corresponding configurations?

It is quite possible that I am missing something obvious, and a short clarification would help me to better align future PRs with the intended behaviour. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants