Repository: eclipse-bluechi/bluechi (language: python)

Issue:
Rename occurrences of Manager to Controller
The usage of `Manager` to describe the controlling component of BlueChi should be avoided. Therefore, all occurrences of `Manager` should be exchanged with `Controller`. For this issue, the focus should be on documentation, configuration and all other API-related changes that cause a breaking change. This includes:
- descriptions of configurations: `bluechi/config`
- documentation: `bluechi/doc/docs`
- API changes: `bluechi/data` 
   - renaming the interfaces for `org.eclipse.bluechi.Manager`
   - re-generating the python bindings
- ...


Discussion / hints:

Fix patch:
diff --git a/README.developer.md b/README.developer.md
index 868ab6c238..dd84664aba 100644
--- a/README.developer.md
+++ b/README.developer.md
@@ -72,7 +72,7 @@ of installation for your setup.
          /org/eclipse/bluechi
 
 NAME                                TYPE      SIGNATURE RESULT/VALUE   FLAGS
-org.eclipse.bluechi.Manager         interface -         -              -
+org.eclipse.bluechi.Controller         interface -         -              -
 .CreateMonitor                      method    -         o              -
 .DisableMetrics                     method    -         -              -
 .EnableMetrics                      method    -         -              -
@@ -100,7 +100,7 @@ org.freedesktop.DBus.Properties     interface -         -              -
 ```bash
 export SERVICE="org.eclipse.bluechi"
 export OBJECT="/org/eclipse/bluechi"
-export INTERFACE="org.eclipse.bluechi.Manager"
+export INTERFACE="org.eclipse.bluechi.Controller"
 export METHOD="ListNodes"
 
 # busctl call \
diff --git a/bluechi.spec.in b/bluechi.spec.in
index 01c3c25f5d..02f0311b81 100644
--- a/bluechi.spec.in
+++ b/bluechi.spec.in
@@ -68,7 +68,7 @@ This package contains the controller service.
 %license LICENSE
 %{_libexecdir}/bluechi-controller
 %{_datadir}/dbus-1/interfaces/org.eclipse.bluechi.Job.xml
-%{_datadir}/dbus-1/interfaces/org.eclipse.bluechi.Manager.xml
+%{_datadir}/dbus-1/interfaces/org.eclipse.bluechi.Controller.xml
 %{_datadir}/dbus-1/interfaces/org.eclipse.bluechi.Monitor.xml
 %{_datadir}/dbus-1/interfaces/org.eclipse.bluechi.Node.xml
 %{_datadir}/dbus-1/system.d/org.eclipse.bluechi.conf
diff --git a/config/agent/agent.conf b/config/agent/agent.conf
index e826bbbbbc..b98dbdad63 100644
--- a/config/agent/agent.conf
+++ b/config/agent/agent.conf
@@ -11,12 +11,12 @@
 #NodeName=
 
 #
-# The IP address that bluechi-agent can use to connect to bluechi manager. It must be a valid IPv4 or IPv6 address.
+# The IP address that bluechi-agent can use to connect to bluechi-controller. It must be a valid IPv4 or IPv6 address.
 # One of the ControllerHost or ControllerAddress options must be set for each bluechi-agent.
 #ControllerHost=
 
 #
-# The port the manager listens on to establish connections with the bluechi agents.
+# The port the controller listens on to establish connections with the bluechi agents.
 #ControllerPort=842
 
 #
diff --git a/config/controller/controller.conf b/config/controller/controller.conf
index da2e616dd7..707151822a 100644
--- a/config/controller/controller.conf
+++ b/config/controller/controller.conf
@@ -6,14 +6,14 @@
 [bluechi-controller]
 
 #
-# A comma separated list of unique bluechi-agent names. Only nodes with names mentioned in the list can connect to bluechi
-# manager. These names are defined in the agent's configuration file under the `NodeName` option.
+# A comma separated list of unique bluechi-agent names. Only nodes with names mentioned in the list can connect to
+# bluechi-controller. These names are defined in the agent's configuration file under the `NodeName` option.
 # (see `bluechi-agent.conf(5)`).
 # Note: The maximum line length is 500 characters. If the list exceeds this, use multiple, indented lines.
 #AllowedNodeNames=
 
 #
-# The port the manager listens on to establish connections with the bluechi agents.
+# The port the controller listens on to establish connections with the bluechi agents.
 #ControllerPort=842
 
 #
diff --git a/data/meson.build b/data/meson.build
index 5b1dde2625..e621f89076 100644
--- a/data/meson.build
+++ b/data/meson.build
@@ -4,7 +4,7 @@
 install_data(
     [
         'org.eclipse.bluechi.Job.xml',
-        'org.eclipse.bluechi.Manager.xml',
+        'org.eclipse.bluechi.Controller.xml',
         'org.eclipse.bluechi.Monitor.xml',
         'org.eclipse.bluechi.Node.xml',
         'org.eclipse.bluechi.Agent.xml'
diff --git a/data/org.eclipse.bluechi.Manager.xml b/data/org.eclipse.bluechi.Controller.xml
similarity index 97%
rename from data/org.eclipse.bluechi.Manager.xml
rename to data/org.eclipse.bluechi.Controller.xml
index cc1e8670c7..02946266fe 100644
--- a/data/org.eclipse.bluechi.Manager.xml
+++ b/data/org.eclipse.bluechi.Controller.xml
@@ -3,12 +3,12 @@
 <node>
 
   <!-- 
-    org.eclipse.bluechi.Manager:
+    org.eclipse.bluechi.Controller:
     @short_description: Public interface of BlueChi on the managing node providing methods and signals for all nodes.
 
     This interface can be used to get information about all nodes and their units, create monitors and listen for job signals.
   -->
-  <interface name="org.eclipse.bluechi.Manager">
+  <interface name="org.eclipse.bluechi.Controller">
 
     <!-- 
       ListUnits:
@@ -84,7 +84,7 @@
       SetLogLevel:
       @loglevel: The new loglevel to use. 
 
-      Change the loglevel of the manager.
+      Change the loglevel of the controller.
     -->
     <method name="SetLogLevel">
       <arg name="loglevel" type="s" direction="in" />
diff --git a/data/org.eclipse.bluechi.Metrics.xml b/data/org.eclipse.bluechi.Metrics.xml
index b8a0f9ed0e..b08a420eb4 100644
--- a/data/org.eclipse.bluechi.Metrics.xml
+++ b/data/org.eclipse.bluechi.Metrics.xml
@@ -6,7 +6,7 @@
     org.eclipse.bluechi.Metrics:
     @short_description: Public interface of BlueChi on the managing node providing signals for performance metrics.
 
-    This interface is only available if the metrics have been enabled before via the Manager interface.
+    This interface is only available if the metrics have been enabled before via the Controller interface.
   -->
   <interface name="org.eclipse.bluechi.Metrics">
 
diff --git a/data/org.eclipse.bluechi.Monitor.xml b/data/org.eclipse.bluechi.Monitor.xml
index 54b77e9401..737e414fb5 100644
--- a/data/org.eclipse.bluechi.Monitor.xml
+++ b/data/org.eclipse.bluechi.Monitor.xml
@@ -6,7 +6,7 @@
     org.eclipse.bluechi.Monitor:
     @short_description: Public interface of BlueChi on the managing node providing monitoring functionality.
 
-    This interface is only available if a monitor has been created before via the Manager interface.
+    This interface is only available if a monitor has been created before via the Controller interface.
     It provides methods to subscribe to changes in systemd units on managed nodes as well as signals for those changes.
   -->
   <interface name="org.eclipse.bluechi.Monitor">
diff --git a/data/org.eclipse.bluechi.Node.xml b/data/org.eclipse.bluechi.Node.xml
index 357b5f2ad4..241c020437 100644
--- a/data/org.eclipse.bluechi.Node.xml
+++ b/data/org.eclipse.bluechi.Node.xml
@@ -21,7 +21,7 @@
     fails if mode is fail.
 
       The job returned is an object path for an object implementing org.eclipse.bluechi.Job, and which be monitored for the progress of the job, or used
-    to cancel the job. To track the result of the job, follow the JobRemoved signal on the Manager.
+    to cancel the job. To track the result of the job, follow the JobRemoved signal on the Controller.
     -->
     <method name="StartUnit">
       <arg name="name" type="s" direction="in" />
@@ -205,7 +205,7 @@
       SetLogLevel:
       @loglevel: The new loglevel to use. 
 
-      Change the loglevel of the manager.
+      Change the loglevel of the controller.
     -->
     <method name="SetLogLevel">
       <arg name="level" type="s" direction="in" />
diff --git a/data/org.eclipse.bluechi.internal.Manager.xml b/data/org.eclipse.bluechi.internal.Controller.xml
similarity index 83%
rename from data/org.eclipse.bluechi.internal.Manager.xml
rename to data/org.eclipse.bluechi.internal.Controller.xml
index 8c593b3919..858b4aa998 100644
--- a/data/org.eclipse.bluechi.internal.Manager.xml
+++ b/data/org.eclipse.bluechi.internal.Controller.xml
@@ -1,7 +1,7 @@
 <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
 <!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
 <node>
-  <interface name="org.eclipse.bluechi.internal.Manager">
+  <interface name="org.eclipse.bluechi.internal.Controller">
     <method name="Register">
       <arg name="name" type="s" direction="in" />
     </method>
diff --git a/doc/api-examples/c/list-nodes.c b/doc/api-examples/c/list-nodes.c
index 89ab0ad8d9..204c271813 100644
--- a/doc/api-examples/c/list-nodes.c
+++ b/doc/api-examples/c/list-nodes.c
@@ -20,7 +20,7 @@ int main() {
                         bus,
                         "org.eclipse.bluechi",
                         "/org/eclipse/bluechi",
-                        "org.eclipse.bluechi.Manager",
+                        "org.eclipse.bluechi.Controller",
                         "ListNodes",
                         &error,
                         &result,
diff --git a/doc/api-examples/c/start-unit.c b/doc/api-examples/c/start-unit.c
index 36fd63d7d2..5b6b1e487f 100644
--- a/doc/api-examples/c/start-unit.c
+++ b/doc/api-examples/c/start-unit.c
@@ -12,7 +12,7 @@ static int get_node_path(sd_bus *bus, char *node_name, char **ret_node_path) {
                         bus,
                         "org.eclipse.bluechi",
                         "/org/eclipse/bluechi",
-                        "org.eclipse.bluechi.Manager",
+                        "org.eclipse.bluechi.Controller",
                         "GetNode",
                         &error,
                         &result,
diff --git a/doc/api-examples/go/enable-unit.go b/doc/api-examples/go/enable-unit.go
index 57cee17b4c..4b2393ea95 100644
--- a/doc/api-examples/go/enable-unit.go
+++ b/doc/api-examples/go/enable-unit.go
@@ -12,7 +12,7 @@ import (
 const (
 	BcDusInterface        = "org.eclipse.bluechi"
 	BcObjectPath          = "/org/eclipse/bluechi"
-	MethodGetNode         = "org.eclipse.bluechi.Manager.GetNode"
+	MethodGetNode         = "org.eclipse.bluechi.Controller.GetNode"
 	MethodEnableUnitFiles = "org.eclipse.bluechi.Node.EnableUnitFiles"
 )
 
diff --git a/doc/api-examples/go/get-cpuweight.go b/doc/api-examples/go/get-cpuweight.go
index a3eb8a3262..6c17a703ed 100644
--- a/doc/api-examples/go/get-cpuweight.go
+++ b/doc/api-examples/go/get-cpuweight.go
@@ -12,7 +12,7 @@ import (
 const (
 	BcDusInterface        = "org.eclipse.bluechi"
 	BcObjectPath          = "/org/eclipse/bluechi"
-	MethodGetNode         = "org.eclipse.bluechi.Manager.GetNode"
+	MethodGetNode         = "org.eclipse.bluechi.Controller.GetNode"
 	MethodGetUnitProperty = "org.eclipse.bluechi.Node.GetUnitProperty"
 )
 
diff --git a/doc/api-examples/go/list-node-units.go b/doc/api-examples/go/list-node-units.go
index 6c2d461513..8b5c37d2b3 100644
--- a/doc/api-examples/go/list-node-units.go
+++ b/doc/api-examples/go/list-node-units.go
@@ -12,7 +12,7 @@ import (
 const (
 	BcDusInterface  = "org.eclipse.bluechi"
 	BcObjectPath    = "/org/eclipse/bluechi"
-	MethodGetNode   = "org.eclipse.bluechi.Manager.GetNode"
+	MethodGetNode   = "org.eclipse.bluechi.Controller.GetNode"
 	MethodListUnits = "org.eclipse.bluechi.Node.ListUnits"
 )
 
diff --git a/doc/api-examples/go/list-nodes.go b/doc/api-examples/go/list-nodes.go
index 26a77e8289..45b4014d07 100644
--- a/doc/api-examples/go/list-nodes.go
+++ b/doc/api-examples/go/list-nodes.go
@@ -12,7 +12,7 @@ import (
 const (
 	BcDusInterface  = "org.eclipse.bluechi"
 	BcObjectPath    = "/org/eclipse/bluechi"
-	MethodListNodes = "org.eclipse.bluechi.Manager.ListNodes"
+	MethodListNodes = "org.eclipse.bluechi.Controller.ListNodes"
 )
 
 func main() {
diff --git a/doc/api-examples/go/monitor-system-status.go b/doc/api-examples/go/monitor-system-status.go
index fb61c99acb..e6f1006fff 100644
--- a/doc/api-examples/go/monitor-system-status.go
+++ b/doc/api-examples/go/monitor-system-status.go
@@ -10,9 +10,9 @@ import (
 )
 
 const (
-	BcDusInterface     = "org.eclipse.bluechi"
-	BcObjectPath       = "/org/eclipse/bluechi"
-	BcManagerInterface = "org.eclipse.bluechi.Manager"
+	BcDusInterface        = "org.eclipse.bluechi"
+	BcObjectPath          = "/org/eclipse/bluechi"
+	BcControllerInterface = "org.eclipse.bluechi.Controller"
 )
 
 func main() {
@@ -34,7 +34,7 @@ func main() {
 	conn.Signal(c)
 	for v := range c {
 		ifaceName := v.Body[0]
-		if ifaceName == BcManagerInterface {
+		if ifaceName == BcControllerInterface {
 			changedValues, ok := v.Body[1].(map[string]dbus.Variant)
 			if !ok {
 				fmt.Println("Received invalid property changed signal")
diff --git a/doc/api-examples/go/monitor-unit.go b/doc/api-examples/go/monitor-unit.go
index 44f81849d6..9095d32c8b 100644
--- a/doc/api-examples/go/monitor-unit.go
+++ b/doc/api-examples/go/monitor-unit.go
@@ -13,7 +13,7 @@ import (
 const (
 	BcDusInterface      = "org.eclipse.bluechi"
 	BcObjectPath        = "/org/eclipse/bluechi"
-	MethodCreateMonitor = "org.eclipse.bluechi.Manager.CreateMonitor"
+	MethodCreateMonitor = "org.eclipse.bluechi.Controller.CreateMonitor"
 	MethodSubscribe     = "org.eclipse.bluechi.Monitor.Subscribe"
 
 	SignalUnitNew               = "UnitNew"
diff --git a/doc/api-examples/go/set-cpuweight.go b/doc/api-examples/go/set-cpuweight.go
index 5b5ccba7c9..8f335bfed8 100644
--- a/doc/api-examples/go/set-cpuweight.go
+++ b/doc/api-examples/go/set-cpuweight.go
@@ -13,7 +13,7 @@ import (
 const (
 	BcDusInterface          = "org.eclipse.bluechi"
 	BcObjectPath            = "/org/eclipse/bluechi"
-	MethodGetNode           = "org.eclipse.bluechi.Manager.GetNode"
+	MethodGetNode           = "org.eclipse.bluechi.Controller.GetNode"
 	MethodSetUnitProperties = "org.eclipse.bluechi.Node.SetUnitProperties"
 )
 
diff --git a/doc/api-examples/go/start-unit.go b/doc/api-examples/go/start-unit.go
index 25153f2b96..c05e345897 100644
--- a/doc/api-examples/go/start-unit.go
+++ b/doc/api-examples/go/start-unit.go
@@ -12,7 +12,7 @@ import (
 const (
 	BcDusInterface  = "org.eclipse.bluechi"
 	BcObjectPath    = "/org/eclipse/bluechi"
-	MethodGetNode   = "org.eclipse.bluechi.Manager.GetNode"
+	MethodGetNode   = "org.eclipse.bluechi.Controller.GetNode"
 	MethodStartUnit = "org.eclipse.bluechi.Node.StartUnit"
 )
 
diff --git a/doc/api-examples/python/enable-unit.py b/doc/api-examples/python/enable-unit.py
index 217da06c48..c1f2cdece2 100644
--- a/doc/api-examples/python/enable-unit.py
+++ b/doc/api-examples/python/enable-unit.py
@@ -15,8 +15,8 @@
 
 node_name = sys.argv[1]
 
-manager = bus.get_proxy("org.eclipse.bluechi", "/org/eclipse/bluechi")
-node_path = manager.GetNode(node_name)
+controller = bus.get_proxy("org.eclipse.bluechi", "/org/eclipse/bluechi")
+node_path = controller.GetNode(node_name)
 node = bus.get_proxy("org.eclipse.bluechi", node_path)
 
 response = node.EnableUnitFiles(sys.argv[2:], False, False)
diff --git a/doc/api-examples/python/get-cpuweight.py b/doc/api-examples/python/get-cpuweight.py
index 94dca3c4d3..6ac0ef7ef3 100644
--- a/doc/api-examples/python/get-cpuweight.py
+++ b/doc/api-examples/python/get-cpuweight.py
@@ -12,8 +12,8 @@
 node_name = sys.argv[1]
 unit_name = sys.argv[2]
 
-manager = bus.get_proxy("org.eclipse.bluechi", "/org/eclipse/bluechi")
-node_path = manager.GetNode(node_name)
+controller = bus.get_proxy("org.eclipse.bluechi", "/org/eclipse/bluechi")
+node_path = controller.GetNode(node_name)
 node = bus.get_proxy("org.eclipse.bluechi", node_path)
 
 value = node.GetUnitProperty(unit_name, "org.freedesktop.systemd1.Service", "CPUWeight")
diff --git a/doc/api-examples/python/get-unit-properties.py b/doc/api-examples/python/get-unit-properties.py
index 06cad60678..15a19e6404 100644
--- a/doc/api-examples/python/get-unit-properties.py
+++ b/doc/api-examples/python/get-unit-properties.py
@@ -13,8 +13,8 @@
 node_name = sys.argv[1]
 unit_name = sys.argv[2]
 
-manager = bus.get_proxy("org.eclipse.bluechi", "/org/eclipse/bluechi")
-node_path = manager.GetNode(node_name)
+controller = bus.get_proxy("org.eclipse.bluechi", "/org/eclipse/bluechi")
+node_path = controller.GetNode(node_name)
 node = bus.get_proxy("org.eclipse.bluechi", node_path)
 
 properties = node.GetUnitProperties(unit_name, "org.freedesktop.systemd1.Unit")
diff --git a/doc/api-examples/python/get-unit-property.py b/doc/api-examples/python/get-unit-property.py
index 316eae0980..82336bef6f 100644
--- a/doc/api-examples/python/get-unit-property.py
+++ b/doc/api-examples/python/get-unit-property.py
@@ -15,8 +15,8 @@
 iface_name = sys.argv[3]
 property_name = sys.argv[4]
 
-manager = bus.get_proxy("org.eclipse.bluechi", "/org/eclipse/bluechi")
-node_path = manager.GetNode(node_name)
+controller = bus.get_proxy("org.eclipse.bluechi", "/org/eclipse/bluechi")
+node_path = controller.GetNode(node_name)
 node = bus.get_proxy("org.eclipse.bluechi", node_path)
 
 val = node.GetUnitProperty(unit_name, iface_name, property_name)
diff --git a/doc/api-examples/python/list-active-services.py b/doc/api-examples/python/list-active-services.py
index 4ec1628459..f74ce436b9 100644
--- a/doc/api-examples/python/list-active-services.py
+++ b/doc/api-examples/python/list-active-services.py
@@ -9,8 +9,8 @@
                                            "description", "load_state", "active_state", "sub_state", "follower",
                                            "object_path", "job_id", "job_type", "job_object_path"])
 
-manager = bus.get_proxy("org.eclipse.bluechi",  "/org/eclipse/bluechi")
-units = manager.ListUnits()
+controller = bus.get_proxy("org.eclipse.bluechi",  "/org/eclipse/bluechi")
+units = controller.ListUnits()
 for u in units:
     info = NodeUnitInfo(*u)
     if info.active_state == "active" and info.name.endswith(".service"):
diff --git a/doc/api-examples/python/list-node-units.py b/doc/api-examples/python/list-node-units.py
index ce90d8f0f0..8a73c886a6 100644
--- a/doc/api-examples/python/list-node-units.py
+++ b/doc/api-examples/python/list-node-units.py
@@ -16,8 +16,8 @@
 
 node_name = sys.argv[1]
 
-manager = bus.get_proxy("org.eclipse.bluechi", "/org/eclipse/bluechi")
-node_path = manager.GetNode(node_name)
+controller = bus.get_proxy("org.eclipse.bluechi", "/org/eclipse/bluechi")
+node_path = controller.GetNode(node_name)
 node = bus.get_proxy("org.eclipse.bluechi", node_path)
 
 units = node.ListUnits()
diff --git a/doc/api-examples/python/list-nodes.py b/doc/api-examples/python/list-nodes.py
index ea8cae3f21..218fb68c4c 100644
--- a/doc/api-examples/python/list-nodes.py
+++ b/doc/api-examples/python/list-nodes.py
@@ -8,8 +8,8 @@
 
 NodeInfo = namedtuple("NodeInfo", ["name", "object_path", "status"])
 
-manager = bus.get_proxy("org.eclipse.bluechi", "/org/eclipse/bluechi")
-nodes = manager.ListNodes()
+controller = bus.get_proxy("org.eclipse.bluechi", "/org/eclipse/bluechi")
+nodes = controller.ListNodes()
 for n in nodes:
     info = NodeInfo(*n)
     print(f"Node: {info.name}, State: {info.status}")
diff --git a/doc/api-examples/python/monitor-node-connections.py b/doc/api-examples/python/monitor-node-connections.py
index d150978c37..a8331c334e 100644
--- a/doc/api-examples/python/monitor-node-connections.py
+++ b/doc/api-examples/python/monitor-node-connections.py
@@ -9,8 +9,8 @@
 loop = EventLoop()
 bus = dasbus.connection.SystemMessageBus()
 
-manager = bus.get_proxy("org.eclipse.bluechi", "/org/eclipse/bluechi")
-nodes = manager.ListNodes()
+controller = bus.get_proxy("org.eclipse.bluechi", "/org/eclipse/bluechi")
+nodes = controller.ListNodes()
 cached_nodes = []
 for n in nodes:
     # node: [name, path, status]
diff --git a/doc/api-examples/python/monitor-unit.py b/doc/api-examples/python/monitor-unit.py
index 12f3589a91..b3c6c397aa 100644
--- a/doc/api-examples/python/monitor-unit.py
+++ b/doc/api-examples/python/monitor-unit.py
@@ -30,9 +30,9 @@ def print_dict_changes(old, new):
 
 bus = dasbus.connection.SystemMessageBus()
 
-manager = bus.get_proxy("org.eclipse.bluechi", "/org/eclipse/bluechi")
+controller = bus.get_proxy("org.eclipse.bluechi", "/org/eclipse/bluechi")
 
-monitor_path = manager.CreateMonitor()
+monitor_path = controller.CreateMonitor()
 monitor = bus.get_proxy("org.eclipse.bluechi", monitor_path)
 
 old_values = {}
diff --git a/doc/api-examples/python/set-cpuweight.py b/doc/api-examples/python/set-cpuweight.py
index e35f1c0132..92c1e9190c 100644
--- a/doc/api-examples/python/set-cpuweight.py
+++ b/doc/api-examples/python/set-cpuweight.py
@@ -17,8 +17,8 @@
 # Don't persist change
 runtime = True
 
-manager = bus.get_proxy("org.eclipse.bluechi", "/org/eclipse/bluechi")
-node_path = manager.GetNode(node_name)
+controller = bus.get_proxy("org.eclipse.bluechi", "/org/eclipse/bluechi")
+node_path = controller.GetNode(node_name)
 node = bus.get_proxy("org.eclipse.bluechi", node_path)
 
 node.SetUnitProperties(unit_name, runtime, [("CPUWeight", Variant("t", value))])
diff --git a/doc/api-examples/python/start-unit.py b/doc/api-examples/python/start-unit.py
index 87af7c4ffa..d6e33c5c53 100644
--- a/doc/api-examples/python/start-unit.py
+++ b/doc/api-examples/python/start-unit.py
@@ -13,8 +13,8 @@
 node_name = sys.argv[1]
 unit_name = sys.argv[2]
 
-manager = bus.get_proxy("org.eclipse.bluechi", "/org/eclipse/bluechi")
-node_path = manager.GetNode(node_name)
+controller = bus.get_proxy("org.eclipse.bluechi", "/org/eclipse/bluechi")
+node_path = controller.GetNode(node_name)
 node = bus.get_proxy("org.eclipse.bluechi", node_path)
 
 my_job_path = node.StartUnit(unit_name, "replace")
diff --git a/doc/api-examples/rust/enable-unit.rs b/doc/api-examples/rust/enable-unit.rs
index 203d5da75e..1a60bc8753 100644
--- a/doc/api-examples/rust/enable-unit.rs
+++ b/doc/api-examples/rust/enable-unit.rs
@@ -28,7 +28,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
     );
 
     let (node,): (Path,) =
-        bluechi.method_call("org.eclipse.bluechi.Manager", "GetNode", (args.node_name,))?;
+        bluechi.method_call("org.eclipse.bluechi.Controller", "GetNode", (args.node_name,))?;
 
     let node_proxy = conn.with_proxy("org.eclipse.bluechi", node, Duration::from_millis(5000));
 
diff --git a/doc/api-examples/rust/get-cpuweight.rs b/doc/api-examples/rust/get-cpuweight.rs
index 859620bbf7..37651a55ac 100644
--- a/doc/api-examples/rust/get-cpuweight.rs
+++ b/doc/api-examples/rust/get-cpuweight.rs
@@ -29,7 +29,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
     );
 
     let (node,): (Path,) =
-        bluechi.method_call("org.eclipse.bluechi.Manager", "GetNode", (args.node_name,))?;
+        bluechi.method_call("org.eclipse.bluechi.Controller", "GetNode", (args.node_name,))?;
 
     let node_proxy = conn.with_proxy("org.eclipse.bluechi", node, Duration::from_millis(5000));
 
diff --git a/doc/api-examples/rust/list-node-units.rs b/doc/api-examples/rust/list-node-units.rs
index 982faab242..b3d2c5a5a2 100644
--- a/doc/api-examples/rust/list-node-units.rs
+++ b/doc/api-examples/rust/list-node-units.rs
@@ -24,7 +24,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
     );
 
     let (node,): (Path,) =
-        bluechi.method_call("org.eclipse.bluechi.Manager", "GetNode", (args.node_name,))?;
+        bluechi.method_call("org.eclipse.bluechi.Controller", "GetNode", (args.node_name,))?;
 
     let node_proxy = conn.with_proxy("org.eclipse.bluechi", node, Duration::from_millis(5000));
 
diff --git a/doc/api-examples/rust/list-nodes.rs b/doc/api-examples/rust/list-nodes.rs
index f0905fd712..d7e8abe94e 100644
--- a/doc/api-examples/rust/list-nodes.rs
+++ b/doc/api-examples/rust/list-nodes.rs
@@ -13,7 +13,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
     );
 
     let (nodes,): (Vec<(String, dbus::Path, String)>,) =
-        bluechi.method_call("org.eclipse.bluechi.Manager", "ListNodes", ())?;
+        bluechi.method_call("org.eclipse.bluechi.Controller", "ListNodes", ())?;
 
     for (name, _, status) in nodes {
         println!("Node: {}, Status: {}", name, status);
diff --git a/doc/api-examples/rust/monitor-node-connections.rs b/doc/api-examples/rust/monitor-node-connections.rs
index 6fac6dfb6d..e8be82c6f5 100644
--- a/doc/api-examples/rust/monitor-node-connections.rs
+++ b/doc/api-examples/rust/monitor-node-connections.rs
@@ -17,7 +17,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
     );
 
     let (nodes,): (Vec<(String, dbus::Path, String)>,) =
-        bluechi.method_call("org.eclipse.bluechi.Manager", "ListNodes", ())?;
+        bluechi.method_call("org.eclipse.bluechi.Controller", "ListNodes", ())?;
 
     for (name, path, _) in nodes {
         let node_name = name;
diff --git a/doc/api-examples/rust/monitor-unit.rs b/doc/api-examples/rust/monitor-unit.rs
index 2277b4d483..8ce6108259 100644
--- a/doc/api-examples/rust/monitor-unit.rs
+++ b/doc/api-examples/rust/monitor-unit.rs
@@ -137,7 +137,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
     );
 
     let (monitor,): (Path,) =
-        bluechi.method_call("org.eclipse.bluechi.Manager", "CreateMonitor", ())?;
+        bluechi.method_call("org.eclipse.bluechi.Controller", "CreateMonitor", ())?;
     let monitor_proxy =
         conn.with_proxy("org.eclipse.bluechi", monitor, Duration::from_millis(5000));
 
diff --git a/doc/api-examples/rust/set-cpuweight.rs b/doc/api-examples/rust/set-cpuweight.rs
index 3244bb8078..999307cfcb 100644
--- a/doc/api-examples/rust/set-cpuweight.rs
+++ b/doc/api-examples/rust/set-cpuweight.rs
@@ -33,7 +33,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
     );
 
     let (node,): (Path,) =
-        bluechi.method_call("org.eclipse.bluechi.Manager", "GetNode", (args.node_name,))?;
+        bluechi.method_call("org.eclipse.bluechi.Controller", "GetNode", (args.node_name,))?;
 
     let node_proxy = conn.with_proxy("org.eclipse.bluechi", node, Duration::from_millis(5000));
 
diff --git a/doc/api-examples/rust/start-unit.rs b/doc/api-examples/rust/start-unit.rs
index 5e025ea5e2..62f99023a7 100644
--- a/doc/api-examples/rust/start-unit.rs
+++ b/doc/api-examples/rust/start-unit.rs
@@ -28,7 +28,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
     );
 
     let (node,): (Path,) =
-        bluechi.method_call("org.eclipse.bluechi.Manager", "GetNode", (&args.node_name,))?;
+        bluechi.method_call("org.eclipse.bluechi.Controller", "GetNode", (&args.node_name,))?;
 
     let node_proxy = conn.with_proxy("org.eclipse.bluechi", node, Duration::from_millis(5000));
 
diff --git a/doc/bluechi-examples/ListActiveServices.py b/doc/bluechi-examples/ListActiveServices.py
index 05d8190d24..fa20bdbd01 100755
--- a/doc/bluechi-examples/ListActiveServices.py
+++ b/doc/bluechi-examples/ListActiveServices.py
@@ -1,9 +1,9 @@
 #!/usr/bin/env python
 # SPDX-License-Identifier: MIT-0
 
-from bluechi.api import Manager
+from bluechi.api import Controller
 
-for unit in Manager().list_units():
+for unit in Controller().list_units():
     # unit[node, name, description, load_state, active_state, ...]
     if unit[4] == "active" and unit[1].endswith(".service"):
         print(f"Node: {unit[0]}, Unit: {unit[1]}")
diff --git a/doc/bluechi-examples/ListAllNodes.py b/doc/bluechi-examples/ListAllNodes.py
index 5efad40337..8274ac377a 100755
--- a/doc/bluechi-examples/ListAllNodes.py
+++ b/doc/bluechi-examples/ListAllNodes.py
@@ -1,8 +1,8 @@
 #!/usr/bin/env python
 # SPDX-License-Identifier: MIT-0
 
-from bluechi.api import Manager
+from bluechi.api import Controller
 
-for node in Manager().list_nodes():
+for node in Controller().list_nodes():
     # node[name, obj_path, status]
     print(f"Node: {node[0]}, State: {node[2]}")
diff --git a/doc/bluechi-examples/MonitorNodeConnections.py b/doc/bluechi-examples/MonitorNodeConnections.py
index ba8d389399..a94d011059 100644
--- a/doc/bluechi-examples/MonitorNodeConnections.py
+++ b/doc/bluechi-examples/MonitorNodeConnections.py
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: MIT-0
 
-from bluechi.api import Manager, Node
+from bluechi.api import Controller, Node
 from dasbus.loop import EventLoop
 from dasbus.typing import Variant
 
@@ -8,7 +8,7 @@
 loop = EventLoop()
 
 nodes = []
-for node in Manager().list_nodes():
+for node in Controller().list_nodes():
     n = Node(node[0])
 
     def changed_wrapper(node_name: str):
diff --git a/doc/bluechi-examples/MonitorSystemStatus.py b/doc/bluechi-examples/MonitorSystemStatus.py
index 2055b57bf1..4b872de37d 100644
--- a/doc/bluechi-examples/MonitorSystemStatus.py
+++ b/doc/bluechi-examples/MonitorSystemStatus.py
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: MIT-0
 
-from bluechi.api import Manager
+from bluechi.api import Controller
 from dasbus.loop import EventLoop
 from dasbus.typing import Variant
 
@@ -12,7 +12,7 @@ def on_system_status_changed(status: Variant):
 
 loop = EventLoop()
 
-mgr = Manager()
+mgr = Controller()
 mgr.on_status_changed(on_system_status_changed)
 
 loop.run()
diff --git a/doc/diagrams.drawio.xml b/doc/diagrams.drawio.xml
index b22410c199..b9a2162368 100644
--- a/doc/diagrams.drawio.xml
+++ b/doc/diagrams.drawio.xml
@@ -158,7 +158,7 @@
       <root>
         <mxCell id="0" />
         <mxCell id="1" parent="0" />
-        <mxCell id="cNh8NexcxSdfIfK-n4i8-1" value="Node - Manager" style="rounded=1;whiteSpace=wrap;html=1;arcSize=7;align=left;verticalAlign=top;spacingLeft=35;fontSize=20;fontStyle=4" parent="1" vertex="1">
+        <mxCell id="cNh8NexcxSdfIfK-n4i8-1" value="Node - Controller" style="rounded=1;whiteSpace=wrap;html=1;arcSize=7;align=left;verticalAlign=top;spacingLeft=35;fontSize=20;fontStyle=4" parent="1" vertex="1">
           <mxGeometry x="20" y="310" width="280" height="180" as="geometry" />
         </mxCell>
         <mxCell id="cNh8NexcxSdfIfK-n4i8-2" value="bluechi" style="rounded=0;whiteSpace=wrap;html=1;fontSize=18;" parent="1" vertex="1">
diff --git a/doc/docs/api/description.md b/doc/docs/api/description.md
index 777dcadb13..edadf23980 100644
--- a/doc/docs/api/description.md
+++ b/doc/docs/api/description.md
@@ -7,12 +7,12 @@ The interfaces described in this sections are referencing the [introspection dat
 
 ## BlueChi public D-Bus API
 
-The main entry point is at the `/org/eclipse/bluechi` object path and implements the `org.eclipse.bluechi.Manager`
+The main entry point is at the `/org/eclipse/bluechi` object path and implements the `org.eclipse.bluechi.Controller`
 interface.
 
 Note that some properties also come with change events, so you can easily track when they change.
 
-### interface org.eclipse.bluechi.Manager
+### interface org.eclipse.bluechi.Controller
 
 #### Methods
 
@@ -129,7 +129,7 @@ Object path: `/org/eclipse/bluechi/monitor/$id`
 ### interface org.eclipse.bluechi.Node
 
 Each node object represents a configured node in the system, independent of whether that node is connected to the
-manager or not, and the status can change over time.
+controller or not, and the status can change over time.
 
 Object path: `/org/eclipse/bluechi/node/$name`
 
@@ -143,7 +143,7 @@ Object path: `/org/eclipse/bluechi/node/$name`
 
     The job returned is an object path for an object implementing `org.eclipse.bluechi.Job`, and which be monitored for
     the progress of the job, or used to cancel the job. To track the result of the job, follow the `JobRemoved` signal
-    on the Manager.
+    on the Controller.
 
   * `StopUnit(in s name, in s mode, out o job)`
 
@@ -263,16 +263,16 @@ interface.
 
     Whenever a service on the agent requires a service on another node it creates a proxy service and calls this method.
     It then creates a new `org.eclipse.bluechi.internal.Proxy` object and emits the `ProxyNew` signal on the internal bus to
-    tell the manager about it. The manager will then try to arrange that the requested unit on the specified node is
+    tell the controller about it. The controller will then try to arrange that the requested unit on the specified node is
     running and notifies the initial agent about the status by calling `Ready` on the internal bus.
 
   * `RemoveProxy(in s service_name, in s node_name, in s unit_name)`
 
-    When a proxy is not needed anymore it is being removed on the node and a `ProxyRemoved` is emitted to notify the manager.
+    When a proxy is not needed anymore it is being removed on the node and a `ProxyRemoved` is emitted to notify the controller.
 
 ### interface org.eclipse.bluechi.Metrics
 
-This interface provides signals for collecting metrics. It is created by calling `EnableMetrics` on the `org.eclipse.bluechi.Manager` interface and removed by calling `DisableMetrics`.
+This interface provides signals for collecting metrics. It is created by calling `EnableMetrics` on the `org.eclipse.bluechi.Controller` interface and removed by calling `DisableMetrics`.
 
 #### Signals
 
@@ -287,13 +287,13 @@ This interface provides signals for collecting metrics. It is created by calling
 ## Internal D-Bus APIs
 
 The above APIs are the public facing ones that users of BlueChi would use. Additionally there are additional APIs that are
-used internally to synchronize between the manager and the nodes, and sometimes internally on a node. We here describe
+used internally to synchronize between the controller and the nodes, and sometimes internally on a node. We here describe
 these APIs.
 
-### interface org.eclipse.bluechi.internal.Manager
+### interface org.eclipse.bluechi.internal.Controller
 
-When a node connects to the manager it does so not via the public API, but via a direct peer-to-peer connection. On this
-connection the regular Manager API is not available, instead we're using internal Manager object as the basic data.
+When a node connects to the controller it does so not via the public API, but via a direct peer-to-peer connection. On this
+connection the regular Controller API is not available, instead we're using internal Controller object as the basic data.
 
 Object path: `/org/eclipse/bluechi/internal`
 
@@ -301,12 +301,12 @@ Object path: `/org/eclipse/bluechi/internal`
 
   * `Register(in st name)`
 
-    Before anything else can happen the node must call this method to register with the manager, giving its unique name.
-    If this succeeds, then the manager will consider the node online and start forwarding operations to it.
+    Before anything else can happen the node must call this method to register with the controller, giving its unique name.
+    If this succeeds, then the controller will consider the node online and start forwarding operations to it.
 
 ### interface org.eclipse.bluechi.internal.Agent
 
-This is the main interface that the node implements and that is used by the manager to affect change on the node.
+This is the main interface that the node implements and that is used by the controller to affect change on the node.
 
 #### Methods
 
@@ -324,11 +324,11 @@ This is the main interface that the node implements and that is used by the mana
 
     These are all API mirrors of the respective method in `org.eclipse.bluechi.Node`, and all they do is forward the
     same operation to the local systemd instance. Similarly, any changes in the systemd job will be forwarded to signals
-    on the node job which will then be forwarded to the manager job and reach the user.
+    on the node job which will then be forwarded to the controller job and reach the user.
 
   * `Subscribe(in unit s)`
 
-    Whenever some monitor object exists in the manager that matches a specific the node name and unit name, this method
+    Whenever some monitor object exists in the controller that matches a specific the node name and unit name, this method
     is called. This can happen either when a monitor is created or when a new node connects. Whenever *some*
     subscription is active, the node will call the systemd `Subscribed` method, and then register for `UnitNew`,
     `UnitRemoved` as well as for property change events on units. Any time a Unit changes it will emit the
@@ -366,11 +366,11 @@ This is the main interface that the node implements and that is used by the mana
 
   * `JobDone(u id, s result)`
 
-    Mirrors of the job signals in the manager and used to forward state changes from systemd to the manager.
+    Mirrors of the job signals in the controller and used to forward state changes from systemd to the controller.
 
   * `JobStateChanged(u id, s state)`
 
-    Forwards the job state property changes from systemd to the manager.
+    Forwards the job state property changes from systemd to the controller.
 
   * `UnitPropertiesChanged(s unit, s interface, a{sv} props)`
 
@@ -380,9 +380,9 @@ This is the main interface that the node implements and that is used by the mana
   * `ProxyNew(s node_name, s unit_name, o proxy)`
 
     Whenever a proxy service is running on the system with the node it calls into the node service, and the node service
-    creates a new `org.eclipse.bluechi.internal.Proxy` object and emits this signal to tell the manager about it. The manager
+    creates a new `org.eclipse.bluechi.internal.Proxy` object and emits this signal to tell the controller about it. The controller
     will notice this and try to arrange that the requested unit is running on the requested node. If the unit is already
-    running, when it is started, or when the start fails, the manager will call the `Ready()` method on it.
+    running, when it is started, or when the start fails, the controller will call the `Ready()` method on it.
 
   * `ProxyRemoved(s node_name, s unit_name)`
 
@@ -391,7 +391,7 @@ This is the main interface that the node implements and that is used by the mana
 
   * `Heartbeat()`
 
-    This is a periodic signal from the node to the manager.
+    This is a periodic signal from the node to the controller.
 
 ### interface org.eclipse.bluechi.internal.Proxy
 
@@ -402,13 +402,13 @@ with the proxy.
 
   * `Ready(in s result)`
 
-    Called by the manager when the corresponding service is active (either was running already, or was started), or when
+    Called by the controller when the corresponding service is active (either was running already, or was started), or when
     it failed. result is `done` if it was already running, otherwise it is the same value as the remote node returned in
     result from its start job.
 
 ### interface org.eclipse.bluechi.internal.Agent.Metrics
 
-This is the interface that provides signals sent from the agent to the manager to collect metrics, e.g. time measurements.
+This is the interface that provides signals sent from the agent to the controller to collect metrics, e.g. time measurements.
 
 #### Signals
 
diff --git a/doc/docs/cross_node_dependencies/proxy_services.md b/doc/docs/cross_node_dependencies/proxy_services.md
index 986ef2074c..b8acaed129 100644
--- a/doc/docs/cross_node_dependencies/proxy_services.md
+++ b/doc/docs/cross_node_dependencies/proxy_services.md
@@ -87,11 +87,11 @@ The dependency used for the dep service is `BindsTo` and `After`, which is a ver
 
 ## Implementation Details
 
-Tracking service state across multiple nodes is very tricky, as the state can diverge due to disconnects, delays, or races. To minimize such problems most state and intelligence is kept in the agent. Whenever the agent registers a new proxy it will announce this to the manager (if connected), and this will start a one-directional flow of non-interpreted state-change events from the target service to the manager to the agent, until the agent explicitly removes the proxy.
+Tracking service state across multiple nodes is very tricky, as the state can diverge due to disconnects, delays, or races. To minimize such problems most state and intelligence is kept in the agent. Whenever the agent registers a new proxy it will announce this to the controller (if connected), and this will start a one-directional flow of non-interpreted state-change events from the target service to the controller to the agent, until the agent explicitly removes the proxy.
 
-If an agent is disconnected from the manager, then the manager treats that as if the agent removed the proxy. On re-connection the agent will re-send the registering of the proxy.
+If an agent is disconnected from the controller, then the controller treats that as if the agent removed the proxy. On re-connection the agent will re-send the registering of the proxy.
 
-In addition to the monitoring, each time a proxy is registered the manager will tell the target node to start the dep service for the target service. BlueChi keeps track of how many proxies are outstanding for the target service and only tell the agent to stop the dep service when this reaches zero. Similar to the above, when the target node reconnect we re-sent starts for any outstanding proxies.
+In addition to the monitoring, each time a proxy is registered the controller will tell the target node to start the dep service for the target service. BlueChi keeps track of how many proxies are outstanding for the target service and only tell the agent to stop the dep service when this reaches zero. Similar to the above, when the target node reconnect we re-sent starts for any outstanding proxies.
 
 !!! Note
 
diff --git a/doc/docs/getting_started/cross_node_dependencies.md b/doc/docs/getting_started/cross_node_dependencies.md
index db3d576256..059e4fd083 100644
--- a/doc/docs/getting_started/cross_node_dependencies.md
+++ b/doc/docs/getting_started/cross_node_dependencies.md
@@ -34,7 +34,7 @@ Type=simple
 ExecStart=/usr/bin/python3 -m http.server 9000 --directory /tmp/bluechi-cdn/
 ```
 
-Reload the systemd manager configuration so it can find the newly created service:
+Reload the systemd controller configuration so it can find the newly created service:
 
 ```bash
 $ systemctl daemon-reload
diff --git a/doc/docs/getting_started/multi_node.md b/doc/docs/getting_started/multi_node.md
index b0ceb6569b..61326916c8 100644
--- a/doc/docs/getting_started/multi_node.md
+++ b/doc/docs/getting_started/multi_node.md
@@ -76,10 +76,10 @@ Once the services are up and running, the journald logs on the **laptop** should
 ```bash
 $ journalctl -u bluechi-controller
 
-Sep 14 14:51:58 laptop systemd[1]: Started BlueChi systemd service controller manager daemon.
-Sep 01 14:51:58 laptop bluechi[3750775]: 2023-09-14 14:51:58,685+0200 INFO        ../src/manager/manager.c:924 manager_start        msg="Starting bluechi 0.5.0"
-Sep 01 14:51:58 laptop bluechi[3750775]: 2023-09-14 14:51:58,928+0200 INFO        ../src/manager/node.c:870 node_method_register    msg="Registered managed node from fd 8 as 'laptop'"
-Sep 01 14:52:02 laptop bluechi[3750775]: 2023-09-14 14:52:02,534+0200 INFO        ../src/manager/node.c:870 node_method_register    msg="Registered managed node from fd 9 as 'pi'"
+Sep 14 14:51:58 laptop systemd[1]: Started BlueChi systemd service controller daemon.
+Sep 01 14:51:58 laptop bluechi[3750775]: 2023-09-14 14:51:58,685+0200 INFO        ../src/controller/controller.c:924 controller_start        msg="Starting bluechi 0.7.0"
+Sep 01 14:51:58 laptop bluechi[3750775]: 2023-09-14 14:51:58,928+0200 INFO        ../src/controller/node.c:870 node_method_register    msg="Registered managed node from fd 8 as 'laptop'"
+Sep 01 14:52:02 laptop bluechi[3750775]: 2023-09-14 14:52:02,534+0200 INFO        ../src/controller/node.c:870 node_method_register    msg="Registered managed node from fd 9 as 'pi'"
 ...
 ```
 
diff --git a/doc/docs/getting_started/securing_multi_node.md b/doc/docs/getting_started/securing_multi_node.md
index a937a735ad..605b5141d5 100644
--- a/doc/docs/getting_started/securing_multi_node.md
+++ b/doc/docs/getting_started/securing_multi_node.md
@@ -217,10 +217,10 @@ On the bluechi-agent machine, review the bluechi-agent journal logs:
 ```bash
 journalctl -u bluechi-agent.service
 
-Oct 31 08:53:46 bluechi systemd[1]: Started BlueChi systemd service controller agent daemon.
-Oct 31 08:53:46 bluechi bluechi-agent[16279]: Starting bluechi-agent 0.6.0
-Oct 31 08:53:46 bluechi bluechi-agent[16279]: Connecting to manager on unix:path=/var/lib/haproxy/bluechi-agent.sock
-Oct 31 08:53:46 bluechi bluechi-agent[16279]: Connected to manager as 'self'
+Oct 31 08:53:46 bluechi systemd[1]: Started BlueChi systemd service agent daemon.
+Oct 31 08:53:46 bluechi bluechi-agent[16279]: Starting bluechi-agent 0.7.0
+Oct 31 08:53:46 bluechi bluechi-agent[16279]: Connecting to controller on unix:path=/var/lib/haproxy/bluechi-agent.sock
+Oct 31 08:53:46 bluechi bluechi-agent[16279]: Connected to controller as 'self'
 ```
 
 #### bluechi-controller logs
@@ -231,7 +231,7 @@ On the bluechi-controller machine, review the bluechi journal logs:
 journalctl -u bluechi-controller.service
 
 Oct 31 08:53:46 bluechi systemd[1]: Started BlueChi Controller systemd service.
-Oct 31 08:53:46 bluechi bluechi-controller[16280]: Starting bluechi 0.6.0
+Oct 31 08:53:46 bluechi bluechi-controller[16280]: Starting bluechi 0.7.0
 Oct 31 08:53:46 bluechi bluechi-controller[16280]: Registered managed node from fd 9 as 'self'
 ```
 
diff --git a/doc/docs/getting_started/single_node.md b/doc/docs/getting_started/single_node.md
index f11bb7c80b..c36931ee3b 100644
--- a/doc/docs/getting_started/single_node.md
+++ b/doc/docs/getting_started/single_node.md
@@ -62,9 +62,9 @@ Once the services are up and running, the journald logs should show that the age
 ```bash
 $ journalctl -u bluechi
 
-Sep 14 14:51:58 laptop systemd[1]: Started BlueChi systemd service controller manager daemon.
-Sep 01 14:51:58 laptop bluechi[3750775]: 2023-09-14 14:51:58,685+0200 INFO        ../src/manager/manager.c:924 manager_start        msg="Starting bluechi 0.5.0"
-Sep 01 14:51:58 laptop bluechi[3750775]: 2023-09-14 14:51:58,928+0200 INFO        ../src/manager/node.c:870 node_method_register    msg="Registered managed node from fd 8 as 'laptop'"
+Sep 14 14:51:58 laptop systemd[1]: Started BlueChi systemd service controller daemon.
+Sep 01 14:51:58 laptop bluechi[3750775]: 2023-09-14 14:51:58,685+0200 INFO        ../src/controller/controller.c:924 controller_start        msg="Starting bluechi 0.7.0"
+Sep 01 14:51:58 laptop bluechi[3750775]: 2023-09-14 14:51:58,928+0200 INFO        ../src/controller/node.c:870 node_method_register    msg="Registered managed node from fd 8 as 'laptop'"
 ...
 ```
 
diff --git a/doc/docs/monitoring/peers.md b/doc/docs/monitoring/peers.md
index 51a086afb3..2ed98e6355 100644
--- a/doc/docs/monitoring/peers.md
+++ b/doc/docs/monitoring/peers.md
@@ -66,7 +66,7 @@ When checking the status of the unit or starting and stopping it now, `create-an
 
     ```python
     import sys
-    from bluechi.api import Manager, Monitor
+    from bluechi.api import Controller, Monitor
     from dasbus.loop import EventLoop
 
     if len(sys.argv) != 3:
@@ -78,7 +78,7 @@ When checking the status of the unit or starting and stopping it now, `create-an
 
     loop = EventLoop()
 
-    mgr = Manager()
+    mgr = Controller()
     monitor_path = mgr.create_monitor()
     print(f"Monitor path: {monitor_path}")
 
diff --git a/doc/man/bluechi-controller.1.md b/doc/man/bluechi-controller.1.md
index 7476ef9043..5b9f50f057 100644
--- a/doc/man/bluechi-controller.1.md
+++ b/doc/man/bluechi-controller.1.md
@@ -2,7 +2,7 @@
 
 ## NAME
 
-bluechi-controller - Manager of services across agents
+bluechi-controller - Controller of services across agents
 
 ## SYNOPSIS
 
diff --git a/doc/man/bluechi-controller.conf.5.md b/doc/man/bluechi-controller.conf.5.md
index 7d46237e6f..71eb47fb34 100644
--- a/doc/man/bluechi-controller.conf.5.md
+++ b/doc/man/bluechi-controller.conf.5.md
@@ -19,12 +19,12 @@ All fields to bootstrap the bluechi controller are contained in the **bluechi-co
 
 #### **ControllerPort** (uint16_t)
 
-The port the manager listens on to establish connections with the `bluechi-agent`. By default port `842` is used.
+The port the bluechi-controller listens on to establish connections with the `bluechi-agent`. By default port `842` is used.
 
 #### **AllowedNodeNames** (string)
 
 A comma separated list of unique bluechi-agent names. It's mandatory to set the option, only nodes with names mentioned
-in the list can connect to `bluechi` manager. These names are defined in the agent's configuration file under `NodeName`
+in the list can connect to `bluechi-controller'. These names are defined in the agent's configuration file under `NodeName`
 option (see `bluechi-agent.conf(5)`).
 
 #### **LogLevel** (string)
diff --git a/meson.build b/meson.build
index 775d5ae103..f290f07978 100644
--- a/meson.build
+++ b/meson.build
@@ -93,7 +93,7 @@ subdir('config')
 subdir('selinux')
 
 # build each binary
-subdir('src/manager')
+subdir('src/controller')
 subdir('src/agent')
 subdir('src/client')
 subdir('src/proxy')
diff --git a/src/agent/agent.c b/src/agent/agent.c
index 4d1d87681b..afedb1552b 100644
--- a/src/agent/agent.c
+++ b/src/agent/agent.c
@@ -110,7 +110,7 @@ static bool agent_reconnect(Agent *agent);
 static int agent_disconnected(UNUSED sd_bus_message *message, void *userdata, UNUSED sd_bus_error *error) {
         Agent *agent = (Agent *) userdata;
 
-        bc_log_error("Disconnected from manager");
+        bc_log_error("Disconnected from controller");
 
         agent->connection_state = AGENT_CONNECTION_STATE_RETRY;
         int r = sd_bus_emit_properties_changed(
@@ -147,7 +147,7 @@ static int agent_heartbeat_timer_callback(sd_event_source *event_source, UNUSED
                 }
         } else if (agent->connection_state == AGENT_CONNECTION_STATE_RETRY) {
                 agent->connection_retry_count++;
-                bc_log_infof("Trying to connect to manager (try %d)", agent->connection_retry_count);
+                bc_log_infof("Trying to connect to controller (try %d)", agent->connection_retry_count);
                 if (!agent_reconnect(agent)) {
                         bc_log_debugf("Connection retry %d failed", agent->connection_retry_count);
                 }
@@ -493,7 +493,7 @@ void agent_unref(Agent *agent) {
         free_and_null(agent->host);
         free_and_null(agent->orch_addr);
         free_and_null(agent->api_bus_service_name);
-        free_and_null(agent->manager_address);
+        free_and_null(agent->controller_address);
 
         if (agent->event != NULL) {
                 sd_event_unrefp(&agent->event);
@@ -531,8 +531,8 @@ bool agent_set_port(Agent *agent, const char *port_s) {
         return true;
 }
 
-bool agent_set_manager_address(Agent *agent, const char *address) {
-        return copy_str(&agent->manager_address, address);
+bool agent_set_controller_address(Agent *agent, const char *address) {
+        return copy_str(&agent->controller_address, address);
 }
 
 bool agent_set_orch_address(Agent *agent, const char *address) {
@@ -609,23 +609,23 @@ bool agent_parse_config(Agent *agent, const char *configfile) {
                 }
         }
 
-        value = cfg_get_value(agent->config, CFG_MANAGER_HOST);
+        value = cfg_get_value(agent->config, CFG_CONTROLLER_HOST);
         if (value) {
                 if (!agent_set_host(agent, value)) {
                         return false;
                 }
         }
 
-        value = cfg_get_value(agent->config, CFG_MANAGER_PORT);
+        value = cfg_get_value(agent->config, CFG_CONTROLLER_PORT);
         if (value) {
                 if (!agent_set_port(agent, value)) {
                         return false;
                 }
         }
 
-        value = cfg_get_value(agent->config, CFG_MANAGER_ADDRESS);
+        value = cfg_get_value(agent->config, CFG_CONTROLLER_ADDRESS);
         if (value) {
-                if (!agent_set_manager_address(agent, value)) {
+                if (!agent_set_controller_address(agent, value)) {
                         return false;
                 }
         }
@@ -2158,12 +2158,12 @@ static bool ensure_orch_address(Agent *agent) {
                 return true;
         }
 
-        if (agent->manager_address != NULL) {
-                return agent_set_orch_address(agent, agent->manager_address);
+        if (agent->controller_address != NULL) {
+                return agent_set_orch_address(agent, agent->controller_address);
         }
 
         if (agent->host == NULL) {
-                bc_log_errorf("No manager host specified for agent '%s'", agent->name);
+                bc_log_errorf("No controller host specified for agent '%s'", agent->name);
                 return false;
         }
 
@@ -2394,7 +2394,7 @@ bool agent_start(Agent *agent) {
         }
 
         if (!agent_connect(agent)) {
-                bc_log_error("Initial manager connection failed, retrying");
+                bc_log_error("Initial controller connection failed, retrying");
                 agent->connection_state = AGENT_CONNECTION_STATE_RETRY;
         }
 
@@ -2431,7 +2431,7 @@ void agent_stop(Agent *agent) {
 static bool agent_connect(Agent *agent) {
         peer_bus_close(agent->peer_dbus);
 
-        bc_log_infof("Connecting to manager on %s", agent->orch_addr);
+        bc_log_infof("Connecting to controller on %s", agent->orch_addr);
 
         agent->peer_dbus = peer_bus_open(agent->event, "peer-bus-to-controller", agent->orch_addr);
         if (agent->peer_dbus == NULL) {
@@ -2458,8 +2458,8 @@ static bool agent_connect(Agent *agent) {
         r = sd_bus_call_method(
                         agent->peer_dbus,
                         BC_DBUS_NAME,
-                        INTERNAL_MANAGER_OBJECT_PATH,
-                        INTERNAL_MANAGER_INTERFACE,
+                        INTERNAL_CONTROLLER_OBJECT_PATH,
+                        INTERNAL_CONTROLLER_INTERFACE,
                         "Register",
                         &error,
                         &bus_msg,
@@ -2477,7 +2477,7 @@ static bool agent_connect(Agent *agent) {
                 return false;
         }
 
-        bc_log_infof("Connected to manager as '%s'", agent->name);
+        bc_log_infof("Connected to controller as '%s'", agent->name);
 
         agent->connection_state = AGENT_CONNECTION_STATE_CONNECTED;
         agent->connection_retry_count = 0;
diff --git a/src/agent/agent.h b/src/agent/agent.h
index 13e070758c..bcba9babc9 100644
--- a/src/agent/agent.h
+++ b/src/agent/agent.h
@@ -54,7 +54,7 @@ struct Agent {
         char *name;
         char *host;
         int port;
-        char *manager_address;
+        char *controller_address;
         long heartbeat_interval_msec;
 
         AgentConnectionState connection_state;
diff --git a/src/agent/proxy.c b/src/agent/proxy.c
index d12d61649d..f00b8d8061 100644
--- a/src/agent/proxy.c
+++ b/src/agent/proxy.c
@@ -19,7 +19,7 @@ static const sd_bus_vtable proxy_service_vtable[] = {
         SD_BUS_VTABLE_END
 };
 
-/* This is called by the manager when the service that is the target
+/* This is called by the controller when the service that is the target
  * of a proxy changes state.
  */
 
@@ -86,7 +86,7 @@ static int proxy_service_method_target_state_changed(
 
         UnitActiveState active_state = active_state_from_string(active_state_str);
 
-        bc_log_debugf("Proxy service '%s' got TargetStateChanged from manager: %s %s %s",
+        bc_log_debugf("Proxy service '%s' got TargetStateChanged from controller: %s %s %s",
                       proxy->local_service_name,
                       active_state_str,
                       substate,
@@ -145,7 +145,7 @@ static int proxy_service_method_target_new(sd_bus_message *m, void *userdata, UN
                 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_INVALID_ARGS, "Invalid arguments");
         }
 
-        bc_log_debugf("Proxy service '%s' got TargetNew from manager: %s", proxy->local_service_name, reason);
+        bc_log_debugf("Proxy service '%s' got TargetNew from controller: %s", proxy->local_service_name, reason);
 
         return sd_bus_reply_method_return(m, "");
 }
@@ -167,7 +167,7 @@ static int proxy_service_method_target_removed(sd_bus_message *m, void *userdata
                                 strerror(-r));
         }
 
-        bc_log_debugf("Proxy service '%s' got TargetRemoved from manager: %s",
+        bc_log_debugf("Proxy service '%s' got TargetRemoved from controller: %s",
                       proxy->local_service_name,
                       reason);
 
@@ -180,7 +180,7 @@ static int proxy_service_method_target_removed(sd_bus_message *m, void *userdata
         return sd_bus_reply_method_return(m, "");
 }
 
-/* This is called by the manager when there was an error setting up the monitor.
+/* This is called by the controller when there was an error setting up the monitor.
  * Note, this is only sent once, and if it is sent, expect no other messages.
  */
 
@@ -316,7 +316,7 @@ int proxy_service_emit_proxy_new(ProxyService *proxy) {
 int proxy_service_emit_proxy_removed(ProxyService *proxy) {
         Agent *agent = proxy->agent;
 
-        /* No need to tell the manager if we didn't announce this */
+        /* No need to tell the controller if we didn't announce this */
         if (!proxy->sent_new_proxy) {
                 return 0;
         }
diff --git a/src/agent/proxy.h b/src/agent/proxy.h
index 7ad840b96a..b3bf8e79d4 100644
--- a/src/agent/proxy.h
+++ b/src/agent/proxy.h
@@ -17,7 +17,7 @@ struct ProxyService {
 
         sd_bus_message *request_message;
 
-        bool sent_new_proxy; /* We told manager about the proxy */
+        bool sent_new_proxy; /* We told controller about the proxy */
         bool dont_stop_proxy;
         bool sent_successful_ready;
 
diff --git a/src/bindings/python/README.md b/src/bindings/python/README.md
index 42e9a26133..b0d16a0746 100644
--- a/src/bindings/python/README.md
+++ b/src/bindings/python/README.md
@@ -22,9 +22,9 @@ pip3 install --force dist/bluechi-<version>-py3-none-any.whl
 Listing all connected nodes and their current state:
 
 ```python
-from bluechi.api import Manager
+from bluechi.api import Controller
 
-for node in Manager().list_nodes():
+for node in Controller().list_nodes():
     # node[name, obj_path, status]
     print(f"Node: {node[0]}, State: {node[3]}")
 ```
diff --git a/src/bindings/python/bluechi/api.py b/src/bindings/python/bluechi/api.py
index fe3a58c1f1..43916e0ec8 100644
--- a/src/bindings/python/bluechi/api.py
+++ b/src/bindings/python/bluechi/api.py
@@ -89,250 +89,223 @@ def get_properties_proxy(self) -> InterfaceProxy | ObjectProxy:
         return self.cached_properties_proxy
 
 
-class Monitor(ApiBase):
+class Agent(ApiBase):
     """
-    org.eclipse.bluechi.Monitor:
-    @short_description: Public interface of BlueChi on the managing node providing monitoring functionality.
+    org.eclipse.bluechi.Agent:
+    @short_description: Public interface of BlueChi on the managed node providing methods and signals for the respective node.
 
-    This interface is only available if a monitor has been created before via the Manager interface.
-    It provides methods to subscribe to changes in systemd units on managed nodes as well as signals for those changes.
+    This interface is used to create proxy services resolving dependencies on services of other managed nodes.
     """
 
-    def __init__(
-        self, monitor_path: ObjPath, bus: MessageBus = None, use_systembus=True
-    ) -> None:
-        super().__init__(BC_DBUS_INTERFACE, monitor_path, bus, use_systembus)
-
-        self.monitor_path = monitor_path
+    def __init__(self, bus: MessageBus = None, use_systembus=True) -> None:
+        super().__init__(BC_AGENT_DBUS_INTERFACE, BC_OBJECT_PATH, bus, use_systembus)
 
-    def close(self) -> None:
+    def create_proxy(self, local_service_name: str, node: str, unit: str) -> None:
         """
-          Close:
+          CreateProxy:
+        @local_service_name: The service name which requests the external dependency
+        @node: The requested node to provide the service
+        @unit: The external unit requested from the local service
 
-        Close the monitor.
+        BlueChi internal usage only.
+        CreateProxy() creates a new proxy service. It is part in the chain of resolving dependencies on services running on other managed nodes.
         """
-        self.get_proxy().Close()
+        self.get_proxy().CreateProxy(
+            local_service_name,
+            node,
+            unit,
+        )
 
-    def subscribe(self, node: str, unit: str) -> UInt32:
+    def remove_proxy(self, local_service_name: str, node: str, unit: str) -> None:
         """
-            Subscribe:
-          @node: The name of the node to subscribe to
-          @unit: The name of the unit to subscribe to
-          @id: The id of the created subscription.
+          RemoveProxy:
+        @local_service_name: The service name which requests the external dependency
+        @node: The requested node to provide the service
+        @unit: The external unit requested from the local service
 
-          Subscribe to changes of a unit on a node. Both fields support a wildcard '*'. A wildcard in the node name will create the subscription for all nodes.
-        If the unit name is a wildcard, then the subscription matches changes for all units on the node.
+        BlueChi internal usage only.
+        RemoveProxy() removes a new proxy service. It is part in the chain of resolving dependencies on services running on other managed nodes.
         """
-        return self.get_proxy().Subscribe(
+        self.get_proxy().RemoveProxy(
+            local_service_name,
             node,
             unit,
         )
 
-    def unsubscribe(self, id: UInt32) -> None:
+    @property
+    def status(self) -> str:
         """
-          Unsubscribe:
-        @id: The id of the subscription to cancel
+          Status:
 
-        Cancel the subscription by ID.
+        The connection status of the agent with the BlueChi controller.
+        On any change, a signal is emitted on the org.freedesktop.DBus.Properties interface.
         """
-        self.get_proxy().Unsubscribe(
-            id,
-        )
+        return self.get_proxy().Status
 
-    def subscribe_list(self, node: str, units: List[str]) -> UInt32:
+    def on_status_changed(self, callback: Callable[[Variant], None]):
         """
-            SubscribeList:
-          @node: The name of the node to subscribe to
-          @units: A list of unit names to subscribe to
-          @id: The id of the created subscription
+          Status:
 
-          Subscribe to changes of a list of units on a node. The node field supports a wildcard '*'. A wildcard in the node name will create the subscription
-        for all nodes.
+        The connection status of the agent with the BlueChi controller.
+        On any change, a signal is emitted on the org.freedesktop.DBus.Properties interface.
         """
-        return self.get_proxy().SubscribeList(
-            node,
-            units,
-        )
 
-    def add_peer(self, name: str) -> UInt32:
+        def on_properties_changed(
+            interface: str,
+            changed_props: Dict[str, Variant],
+            invalidated_props: Dict[str, Variant],
+        ) -> None:
+            value = changed_props.get("Status")
+            if value is not None:
+                callback(value)
+
+        self.get_properties_proxy().PropertiesChanged.connect(on_properties_changed)
+
+    @property
+    def disconnect_timestamp(self) -> UInt64:
         """
-          AddPeer:
-        @name: The name of the peer to add as listener to all monitor events. Needs to be unique name on the bus.
-        @id: The id of the created peer
+          DisconnectTimestamp:
 
-        Add a new peer to the monitor. A peer will receive all events that the monitor subscribes to.
+        A timestamp indicating when the agent lost connection to the BlueChi controller.
+        If the connection is active (agent is online), this value is 0.
         """
-        return self.get_proxy().AddPeer(
-            name,
-        )
+        return self.get_proxy().DisconnectTimestamp
 
-    def remove_peer(self, id: UInt32, reason: str) -> None:
+
+class Job(ApiBase):
+    """
+    org.eclipse.bluechi.Job:
+    @short_description: Public interface of BlueChi on the managing node for all job objects.
+
+    This interface is used to either cancel a job, get its properties and monitor its state.
+    """
+
+    def __init__(
+        self, job_path: ObjPath, bus: MessageBus = None, use_systembus=True
+    ) -> None:
+        super().__init__(BC_DBUS_INTERFACE, job_path, bus, use_systembus)
+
+        self.job_path = job_path
+
+    def cancel(self) -> None:
         """
-          RemovePeer:
-        @id: The id of the peer to remove
-        @reason: The reason for removing the peer
+          Cancel:
 
-        Remove a previously added peer from the monitor. The reason will be part of the PeerRemoved signal, which is only sent to the respective peer.
+        Cancels the job.
+        It cancels the corresponding systemd job if it was already started. Otherwise it cancels the BlueChi job.
         """
-        self.get_proxy().RemovePeer(
-            id,
-            reason,
-        )
+        self.get_proxy().Cancel()
 
-    def on_unit_properties_changed(
-        self,
-        callback: Callable[
-            [
-                str,
-                str,
-                str,
-                Structure,
-            ],
-            None,
-        ],
-    ) -> None:
+    @property
+    def id(self) -> UInt32:
         """
-          UnitPropertiesChanged:
-        @node: The node name this signal originated from
-        @unit: The unit for which the properties changed
-        @interface: The originating interface
-        @props: The changed properties as key-value pair with the name of the property as key
+          Id:
 
-        Whenever the properties change for any of the units that are currently subscribed to, this signal is emitted.
+        An integer giving the id of the job.
         """
-        self.get_proxy().UnitPropertiesChanged.connect(callback)
+        return self.get_proxy().Id
 
-    def on_unit_state_changed(
+    @property
+    def node(self) -> str:
+        """
+          Node:
+
+        The name of the node the job is on.
+        """
+        return self.get_proxy().Node
+
+    @property
+    def unit(self) -> str:
+        """
+          Unit:
+
+        The name of the unit the job works on.
+        """
+        return self.get_proxy().Unit
+
+    @property
+    def job_type(self) -> str:
+        """
+          JobType:
+
+        Type of the job, either Start or Stop.
+        """
+        return self.get_proxy().JobType
+
+    @property
+    def state(self) -> str:
+        """
+          State:
+
+        The current state of the job, one of: waiting (queued jobs) or running.
+        On any change, a signal is emitted on the org.freedesktop.DBus.Properties interface.
+        """
+        return self.get_proxy().State
+
+    def on_state_changed(self, callback: Callable[[Variant], None]):
+        """
+          State:
+
+        The current state of the job, one of: waiting (queued jobs) or running.
+        On any change, a signal is emitted on the org.freedesktop.DBus.Properties interface.
+        """
+
+        def on_properties_changed(
+            interface: str,
+            changed_props: Dict[str, Variant],
+            invalidated_props: Dict[str, Variant],
+        ) -> None:
+            value = changed_props.get("State")
+            if value is not None:
+                callback(value)
+
+        self.get_properties_proxy().PropertiesChanged.connect(on_properties_changed)
+
+
+class Metrics(ApiBase):
+    """
+    org.eclipse.bluechi.Metrics:
+    @short_description: Public interface of BlueChi on the managing node providing signals for performance metrics.
+
+    This interface is only available if the metrics have been enabled before via the Controller interface.
+    """
+
+    def __init__(self, bus: MessageBus = None, use_systembus=True) -> None:
+        super().__init__(BC_DBUS_INTERFACE, BC_METRICS_OBJECT_PATH, bus, use_systembus)
+
+    def on_start_unit_job_metrics(
         self,
         callback: Callable[
             [
                 str,
                 str,
                 str,
-                str,
-                str,
+                UInt64,
+                UInt64,
             ],
             None,
         ],
     ) -> None:
         """
-          UnitStateChanged:
-        @node: The node name this signal originated from
-        @unit: The unit for which the properties changed
-        @active_state: The active state of the unit
-        @sub_state: The sub state of the unit
-        @reason: The reason for the state change, the value is either real or virtual
+          StartUnitJobMetrics:
+        @node_name: The node name this metrics has been collected for
+        @job_id: The id of the job linked to the collected metrics
+        @unit: The unit name this metrics has been collected for
+        @job_measured_time_micros: The measured time it took starting the unit on the node in microseconds
+        @unit_start_prop_time_micros: The systemd time it took starting the unit on the node in microseconds
 
-        Emitted when the active state (and substate) of a monitored unit changes.
+        Emitted when a start operation processed by BlueChi finishes and the collection of metrics has been enabled previously.
         """
-        self.get_proxy().UnitStateChanged.connect(callback)
+        self.get_proxy().StartUnitJobMetrics.connect(callback)
 
-    def on_unit_new(
+    def on_agent_job_metrics(
         self,
         callback: Callable[
             [
                 str,
                 str,
                 str,
-            ],
-            None,
-        ],
-    ) -> None:
-        """
-            UnitNew:
-          @node: The node name this signal originated from
-          @unit: The unit for which the properties changed
-          @reason: The reason for the state change, the value is either real or virtual
-
-          Emitted when a new unit is loaded by systemd, for example when a service is started (reason=real), or if BlueChi learns of an already loaded unit
-        (reason=virtual).
-        """
-        self.get_proxy().UnitNew.connect(callback)
-
-    def on_unit_removed(
-        self,
-        callback: Callable[
-            [
-                str,
-                str,
-                str,
-            ],
-            None,
-        ],
-    ) -> None:
-        """
-            UnitRemoved:
-          @node: The node name this signal originated from
-          @unit: The unit for which the properties changed
-          @reason: The reason for the state change, the value is either real or virtual
-
-          Emitted when a unit is unloaded by systemd (reason=real), or when the agent disconnects and we previously reported the unit as loaded
-        (reason=virtual).
-        """
-        self.get_proxy().UnitRemoved.connect(callback)
-
-    def on_peer_removed(
-        self,
-        callback: Callable[
-            [
-                str,
-            ],
-            None,
-        ],
-    ) -> None:
-        """
-          PeerRemoved:
-        @reason: The reason the peer got removed from the monitor.
-
-        Emitted when a peer is removed from the monitor, e.g. when the monitor has been closed, and only sent to the respective peer.
-        """
-        self.get_proxy().PeerRemoved.connect(callback)
-
-
-class Metrics(ApiBase):
-    """
-    org.eclipse.bluechi.Metrics:
-    @short_description: Public interface of BlueChi on the managing node providing signals for performance metrics.
-
-    This interface is only available if the metrics have been enabled before via the Manager interface.
-    """
-
-    def __init__(self, bus: MessageBus = None, use_systembus=True) -> None:
-        super().__init__(BC_DBUS_INTERFACE, BC_METRICS_OBJECT_PATH, bus, use_systembus)
-
-    def on_start_unit_job_metrics(
-        self,
-        callback: Callable[
-            [
-                str,
-                str,
-                str,
-                UInt64,
-                UInt64,
-            ],
-            None,
-        ],
-    ) -> None:
-        """
-          StartUnitJobMetrics:
-        @node_name: The node name this metrics has been collected for
-        @job_id: The id of the job linked to the collected metrics
-        @unit: The unit name this metrics has been collected for
-        @job_measured_time_micros: The measured time it took starting the unit on the node in microseconds
-        @unit_start_prop_time_micros: The systemd time it took starting the unit on the node in microseconds
-
-        Emitted when a start operation processed by BlueChi finishes and the collection of metrics has been enabled previously.
-        """
-        self.get_proxy().StartUnitJobMetrics.connect(callback)
-
-    def on_agent_job_metrics(
-        self,
-        callback: Callable[
-            [
-                str,
-                str,
-                str,
-                UInt64,
+                UInt64,
             ],
             None,
         ],
@@ -350,247 +323,253 @@ def on_agent_job_metrics(
         self.get_proxy().AgentJobMetrics.connect(callback)
 
 
-class Job(ApiBase):
+class Node(ApiBase):
     """
-    org.eclipse.bluechi.Job:
-    @short_description: Public interface of BlueChi on the managing node for all job objects.
+    org.eclipse.bluechi.Node:
+    @short_description: Public interface of BlueChi on the managing node providing methods, signals and  for a specific node.
 
-    This interface is used to either cancel a job, get its properties and monitor its state.
+    This interface can be used to get information about a specific node and its units as well as control them, e.g. by starting or stopping them.
     """
 
     def __init__(
-        self, job_path: ObjPath, bus: MessageBus = None, use_systembus=True
+        self, node_name: str, bus: MessageBus = None, use_systembus=True
     ) -> None:
-        super().__init__(BC_DBUS_INTERFACE, job_path, bus, use_systembus)
+        # set empty node path temporary, needs to be resolved after the bus has been set
+        super().__init__(BC_DBUS_INTERFACE, "", bus, use_systembus)
 
-        self.job_path = job_path
+        controller = self.bus.get_proxy(BC_DBUS_INTERFACE, BC_OBJECT_PATH)
+        self.object_path = controller.GetNode(node_name)
 
-    def cancel(self) -> None:
-        """
-          Cancel:
-
-        Cancels the job.
-        It cancels the corresponding systemd job if it was already started. Otherwise it cancels the BlueChi job.
-        """
-        self.get_proxy().Cancel()
-
-    @property
-    def id(self) -> UInt32:
-        """
-          Id:
+        self.node_name = node_name
 
-        An integer giving the id of the job.
+    def start_unit(self, name: str, mode: str) -> ObjPath:
         """
-        return self.get_proxy().Id
+            StartUnit:
+          @name: The name of the unit to start
+          @mode: The mode used to start the unit
+          @job: The path for the job associated with the start operation
 
-    @property
-    def node(self) -> str:
-        """
-          Node:
+          Queues a unit activate job for the named unit on this node. The queue is per-unit name, which means there is only ever one active job per unit. Mode
+        can be one of replace or fail. If there is an outstanding queued (but not running) job, that is replaced if mode is replace, or the job
+        fails if mode is fail.
 
-        The name of the node the job is on.
+          The job returned is an object path for an object implementing org.eclipse.bluechi.Job, and which be monitored for the progress of the job, or used
+        to cancel the job. To track the result of the job, follow the JobRemoved signal on the Controller.
         """
-        return self.get_proxy().Node
+        return self.get_proxy().StartUnit(
+            name,
+            mode,
+        )
 
-    @property
-    def unit(self) -> str:
+    def stop_unit(self, name: str, mode: str) -> ObjPath:
         """
-          Unit:
+          StopUnit:
+        @name: The name of the unit to stop
+        @mode: The mode used to stop the unit
+        @job: The path for the job associated with the stop operation
 
-        The name of the unit the job works on.
+        StopUnit() is similar to StartUnit() but stops the specified unit rather than starting it.
         """
-        return self.get_proxy().Unit
+        return self.get_proxy().StopUnit(
+            name,
+            mode,
+        )
 
-    @property
-    def job_type(self) -> str:
+    def freeze_unit(self, name: str) -> None:
         """
-          JobType:
+            FreezeUnit:
+          @name: The name of the unit to freeze
 
-        Type of the job, either Start or Stop.
+          Freezing the unit will cause all processes contained within the cgroup corresponding to the unit to be suspended. Being suspended means that unit's
+        processes won't be scheduled to run on CPU until thawed.
         """
-        return self.get_proxy().JobType
+        self.get_proxy().FreezeUnit(
+            name,
+        )
 
-    @property
-    def state(self) -> str:
+    def thaw_unit(self, name: str) -> None:
         """
-          State:
+          ThawUnit:
+        @name: The name of the unit to thaw
 
-        The current state of the job, one of: waiting (queued jobs) or running.
-        On any change, a signal is emitted on the org.freedesktop.DBus.Properties interface.
+        This is the inverse operation to the freeze command and resumes the execution of processes in the unit's cgroup.
         """
-        return self.get_proxy().State
+        self.get_proxy().ThawUnit(
+            name,
+        )
 
-    def on_state_changed(self, callback: Callable[[Variant], None]):
+    def reload_unit(self, name: str, mode: str) -> ObjPath:
         """
-          State:
+          ReloadUnit:
+        @name: The name of the unit to reload
+        @mode: The mode used to reload the unit
+        @job: The path for the job associated with the reload operation
 
-        The current state of the job, one of: waiting (queued jobs) or running.
-        On any change, a signal is emitted on the org.freedesktop.DBus.Properties interface.
+        ReloadUnit() is similar to StartUnit() but can be used to reload a unit instead. See equivalent systemd methods for details.
         """
+        return self.get_proxy().ReloadUnit(
+            name,
+            mode,
+        )
 
-        def on_properties_changed(
-            interface: str,
-            changed_props: Dict[str, Variant],
-            invalidated_props: Dict[str, Variant],
-        ) -> None:
-            value = changed_props.get("State")
-            if value is not None:
-                callback(value)
-
-        self.get_properties_proxy().PropertiesChanged.connect(on_properties_changed)
-
-
-class Manager(ApiBase):
-    """
-    org.eclipse.bluechi.Manager:
-    @short_description: Public interface of BlueChi on the managing node providing methods and signals for all nodes.
-
-    This interface can be used to get information about all nodes and their units, create monitors and listen for job signals.
-    """
-
-    def __init__(self, bus: MessageBus = None, use_systembus=True) -> None:
-        super().__init__(BC_DBUS_INTERFACE, BC_OBJECT_PATH, bus, use_systembus)
-
-    def list_units(
-        self,
-    ) -> List[Tuple[str, str, str, str, str, str, str, ObjPath, UInt32, str, ObjPath]]:
+    def restart_unit(self, name: str, mode: str) -> ObjPath:
         """
-          ListUnits:
-        @units: A list of all units on each node:
-          - The node name
-          - The primary unit name as string
-          - The human readable description string
-          - The load state (i.e. whether the unit file has been loaded successfully)
-          - The active state (i.e. whether the unit is currently started or not)
-          - The sub state (a more fine-grained version of the active state that is specific to the unit type, which the active state is not)
-          - A unit that is being followed in its state by this unit, if there is any, otherwise the empty string.
-          - The unit object path
-          - If there is a job queued for the job unit the numeric job id, 0 otherwise
-          - The job type as string
-          - The job object path
+          RestartUnit:
+        @name: The name of the unit to restart
+        @mode: The mode used to restart the unit
+        @job: The path for the job associated with the restart operation
 
-        List all loaded systemd units on all nodes which are online.
+        RestartUnit() is similar to StartUnit() but can be used to restart a unit instead. See equivalent systemd methods for details.
         """
-        return self.get_proxy().ListUnits()
+        return self.get_proxy().RestartUnit(
+            name,
+            mode,
+        )
 
-    def list_nodes(self) -> List[Tuple[str, ObjPath, str]]:
+    def get_unit_properties(self, name: str, interface: str) -> Structure:
         """
-          ListNodes:
-        @nodes: A list of all nodes:
-          - The node name
-          - The object path of the node
-          - the current state of that node, either online or offline
+          GetUnitProperties:
+        @name: The name of unit
+        @interface: The interface name
+        @props: The  as key-value pair with the name of the property as key
 
-        List all nodes managed by BlueChi regardless if they are offline or online.
+        Returns the current  for a named unit on the node. The returned  are the same as you would get in the systemd  apis.
         """
-        return self.get_proxy().ListNodes()
+        return self.get_proxy().GetUnitProperties(
+            name,
+            interface,
+        )
 
-    def get_node(self, name: str) -> ObjPath:
+    def get_unit_property(self, name: str, interface: str, property: str) -> Variant:
         """
-          GetNode:
-        @name: Name of the node
-        @path: The path of the requested node
+          GetUnitProperty:
+        @name: The name of unit
+        @interface: The interface name
+        @property: The property name
+        @value: The value of the property
 
-        Get the object path of the named node.
+        Get one named property, otherwise similar to GetUnit.
         """
-        return self.get_proxy().GetNode(
+        return self.get_proxy().GetUnitProperty(
             name,
+            interface,
+            property,
         )
 
-    def create_monitor(self) -> ObjPath:
+    def set_unit_properties(
+        self, name: str, runtime: bool, keyvalues: List[Tuple[str, Variant]]
+    ) -> None:
         """
-          CreateMonitor:
-        @monitor: The path of the created monitor.
+          SetUnitProperties:
+        @name: The name of the unit
+        @runtime: Specify if the changes should persist after reboot or not
+        @keyvalues: A list of the new values as key-value pair with the key being the name of the property
 
-        Create a new monitor on which subscriptions can be added. It will automatically be closed as soon as the connection is closed.
+        Set named . If runtime is true the property changes do not persist across reboots.
         """
-        return self.get_proxy().CreateMonitor()
+        self.get_proxy().SetUnitProperties(
+            name,
+            runtime,
+            keyvalues,
+        )
 
-    def enable_metrics(self) -> None:
+    def enable_unit_files(
+        self, files: List[str], runtime: bool, force: bool
+    ) -> Tuple[bool, List[Tuple[str, str, str]],]:
         """
-          EnableMetrics:
+          EnableUnitFiles:
+        @files: A list of units to enable
+        @runtime: Specify if the changes should persist after reboot or not
+        @force: Specify if replacing the symlinks pointing to other units should be enforced
+        @carries_install_info: True if the units contained enablement information
+        @changes: The changes made
+          - type of change (one of: symlink, unlink)
+          - file name of the symlink
+          - destination of the symlink
 
-        Enable collecting performance metrics.
+        EnableUnitFiles() may be used to enable one or more units in the system (by creating symlinks to them in /etc/ or /run/).
         """
-        self.get_proxy().EnableMetrics()
+        return self.get_proxy().EnableUnitFiles(
+            files,
+            runtime,
+            force,
+        )
 
-    def disable_metrics(self) -> None:
+    def disable_unit_files(
+        self, files: List[str], runtime: bool
+    ) -> List[Tuple[str, str, str]]:
         """
-          DisableMetrics:
+          DisableUnitFiles:
+        @files: A list of units to enable
+        @runtime: Specify if the changes should persist after reboot or not
+        @changes: The changes made
+          - type of change (one of: symlink, unlink)
+          - file name of the symlink
+          - destination of the symlink
 
-        Disable collecting performance metrics.
+        DisableUnitFiles() is similar to EnableUnitFiles() but disables the specified units by removing all symlinks to them in /etc/ and /run/
         """
-        self.get_proxy().DisableMetrics()
+        return self.get_proxy().DisableUnitFiles(
+            files,
+            runtime,
+        )
 
-    def set_log_level(self, loglevel: str) -> None:
+    def list_units(
+        self,
+    ) -> List[Tuple[str, str, str, str, str, str, ObjPath, UInt32, str, ObjPath]]:
         """
-          SetLogLevel:
-        @loglevel: The new loglevel to use.
+          ListUnits:
+        @units: A list of all units on the node:
+          - The primary unit name as string
+          - The human readable description string
+          - The load state (i.e. whether the unit file has been loaded successfully)
+          - The active state (i.e. whether the unit is currently started or not)
+          - The sub state (a more fine-grained version of the active state that is specific to the unit type, which the active state is not)
+          - A unit that is being followed in its state by this unit, if there is any, otherwise the empty string.
+          - The unit object path
+          - If there is a job queued for the job unit the numeric job id, 0 otherwise
+          - The job type as string
+          - The job object path
 
-        Change the loglevel of the manager.
+        List all loaded systemd units.
         """
-        self.get_proxy().SetLogLevel(
-            loglevel,
-        )
+        return self.get_proxy().ListUnits()
 
-    def on_job_new(
-        self,
-        callback: Callable[
-            [
-                UInt32,
-                ObjPath,
-            ],
-            None,
-        ],
-    ) -> None:
+    def reload(self) -> None:
         """
-          JobNew:
-        @id: The id of the new job
-        @job: The path of the job
+          Reload:
 
-        Emitted each time a new BlueChi job is queued.
+        Reload() may be invoked to reload all unit files.
         """
-        self.get_proxy().JobNew.connect(callback)
+        self.get_proxy().Reload()
 
-    def on_job_removed(
-        self,
-        callback: Callable[
-            [
-                UInt32,
-                ObjPath,
-                str,
-                str,
-                str,
-            ],
-            None,
-        ],
-    ) -> None:
+    def set_log_level(self, level: str) -> None:
         """
-            JobRemoved:
-          @id: The id of the new job
-          @job: The path of the job
-          @node: The name of the node the job has been completed on
-          @unit: The name of the unit the job has been completed on
-          @result: The result of the job
+          SetLogLevel:
+        @loglevel: The new loglevel to use.
 
-          Emitted each time a new job is dequeued or the underlying systemd job finished. result is one of: done, failed, cancelled, timeout, dependency,
-        skipped. This is either the result from systemd on the node, or cancelled if the job was cancelled in BlueChi before any systemd job was started
-        for it.
+        Change the loglevel of the controller.
         """
-        self.get_proxy().JobRemoved.connect(callback)
+        self.get_proxy().SetLogLevel(
+            level,
+        )
+
+    @property
+    def name(self) -> str:
+        """
+          Name:
+
+        The name of the node.
+        """
+        return self.get_proxy().Name
 
     @property
     def status(self) -> str:
         """
           Status:
 
-        The status of the overall system. Its value is one of:
-          down:  no node is connected
-          degraded: at least one node is not connected
-          up:   all nodes listed in the AllowedNodeNames config are connected
-        A signal is emitted on the org.freedesktop.DBus.Properties interface each time the system state changes. Therefore, a (dis-)connecting node
-        doesn't necessarily result in a signal to be emitted. For this puprose, the Status property on the org.eclipse.bluechi.Node interface is a
-        better choice.
+        The connection status of the node with the BlueChi controller.
+        On any change, a signal is emitted on the org.freedesktop.DBus.Properties interface.
         """
         return self.get_proxy().Status
 
@@ -598,13 +577,8 @@ def on_status_changed(self, callback: Callable[[Variant], None]):
         """
           Status:
 
-        The status of the overall system. Its value is one of:
-          down:  no node is connected
-          degraded: at least one node is not connected
-          up:   all nodes listed in the AllowedNodeNames config are connected
-        A signal is emitted on the org.freedesktop.DBus.Properties interface each time the system state changes. Therefore, a (dis-)connecting node
-        doesn't necessarily result in a signal to be emitted. For this puprose, the Status property on the org.eclipse.bluechi.Node interface is a
-        better choice.
+        The connection status of the node with the BlueChi controller.
+        On any change, a signal is emitted on the org.freedesktop.DBus.Properties interface.
         """
 
         def on_properties_changed(
@@ -618,204 +592,234 @@ def on_properties_changed(
 
         self.get_properties_proxy().PropertiesChanged.connect(on_properties_changed)
 
+    @property
+    def last_seen_timestamp(self) -> UInt64:
+        """
+          LastSeenTimestamp:
 
-class Node(ApiBase):
+        A timestamp indicating when the last connection test (e.g. via heartbeat) was successful.
+        """
+        return self.get_proxy().LastSeenTimestamp
+
+
+class Monitor(ApiBase):
     """
-    org.eclipse.bluechi.Node:
-    @short_description: Public interface of BlueChi on the managing node providing methods, signals and  for a specific node.
+    org.eclipse.bluechi.Monitor:
+    @short_description: Public interface of BlueChi on the managing node providing monitoring functionality.
 
-    This interface can be used to get information about a specific node and its units as well as control them, e.g. by starting or stopping them.
+    This interface is only available if a monitor has been created before via the Controller interface.
+    It provides methods to subscribe to changes in systemd units on managed nodes as well as signals for those changes.
     """
 
     def __init__(
-        self, node_name: str, bus: MessageBus = None, use_systembus=True
+        self, monitor_path: ObjPath, bus: MessageBus = None, use_systembus=True
     ) -> None:
-        # set empty node path temporary, needs to be resolved after the bus has been set
-        super().__init__(BC_DBUS_INTERFACE, "", bus, use_systembus)
+        super().__init__(BC_DBUS_INTERFACE, monitor_path, bus, use_systembus)
 
-        manager = self.bus.get_proxy(BC_DBUS_INTERFACE, BC_OBJECT_PATH)
-        self.object_path = manager.GetNode(node_name)
+        self.monitor_path = monitor_path
 
-        self.node_name = node_name
+    def close(self) -> None:
+        """
+          Close:
 
-    def start_unit(self, name: str, mode: str) -> ObjPath:
+        Close the monitor.
         """
-            StartUnit:
-          @name: The name of the unit to start
-          @mode: The mode used to start the unit
-          @job: The path for the job associated with the start operation
+        self.get_proxy().Close()
 
-          Queues a unit activate job for the named unit on this node. The queue is per-unit name, which means there is only ever one active job per unit. Mode
-        can be one of replace or fail. If there is an outstanding queued (but not running) job, that is replaced if mode is replace, or the job
-        fails if mode is fail.
+    def subscribe(self, node: str, unit: str) -> UInt32:
+        """
+            Subscribe:
+          @node: The name of the node to subscribe to
+          @unit: The name of the unit to subscribe to
+          @id: The id of the created subscription.
 
-          The job returned is an object path for an object implementing org.eclipse.bluechi.Job, and which be monitored for the progress of the job, or used
-        to cancel the job. To track the result of the job, follow the JobRemoved signal on the Manager.
+          Subscribe to changes of a unit on a node. Both fields support a wildcard '*'. A wildcard in the node name will create the subscription for all nodes.
+        If the unit name is a wildcard, then the subscription matches changes for all units on the node.
         """
-        return self.get_proxy().StartUnit(
-            name,
-            mode,
+        return self.get_proxy().Subscribe(
+            node,
+            unit,
         )
 
-    def stop_unit(self, name: str, mode: str) -> ObjPath:
+    def unsubscribe(self, id: UInt32) -> None:
         """
-          StopUnit:
-        @name: The name of the unit to stop
-        @mode: The mode used to stop the unit
-        @job: The path for the job associated with the stop operation
+          Unsubscribe:
+        @id: The id of the subscription to cancel
 
-        StopUnit() is similar to StartUnit() but stops the specified unit rather than starting it.
+        Cancel the subscription by ID.
         """
-        return self.get_proxy().StopUnit(
-            name,
-            mode,
+        self.get_proxy().Unsubscribe(
+            id,
         )
 
-    def freeze_unit(self, name: str) -> None:
+    def subscribe_list(self, node: str, units: List[str]) -> UInt32:
         """
-            FreezeUnit:
-          @name: The name of the unit to freeze
+            SubscribeList:
+          @node: The name of the node to subscribe to
+          @units: A list of unit names to subscribe to
+          @id: The id of the created subscription
 
-          Freezing the unit will cause all processes contained within the cgroup corresponding to the unit to be suspended. Being suspended means that unit's
-        processes won't be scheduled to run on CPU until thawed.
+          Subscribe to changes of a list of units on a node. The node field supports a wildcard '*'. A wildcard in the node name will create the subscription
+        for all nodes.
         """
-        self.get_proxy().FreezeUnit(
-            name,
+        return self.get_proxy().SubscribeList(
+            node,
+            units,
         )
 
-    def thaw_unit(self, name: str) -> None:
+    def add_peer(self, name: str) -> UInt32:
         """
-          ThawUnit:
-        @name: The name of the unit to thaw
+          AddPeer:
+        @name: The name of the peer to add as listener to all monitor events. Needs to be unique name on the bus.
+        @id: The id of the created peer
 
-        This is the inverse operation to the freeze command and resumes the execution of processes in the unit's cgroup.
+        Add a new peer to the monitor. A peer will receive all events that the monitor subscribes to.
         """
-        self.get_proxy().ThawUnit(
+        return self.get_proxy().AddPeer(
             name,
         )
 
-    def reload_unit(self, name: str, mode: str) -> ObjPath:
+    def remove_peer(self, id: UInt32, reason: str) -> None:
         """
-          ReloadUnit:
-        @name: The name of the unit to reload
-        @mode: The mode used to reload the unit
-        @job: The path for the job associated with the reload operation
+          RemovePeer:
+        @id: The id of the peer to remove
+        @reason: The reason for removing the peer
 
-        ReloadUnit() is similar to StartUnit() but can be used to reload a unit instead. See equivalent systemd methods for details.
+        Remove a previously added peer from the monitor. The reason will be part of the PeerRemoved signal, which is only sent to the respective peer.
         """
-        return self.get_proxy().ReloadUnit(
-            name,
-            mode,
+        self.get_proxy().RemovePeer(
+            id,
+            reason,
         )
 
-    def restart_unit(self, name: str, mode: str) -> ObjPath:
+    def on_unit_properties_changed(
+        self,
+        callback: Callable[
+            [
+                str,
+                str,
+                str,
+                Structure,
+            ],
+            None,
+        ],
+    ) -> None:
         """
-          RestartUnit:
-        @name: The name of the unit to restart
-        @mode: The mode used to restart the unit
-        @job: The path for the job associated with the restart operation
+          UnitPropertiesChanged:
+        @node: The node name this signal originated from
+        @unit: The unit for which the properties changed
+        @interface: The originating interface
+        @props: The changed properties as key-value pair with the name of the property as key
 
-        RestartUnit() is similar to StartUnit() but can be used to restart a unit instead. See equivalent systemd methods for details.
+        Whenever the properties change for any of the units that are currently subscribed to, this signal is emitted.
         """
-        return self.get_proxy().RestartUnit(
-            name,
-            mode,
-        )
+        self.get_proxy().UnitPropertiesChanged.connect(callback)
 
-    def get_unit_properties(self, name: str, interface: str) -> Structure:
+    def on_unit_state_changed(
+        self,
+        callback: Callable[
+            [
+                str,
+                str,
+                str,
+                str,
+                str,
+            ],
+            None,
+        ],
+    ) -> None:
         """
-          GetUnitProperties:
-        @name: The name of unit
-        @interface: The interface name
-        @props: The  as key-value pair with the name of the property as key
+          UnitStateChanged:
+        @node: The node name this signal originated from
+        @unit: The unit for which the properties changed
+        @active_state: The active state of the unit
+        @sub_state: The sub state of the unit
+        @reason: The reason for the state change, the value is either real or virtual
 
-        Returns the current  for a named unit on the node. The returned  are the same as you would get in the systemd  apis.
+        Emitted when the active state (and substate) of a monitored unit changes.
         """
-        return self.get_proxy().GetUnitProperties(
-            name,
-            interface,
-        )
+        self.get_proxy().UnitStateChanged.connect(callback)
 
-    def get_unit_property(self, name: str, interface: str, property: str) -> Variant:
+    def on_unit_new(
+        self,
+        callback: Callable[
+            [
+                str,
+                str,
+                str,
+            ],
+            None,
+        ],
+    ) -> None:
         """
-          GetUnitProperty:
-        @name: The name of unit
-        @interface: The interface name
-        @property: The property name
-        @value: The value of the property
+            UnitNew:
+          @node: The node name this signal originated from
+          @unit: The unit for which the properties changed
+          @reason: The reason for the state change, the value is either real or virtual
 
-        Get one named property, otherwise similar to GetUnit.
+          Emitted when a new unit is loaded by systemd, for example when a service is started (reason=real), or if BlueChi learns of an already loaded unit
+        (reason=virtual).
         """
-        return self.get_proxy().GetUnitProperty(
-            name,
-            interface,
-            property,
-        )
+        self.get_proxy().UnitNew.connect(callback)
 
-    def set_unit_properties(
-        self, name: str, runtime: bool, keyvalues: List[Tuple[str, Variant]]
+    def on_unit_removed(
+        self,
+        callback: Callable[
+            [
+                str,
+                str,
+                str,
+            ],
+            None,
+        ],
     ) -> None:
         """
-          SetUnitProperties:
-        @name: The name of the unit
-        @runtime: Specify if the changes should persist after reboot or not
-        @keyvalues: A list of the new values as key-value pair with the key being the name of the property
+            UnitRemoved:
+          @node: The node name this signal originated from
+          @unit: The unit for which the properties changed
+          @reason: The reason for the state change, the value is either real or virtual
 
-        Set named . If runtime is true the property changes do not persist across reboots.
+          Emitted when a unit is unloaded by systemd (reason=real), or when the agent disconnects and we previously reported the unit as loaded
+        (reason=virtual).
         """
-        self.get_proxy().SetUnitProperties(
-            name,
-            runtime,
-            keyvalues,
-        )
+        self.get_proxy().UnitRemoved.connect(callback)
 
-    def enable_unit_files(
-        self, files: List[str], runtime: bool, force: bool
-    ) -> Tuple[bool, List[Tuple[str, str, str]],]:
+    def on_peer_removed(
+        self,
+        callback: Callable[
+            [
+                str,
+            ],
+            None,
+        ],
+    ) -> None:
         """
-          EnableUnitFiles:
-        @files: A list of units to enable
-        @runtime: Specify if the changes should persist after reboot or not
-        @force: Specify if replacing the symlinks pointing to other units should be enforced
-        @carries_install_info: True if the units contained enablement information
-        @changes: The changes made
-          - type of change (one of: symlink, unlink)
-          - file name of the symlink
-          - destination of the symlink
+          PeerRemoved:
+        @reason: The reason the peer got removed from the monitor.
 
-        EnableUnitFiles() may be used to enable one or more units in the system (by creating symlinks to them in /etc/ or /run/).
+        Emitted when a peer is removed from the monitor, e.g. when the monitor has been closed, and only sent to the respective peer.
         """
-        return self.get_proxy().EnableUnitFiles(
-            files,
-            runtime,
-            force,
-        )
+        self.get_proxy().PeerRemoved.connect(callback)
 
-    def disable_unit_files(
-        self, files: List[str], runtime: bool
-    ) -> List[Tuple[str, str, str]]:
-        """
-          DisableUnitFiles:
-        @files: A list of units to enable
-        @runtime: Specify if the changes should persist after reboot or not
-        @changes: The changes made
-          - type of change (one of: symlink, unlink)
-          - file name of the symlink
-          - destination of the symlink
 
-        DisableUnitFiles() is similar to EnableUnitFiles() but disables the specified units by removing all symlinks to them in /etc/ and /run/
-        """
-        return self.get_proxy().DisableUnitFiles(
-            files,
-            runtime,
-        )
+class Controller(ApiBase):
+    """
+    org.eclipse.bluechi.Controller:
+    @short_description: Public interface of BlueChi on the managing node providing methods and signals for all nodes.
+
+    This interface can be used to get information about all nodes and their units, create monitors and listen for job signals.
+    """
+
+    def __init__(self, bus: MessageBus = None, use_systembus=True) -> None:
+        super().__init__(BC_DBUS_INTERFACE, BC_OBJECT_PATH, bus, use_systembus)
 
     def list_units(
         self,
-    ) -> List[Tuple[str, str, str, str, str, str, ObjPath, UInt32, str, ObjPath]]:
+    ) -> List[Tuple[str, str, str, str, str, str, str, ObjPath, UInt32, str, ObjPath]]:
         """
           ListUnits:
-        @units: A list of all units on the node:
+        @units: A list of all units on each node:
+          - The node name
           - The primary unit name as string
           - The human readable description string
           - The load state (i.e. whether the unit file has been loaded successfully)
@@ -827,127 +831,128 @@ def list_units(
           - The job type as string
           - The job object path
 
-        List all loaded systemd units.
+        List all loaded systemd units on all nodes which are online.
         """
         return self.get_proxy().ListUnits()
 
-    def reload(self) -> None:
+    def list_nodes(self) -> List[Tuple[str, ObjPath, str]]:
         """
-          Reload:
+          ListNodes:
+        @nodes: A list of all nodes:
+          - The node name
+          - The object path of the node
+          - the current state of that node, either online or offline
 
-        Reload() may be invoked to reload all unit files.
+        List all nodes managed by BlueChi regardless if they are offline or online.
         """
-        self.get_proxy().Reload()
+        return self.get_proxy().ListNodes()
 
-    def set_log_level(self, level: str) -> None:
+    def get_node(self, name: str) -> ObjPath:
         """
-          SetLogLevel:
-        @loglevel: The new loglevel to use.
+          GetNode:
+        @name: Name of the node
+        @path: The path of the requested node
 
-        Change the loglevel of the manager.
+        Get the object path of the named node.
         """
-        self.get_proxy().SetLogLevel(
-            level,
+        return self.get_proxy().GetNode(
+            name,
         )
 
-    @property
-    def name(self) -> str:
+    def create_monitor(self) -> ObjPath:
         """
-          Name:
+          CreateMonitor:
+        @monitor: The path of the created monitor.
 
-        The name of the node.
+        Create a new monitor on which subscriptions can be added. It will automatically be closed as soon as the connection is closed.
         """
-        return self.get_proxy().Name
+        return self.get_proxy().CreateMonitor()
 
-    @property
-    def status(self) -> str:
+    def enable_metrics(self) -> None:
         """
-          Status:
+          EnableMetrics:
 
-        The connection status of the node with the BlueChi controller.
-        On any change, a signal is emitted on the org.freedesktop.DBus.Properties interface.
+        Enable collecting performance metrics.
         """
-        return self.get_proxy().Status
+        self.get_proxy().EnableMetrics()
 
-    def on_status_changed(self, callback: Callable[[Variant], None]):
+    def disable_metrics(self) -> None:
         """
-          Status:
+          DisableMetrics:
 
-        The connection status of the node with the BlueChi controller.
-        On any change, a signal is emitted on the org.freedesktop.DBus.Properties interface.
+        Disable collecting performance metrics.
         """
+        self.get_proxy().DisableMetrics()
 
-        def on_properties_changed(
-            interface: str,
-            changed_props: Dict[str, Variant],
-            invalidated_props: Dict[str, Variant],
-        ) -> None:
-            value = changed_props.get("Status")
-            if value is not None:
-                callback(value)
-
-        self.get_properties_proxy().PropertiesChanged.connect(on_properties_changed)
-
-    @property
-    def last_seen_timestamp(self) -> UInt64:
+    def set_log_level(self, loglevel: str) -> None:
         """
-          LastSeenTimestamp:
+          SetLogLevel:
+        @loglevel: The new loglevel to use.
 
-        A timestamp indicating when the last connection test (e.g. via heartbeat) was successful.
+        Change the loglevel of the controller.
         """
-        return self.get_proxy().LastSeenTimestamp
-
-
-class Agent(ApiBase):
-    """
-    org.eclipse.bluechi.Agent:
-    @short_description: Public interface of BlueChi on the managed node providing methods and signals for the respective node.
-
-    This interface is used to create proxy services resolving dependencies on services of other managed nodes.
-    """
-
-    def __init__(self, bus: MessageBus = None, use_systembus=True) -> None:
-        super().__init__(BC_AGENT_DBUS_INTERFACE, BC_OBJECT_PATH, bus, use_systembus)
+        self.get_proxy().SetLogLevel(
+            loglevel,
+        )
 
-    def create_proxy(self, local_service_name: str, node: str, unit: str) -> None:
+    def on_job_new(
+        self,
+        callback: Callable[
+            [
+                UInt32,
+                ObjPath,
+            ],
+            None,
+        ],
+    ) -> None:
         """
-          CreateProxy:
-        @local_service_name: The service name which requests the external dependency
-        @node: The requested node to provide the service
-        @unit: The external unit requested from the local service
+          JobNew:
+        @id: The id of the new job
+        @job: The path of the job
 
-        BlueChi internal usage only.
-        CreateProxy() creates a new proxy service. It is part in the chain of resolving dependencies on services running on other managed nodes.
+        Emitted each time a new BlueChi job is queued.
         """
-        self.get_proxy().CreateProxy(
-            local_service_name,
-            node,
-            unit,
-        )
+        self.get_proxy().JobNew.connect(callback)
 
-    def remove_proxy(self, local_service_name: str, node: str, unit: str) -> None:
+    def on_job_removed(
+        self,
+        callback: Callable[
+            [
+                UInt32,
+                ObjPath,
+                str,
+                str,
+                str,
+            ],
+            None,
+        ],
+    ) -> None:
         """
-          RemoveProxy:
-        @local_service_name: The service name which requests the external dependency
-        @node: The requested node to provide the service
-        @unit: The external unit requested from the local service
+            JobRemoved:
+          @id: The id of the new job
+          @job: The path of the job
+          @node: The name of the node the job has been completed on
+          @unit: The name of the unit the job has been completed on
+          @result: The result of the job
 
-        BlueChi internal usage only.
-        RemoveProxy() removes a new proxy service. It is part in the chain of resolving dependencies on services running on other managed nodes.
+          Emitted each time a new job is dequeued or the underlying systemd job finished. result is one of: done, failed, cancelled, timeout, dependency,
+        skipped. This is either the result from systemd on the node, or cancelled if the job was cancelled in BlueChi before any systemd job was started
+        for it.
         """
-        self.get_proxy().RemoveProxy(
-            local_service_name,
-            node,
-            unit,
-        )
+        self.get_proxy().JobRemoved.connect(callback)
 
     @property
     def status(self) -> str:
         """
           Status:
 
-        The connection status of the agent with the BlueChi controller.
-        On any change, a signal is emitted on the org.freedesktop.DBus.Properties interface.
+        The status of the overall system. Its value is one of:
+          down:  no node is connected
+          degraded: at least one node is not connected
+          up:   all nodes listed in the AllowedNodeNames config are connected
+        A signal is emitted on the org.freedesktop.DBus.Properties interface each time the system state changes. Therefore, a (dis-)connecting node
+        doesn't necessarily result in a signal to be emitted. For this puprose, the Status property on the org.eclipse.bluechi.Node interface is a
+        better choice.
         """
         return self.get_proxy().Status
 
@@ -955,8 +960,13 @@ def on_status_changed(self, callback: Callable[[Variant], None]):
         """
           Status:
 
-        The connection status of the agent with the BlueChi controller.
-        On any change, a signal is emitted on the org.freedesktop.DBus.Properties interface.
+        The status of the overall system. Its value is one of:
+          down:  no node is connected
+          degraded: at least one node is not connected
+          up:   all nodes listed in the AllowedNodeNames config are connected
+        A signal is emitted on the org.freedesktop.DBus.Properties interface each time the system state changes. Therefore, a (dis-)connecting node
+        doesn't necessarily result in a signal to be emitted. For this puprose, the Status property on the org.eclipse.bluechi.Node interface is a
+        better choice.
         """
 
         def on_properties_changed(
@@ -969,13 +979,3 @@ def on_properties_changed(
                 callback(value)
 
         self.get_properties_proxy().PropertiesChanged.connect(on_properties_changed)
-
-    @property
-    def disconnect_timestamp(self) -> UInt64:
-        """
-          DisconnectTimestamp:
-
-        A timestamp indicating when the agent lost connection to the BlueChi controller.
-        If the connection is active (agent is online), this value is 0.
-        """
-        return self.get_proxy().DisconnectTimestamp
diff --git a/src/bindings/python/bluechi/ext.py b/src/bindings/python/bluechi/ext.py
index f4719dda3e..5ceed8f805 100644
--- a/src/bindings/python/bluechi/ext.py
+++ b/src/bindings/python/bluechi/ext.py
@@ -6,7 +6,7 @@
 from dasbus.loop import EventLoop
 from dasbus.typing import UInt32, ObjPath
 
-from bluechi.api import Node, Manager
+from bluechi.api import Node, Controller
 
 
 UnitInfo = namedtuple(
@@ -63,7 +63,7 @@ def on_job_removed(
                 self.job_result = result
                 event_loop.quit()
 
-        Manager(bus=self.node.bus).on_job_removed(on_job_removed)
+        Controller(bus=self.node.bus).on_job_removed(on_job_removed)
 
         wait_for_job_path = operation(unit, "replace")
         event_loop.run()
diff --git a/src/bindings/python/templates/manager.tmpl b/src/bindings/python/templates/controller.tmpl
similarity index 92%
rename from src/bindings/python/templates/manager.tmpl
rename to src/bindings/python/templates/controller.tmpl
index bf0efbdb79..74327759f3 100644
--- a/src/bindings/python/templates/manager.tmpl
+++ b/src/bindings/python/templates/controller.tmpl
@@ -1,5 +1,5 @@
 
-class Manager(ApiBase):
+class Controller(ApiBase):
     """
     {{ iface_doc }}
     """
diff --git a/src/bindings/python/templates/node.tmpl b/src/bindings/python/templates/node.tmpl
index afb5b5b7d8..179aca9611 100644
--- a/src/bindings/python/templates/node.tmpl
+++ b/src/bindings/python/templates/node.tmpl
@@ -8,11 +8,11 @@ class Node(ApiBase):
         # set empty node path temporary, needs to be resolved after the bus has been set
         super().__init__(BC_DBUS_INTERFACE, "", bus, use_systembus)
 
-        manager = self.bus.get_proxy(
+        controller = self.bus.get_proxy(
                 BC_DBUS_INTERFACE,
                 BC_OBJECT_PATH
             )
-        self.object_path = manager.GetNode(node_name)
+        self.object_path = controller.GetNode(node_name)
 
         self.node_name = node_name
 
diff --git a/src/client/method-list-units.c b/src/client/method-list-units.c
index 6ed3065194..6c06130b1a 100644
--- a/src/client/method-list-units.c
+++ b/src/client/method-list-units.c
@@ -76,7 +76,7 @@ static int method_list_units_on_all(sd_bus *api_bus, print_unit_list_fn print, c
                         api_bus,
                         NULL,
                         BC_OBJECT_PATH,
-                        MANAGER_INTERFACE,
+                        CONTROLLER_INTERFACE,
                         NODE_AND_UNIT_INFO_STRUCT_TYPESTRING,
                         &bus_parse_unit_on_node_info,
                         unit_list);
diff --git a/src/client/method-loglevel.c b/src/client/method-loglevel.c
index 56c8327afa..fb6068dd95 100644
--- a/src/client/method-loglevel.c
+++ b/src/client/method-loglevel.c
@@ -40,7 +40,7 @@ static int method_set_loglevel_on(Client *client, char *node_name, char *logleve
                                 client->api_bus,
                                 BC_INTERFACE_BASE_NAME,
                                 BC_OBJECT_PATH,
-                                MANAGER_INTERFACE,
+                                CONTROLLER_INTERFACE,
                                 "SetLogLevel",
                                 &error,
                                 &result,
diff --git a/src/client/method-metrics.c b/src/client/method-metrics.c
index 6e031fed98..626828081c 100644
--- a/src/client/method-metrics.c
+++ b/src/client/method-metrics.c
@@ -15,7 +15,7 @@ static int method_metrics_toggle(Client *client, char *method) {
                         client->api_bus,
                         BC_INTERFACE_BASE_NAME,
                         BC_OBJECT_PATH,
-                        MANAGER_INTERFACE,
+                        CONTROLLER_INTERFACE,
                         method,
                         &error,
                         &message,
diff --git a/src/client/method-monitor.c b/src/client/method-monitor.c
index 3944020ff7..94226bb581 100644
--- a/src/client/method-monitor.c
+++ b/src/client/method-monitor.c
@@ -141,7 +141,7 @@ static int method_monitor_units_on_nodes(Client *client, char *node, char *units
                         client->api_bus,
                         BC_INTERFACE_BASE_NAME,
                         BC_OBJECT_PATH,
-                        MANAGER_INTERFACE,
+                        CONTROLLER_INTERFACE,
                         "CreateMonitor",
                         &error,
                         &reply,
diff --git a/src/client/method-status.c b/src/client/method-status.c
index 20c82ab1c9..c421825c4d 100644
--- a/src/client/method-status.c
+++ b/src/client/method-status.c
@@ -549,7 +549,7 @@ static int method_print_node_status(Client *client, char *node_name, bool do_wat
                         client->api_bus,
                         BC_INTERFACE_BASE_NAME,
                         BC_OBJECT_PATH,
-                        MANAGER_INTERFACE,
+                        CONTROLLER_INTERFACE,
                         "ListNodes",
                         &error,
                         &reply,
diff --git a/src/client/method-unit-actions.c b/src/client/method-unit-actions.c
index 2b78f30a9a..76162bf567 100644
--- a/src/client/method-unit-actions.c
+++ b/src/client/method-unit-actions.c
@@ -21,8 +21,8 @@ static int method_lifecycle_action_on(Client *client, char *node_name, char *uni
                         client->api_bus,
                         NULL,
                         BC_INTERFACE_BASE_NAME,
-                        BC_MANAGER_OBJECT_PATH,
-                        MANAGER_INTERFACE,
+                        BC_CONTROLLER_OBJECT_PATH,
+                        CONTROLLER_INTERFACE,
                         "JobRemoved",
                         match_job_removed_signal,
                         client);
diff --git a/src/manager/manager.c b/src/controller/controller.c
similarity index 63%
rename from src/manager/manager.c
rename to src/controller/controller.c
index 4e3b23a351..1cca136622 100644
--- a/src/manager/manager.c
+++ b/src/controller/controller.c
@@ -11,15 +11,15 @@
 #include "libbluechi/log/log.h"
 #include "libbluechi/service/shutdown.h"
 
+#include "controller.h"
 #include "job.h"
-#include "manager.h"
 #include "metrics.h"
 #include "monitor.h"
 #include "node.h"
 
 #define DEBUG_MESSAGES 0
 
-Manager *manager_new(void) {
+Controller *controller_new(void) {
         int r = 0;
         _cleanup_sd_event_ sd_event *event = NULL;
         r = sd_event_default(&event);
@@ -40,81 +40,81 @@ Manager *manager_new(void) {
                 return NULL;
         }
 
-        Manager *manager = malloc0(sizeof(Manager));
-        if (manager != NULL) {
-                manager->ref_count = 1;
-                manager->api_bus_service_name = steal_pointer(&service_name);
-                manager->event = steal_pointer(&event);
-                manager->metrics_enabled = false;
-                manager->number_of_nodes = 0;
-                manager->number_of_nodes_online = 0;
-                manager->peer_socket_options = steal_pointer(&socket_opts);
-                LIST_HEAD_INIT(manager->nodes);
-                LIST_HEAD_INIT(manager->anonymous_nodes);
-                LIST_HEAD_INIT(manager->jobs);
-                LIST_HEAD_INIT(manager->monitors);
-                LIST_HEAD_INIT(manager->all_subscriptions);
+        Controller *controller = malloc0(sizeof(Controller));
+        if (controller != NULL) {
+                controller->ref_count = 1;
+                controller->api_bus_service_name = steal_pointer(&service_name);
+                controller->event = steal_pointer(&event);
+                controller->metrics_enabled = false;
+                controller->number_of_nodes = 0;
+                controller->number_of_nodes_online = 0;
+                controller->peer_socket_options = steal_pointer(&socket_opts);
+                LIST_HEAD_INIT(controller->nodes);
+                LIST_HEAD_INIT(controller->anonymous_nodes);
+                LIST_HEAD_INIT(controller->jobs);
+                LIST_HEAD_INIT(controller->monitors);
+                LIST_HEAD_INIT(controller->all_subscriptions);
         }
 
-        return manager;
+        return controller;
 }
 
-Manager *manager_ref(Manager *manager) {
-        manager->ref_count++;
-        return manager;
+Controller *controller_ref(Controller *controller) {
+        controller->ref_count++;
+        return controller;
 }
 
-void manager_unref(Manager *manager) {
-        assert(manager->ref_count > 0);
+void controller_unref(Controller *controller) {
+        assert(controller->ref_count > 0);
 
-        manager->ref_count--;
-        if (manager->ref_count != 0) {
+        controller->ref_count--;
+        if (controller->ref_count != 0) {
                 return;
         }
 
-        bc_log_debug("Finalizing manager");
+        bc_log_debug("Finalizing controller");
 
-        /* These are removed in manager_stop */
-        assert(LIST_IS_EMPTY(manager->jobs));
-        assert(LIST_IS_EMPTY(manager->all_subscriptions));
-        assert(LIST_IS_EMPTY(manager->monitors));
-        assert(LIST_IS_EMPTY(manager->nodes));
-        assert(LIST_IS_EMPTY(manager->anonymous_nodes));
+        /* These are removed in controller_stop */
+        assert(LIST_IS_EMPTY(controller->jobs));
+        assert(LIST_IS_EMPTY(controller->all_subscriptions));
+        assert(LIST_IS_EMPTY(controller->monitors));
+        assert(LIST_IS_EMPTY(controller->nodes));
+        assert(LIST_IS_EMPTY(controller->anonymous_nodes));
 
-        if (manager->config) {
-                cfg_dispose(manager->config);
-                manager->config = NULL;
+        if (controller->config) {
+                cfg_dispose(controller->config);
+                controller->config = NULL;
         }
 
-        sd_event_unrefp(&manager->event);
+        sd_event_unrefp(&controller->event);
 
-        free_and_null(manager->api_bus_service_name);
-        free_and_null(manager->peer_socket_options);
+        free_and_null(controller->api_bus_service_name);
+        free_and_null(controller->peer_socket_options);
 
-        sd_event_source_unrefp(&manager->node_connection_source);
+        sd_event_source_unrefp(&controller->node_connection_source);
 
-        sd_bus_slot_unrefp(&manager->name_owner_changed_slot);
-        sd_bus_slot_unrefp(&manager->filter_slot);
-        sd_bus_slot_unrefp(&manager->manager_slot);
-        sd_bus_slot_unrefp(&manager->metrics_slot);
-        sd_bus_unrefp(&manager->api_bus);
+        sd_bus_slot_unrefp(&controller->name_owner_changed_slot);
+        sd_bus_slot_unrefp(&controller->filter_slot);
+        sd_bus_slot_unrefp(&controller->controller_slot);
+        sd_bus_slot_unrefp(&controller->metrics_slot);
+        sd_bus_unrefp(&controller->api_bus);
 
-        free(manager);
+        free(controller);
 }
 
-void manager_add_subscription(Manager *manager, Subscription *sub) {
+void controller_add_subscription(Controller *controller, Subscription *sub) {
         Node *node = NULL;
 
-        LIST_APPEND(all_subscriptions, manager->all_subscriptions, subscription_ref(sub));
+        LIST_APPEND(all_subscriptions, controller->all_subscriptions, subscription_ref(sub));
 
         if (subscription_has_node_wildcard(sub)) {
-                LIST_FOREACH(nodes, node, manager->nodes) {
+                LIST_FOREACH(nodes, node, controller->nodes) {
                         node_subscribe(node, sub);
                 }
                 return;
         }
 
-        node = manager_find_node(manager, sub->node);
+        node = controller_find_node(controller, sub->node);
         if (node) {
                 node_subscribe(node, sub);
         } else {
@@ -122,28 +122,28 @@ void manager_add_subscription(Manager *manager, Subscription *sub) {
         }
 }
 
-void manager_remove_subscription(Manager *manager, Subscription *sub) {
+void controller_remove_subscription(Controller *controller, Subscription *sub) {
         Node *node = NULL;
 
         if (subscription_has_node_wildcard(sub)) {
-                LIST_FOREACH(nodes, node, manager->nodes) {
+                LIST_FOREACH(nodes, node, controller->nodes) {
                         node_unsubscribe(node, sub);
                 }
         } else {
-                node = manager_find_node(manager, sub->node);
+                node = controller_find_node(controller, sub->node);
                 if (node) {
                         node_unsubscribe(node, sub);
                 }
         }
 
-        LIST_REMOVE(all_subscriptions, manager->all_subscriptions, sub);
+        LIST_REMOVE(all_subscriptions, controller->all_subscriptions, sub);
         subscription_unref(sub);
 }
 
-Node *manager_find_node(Manager *manager, const char *name) {
+Node *controller_find_node(Controller *controller, const char *name) {
         Node *node = NULL;
 
-        LIST_FOREACH(nodes, node, manager->nodes) {
+        LIST_FOREACH(nodes, node, controller->nodes) {
                 if (strcmp(node->name, name) == 0) {
                         return node;
                 }
@@ -153,10 +153,10 @@ Node *manager_find_node(Manager *manager, const char *name) {
 }
 
 
-Node *manager_find_node_by_path(Manager *manager, const char *path) {
+Node *controller_find_node_by_path(Controller *controller, const char *path) {
         Node *node = NULL;
 
-        LIST_FOREACH(nodes, node, manager->nodes) {
+        LIST_FOREACH(nodes, node, controller->nodes) {
                 if (streq(node->object_path, path)) {
                         return node;
                 }
@@ -165,30 +165,30 @@ Node *manager_find_node_by_path(Manager *manager, const char *path) {
         return NULL;
 }
 
-void manager_remove_node(Manager *manager, Node *node) {
+void controller_remove_node(Controller *controller, Node *node) {
         if (node->name) {
-                manager->number_of_nodes--;
-                LIST_REMOVE(nodes, manager->nodes, node);
+                controller->number_of_nodes--;
+                LIST_REMOVE(nodes, controller->nodes, node);
         } else {
-                LIST_REMOVE(nodes, manager->anonymous_nodes, node);
+                LIST_REMOVE(nodes, controller->anonymous_nodes, node);
         }
 
         if (node_is_online(node)) {
                 node_shutdown(node);
-                manager->number_of_nodes_online--;
+                controller->number_of_nodes_online--;
         }
         node_unref(node);
 }
 
-bool manager_add_job(Manager *manager, Job *job) {
+bool controller_add_job(Controller *controller, Job *job) {
         if (!job_export(job)) {
                 return false;
         }
 
         int r = sd_bus_emit_signal(
-                        manager->api_bus,
-                        BC_MANAGER_OBJECT_PATH,
-                        MANAGER_INTERFACE,
+                        controller->api_bus,
+                        BC_CONTROLLER_OBJECT_PATH,
+                        CONTROLLER_INTERFACE,
                         "JobNew",
                         "uo",
                         job->id,
@@ -198,15 +198,15 @@ bool manager_add_job(Manager *manager, Job *job) {
                 return false;
         }
 
-        LIST_APPEND(jobs, manager->jobs, job_ref(job));
+        LIST_APPEND(jobs, controller->jobs, job_ref(job));
         return true;
 }
 
-void manager_remove_job(Manager *manager, Job *job, const char *result) {
+void controller_remove_job(Controller *controller, Job *job, const char *result) {
         int r = sd_bus_emit_signal(
-                        manager->api_bus,
-                        BC_MANAGER_OBJECT_PATH,
-                        MANAGER_INTERFACE,
+                        controller->api_bus,
+                        BC_CONTROLLER_OBJECT_PATH,
+                        CONTROLLER_INTERFACE,
                         "JobRemoved",
                         "uosss",
                         job->id,
@@ -219,17 +219,17 @@ void manager_remove_job(Manager *manager, Job *job, const char *result) {
                 /* We can't really return a failure here */
         }
 
-        LIST_REMOVE(jobs, manager->jobs, job);
-        if (manager->metrics_enabled && streq(job->type, "start")) {
+        LIST_REMOVE(jobs, controller->jobs, job);
+        if (controller->metrics_enabled && streq(job->type, "start")) {
                 metrics_produce_job_report(job);
         }
         job_unref(job);
 }
 
-void manager_job_state_changed(Manager *manager, uint32_t job_id, const char *state) {
+void controller_job_state_changed(Controller *controller, uint32_t job_id, const char *state) {
         JobState new_state = job_state_from_string(state);
         Job *job = NULL;
-        LIST_FOREACH(jobs, job, manager->jobs) {
+        LIST_FOREACH(jobs, job, controller->jobs) {
                 if (job->id == job_id) {
                         job_set_state(job, new_state);
                         break;
@@ -237,69 +237,69 @@ void manager_job_state_changed(Manager *manager, uint32_t job_id, const char *st
         }
 }
 
-void manager_finish_job(Manager *manager, uint32_t job_id, const char *result) {
+void controller_finish_job(Controller *controller, uint32_t job_id, const char *result) {
         Job *job = NULL;
-        LIST_FOREACH(jobs, job, manager->jobs) {
+        LIST_FOREACH(jobs, job, controller->jobs) {
                 if (job->id == job_id) {
-                        if (manager->metrics_enabled) {
+                        if (controller->metrics_enabled) {
                                 job->job_end_micros = get_time_micros();
                         }
-                        manager_remove_job(manager, job, result);
+                        controller_remove_job(controller, job, result);
                         break;
                 }
         }
 }
 
-Node *manager_add_node(Manager *manager, const char *name) {
-        _cleanup_node_ Node *node = node_new(manager, name);
+Node *controller_add_node(Controller *controller, const char *name) {
+        _cleanup_node_ Node *node = node_new(controller, name);
         if (node == NULL) {
                 return NULL;
         }
 
         if (name) {
-                manager->number_of_nodes++;
-                LIST_APPEND(nodes, manager->nodes, node);
+                controller->number_of_nodes++;
+                LIST_APPEND(nodes, controller->nodes, node);
         } else {
-                LIST_APPEND(nodes, manager->anonymous_nodes, node);
+                LIST_APPEND(nodes, controller->anonymous_nodes, node);
         }
 
         return steal_pointer(&node);
 }
 
-bool manager_set_port(Manager *manager, const char *port_s) {
+bool controller_set_port(Controller *controller, const char *port_s) {
         uint16_t port = 0;
 
         if (!parse_port(port_s, &port)) {
                 bc_log_errorf("Invalid port format '%s'", port_s);
                 return false;
         }
-        manager->port = port;
+        controller->port = port;
         return true;
 }
 
-bool manager_parse_config(Manager *manager, const char *configfile) {
+bool controller_parse_config(Controller *controller, const char *configfile) {
         int result = 0;
 
-        result = cfg_initialize(&manager->config);
+        result = cfg_initialize(&controller->config);
         if (result != 0) {
                 fprintf(stderr, "Error initializing configuration: '%s'.\n", strerror(-result));
                 return false;
         }
 
-        result = cfg_manager_def_conf(manager->config);
+        result = cfg_controller_def_conf(controller->config);
         if (result != 0) {
-                fprintf(stderr, "Failed to set default settings for manager: %s", strerror(-result));
+                fprintf(stderr, "Failed to set default settings for controller: %s", strerror(-result));
                 return false;
         }
 
         result = cfg_load_complete_configuration(
-                        manager->config, CFG_BC_DEFAULT_CONFIG, CFG_ETC_BC_CONF, CFG_ETC_BC_CONF_DIR);
+                        controller->config, CFG_BC_DEFAULT_CONFIG, CFG_ETC_BC_CONF, CFG_ETC_BC_CONF_DIR);
         if (result != 0) {
                 return false;
         }
 
         if (configfile != NULL) {
-                result = cfg_load_from_file(manager->config, configfile);
+                result = cfg_load_from_file(controller->config, configfile);
                 if (result < 0) {
                         fprintf(stderr,
                                 "Error loading configuration file '%s': '%s'.\n",
@@ -313,17 +313,17 @@ bool manager_parse_config(Manager *manager, const char *configfile) {
         }
 
         // set logging configuration
-        bc_log_init(manager->config);
+        bc_log_init(controller->config);
 
         const char *port = NULL;
-        port = cfg_get_value(manager->config, CFG_MANAGER_PORT);
+        port = cfg_get_value(controller->config, CFG_CONTROLLER_PORT);
         if (port) {
-                if (!manager_set_port(manager, port)) {
+                if (!controller_set_port(controller, port)) {
                         return false;
                 }
         }
 
-        const char *expected_nodes = cfg_get_value(manager->config, CFG_ALLOWED_NODE_NAMES);
+        const char *expected_nodes = cfg_get_value(controller->config, CFG_ALLOWED_NODE_NAMES);
         if (expected_nodes) {
                 char *saveptr = NULL;
 
@@ -333,8 +333,8 @@ bool manager_parse_config(Manager *manager, const char *configfile) {
 
                 char *name = strtok_r(expected_nodes_cpy, ",", &saveptr);
                 while (name != NULL) {
-                        if (manager_find_node(manager, name) == NULL) {
-                                manager_add_node(manager, name);
+                        if (controller_find_node(controller, name) == NULL) {
+                                controller_add_node(controller, name);
                         }
 
                         name = strtok_r(NULL, ",", &saveptr);
@@ -342,36 +342,36 @@ bool manager_parse_config(Manager *manager, const char *configfile) {
         }
 
         /* Set socket options used for peer connections with the agents */
-        const char *keepidle = cfg_get_value(manager->config, CFG_TCP_KEEPALIVE_TIME);
+        const char *keepidle = cfg_get_value(controller->config, CFG_TCP_KEEPALIVE_TIME);
         if (keepidle) {
-                if (socket_options_set_tcp_keepidle(manager->peer_socket_options, keepidle) < 0) {
+                if (socket_options_set_tcp_keepidle(controller->peer_socket_options, keepidle) < 0) {
                         bc_log_error("Failed to set TCP KEEPIDLE");
                         return false;
                 }
         }
-        const char *keepintvl = cfg_get_value(manager->config, CFG_TCP_KEEPALIVE_INTERVAL);
+        const char *keepintvl = cfg_get_value(controller->config, CFG_TCP_KEEPALIVE_INTERVAL);
         if (keepintvl) {
-                if (socket_options_set_tcp_keepintvl(manager->peer_socket_options, keepintvl) < 0) {
+                if (socket_options_set_tcp_keepintvl(controller->peer_socket_options, keepintvl) < 0) {
                         bc_log_error("Failed to set TCP KEEPINTVL");
                         return false;
                 }
         }
-        const char *keepcnt = cfg_get_value(manager->config, CFG_TCP_KEEPALIVE_COUNT);
+        const char *keepcnt = cfg_get_value(controller->config, CFG_TCP_KEEPALIVE_COUNT);
         if (keepcnt) {
-                if (socket_options_set_tcp_keepcnt(manager->peer_socket_options, keepcnt) < 0) {
+                if (socket_options_set_tcp_keepcnt(controller->peer_socket_options, keepcnt) < 0) {
                         bc_log_error("Failed to set TCP KEEPCNT");
                         return false;
                 }
         }
         if (socket_options_set_ip_recverr(
-                            manager->peer_socket_options,
-                            cfg_get_bool_value(manager->config, CFG_IP_RECEIVE_ERRORS)) < 0) {
+                            controller->peer_socket_options,
+                            cfg_get_bool_value(controller->config, CFG_IP_RECEIVE_ERRORS)) < 0) {
                 bc_log_error("Failed to set IP RECVERR");
                 return false;
         }
 
 
-        _cleanup_free_ const char *dumped_cfg = cfg_dump(manager->config);
+        _cleanup_free_ const char *dumped_cfg = cfg_dump(controller->config);
         bc_log_debug_with_data("Final configuration used", "\n%s", dumped_cfg);
 
         /* TODO: Handle per-node-name option section */
@@ -379,9 +379,9 @@ bool manager_parse_config(Manager *manager, const char *configfile) {
         return true;
 }
 
-static int manager_accept_node_connection(
+static int controller_accept_node_connection(
                 UNUSED sd_event_source *source, int fd, UNUSED uint32_t revents, void *userdata) {
-        Manager *manager = userdata;
+        Controller *controller = userdata;
         Node *node = NULL;
         _cleanup_fd_ int nfd = accept_tcp_connection_request(fd);
         if (nfd < 0) {
@@ -390,28 +390,28 @@ static int manager_accept_node_connection(
         }
 
         _cleanup_sd_bus_ sd_bus *dbus_server = peer_bus_open_server(
-                        manager->event, "managed-node", BC_DBUS_NAME, steal_fd(&nfd));
+                        controller->event, "managed-node", BC_DBUS_NAME, steal_fd(&nfd));
         if (dbus_server == NULL) {
                 return -1;
         }
 
-        bus_socket_set_options(dbus_server, manager->peer_socket_options);
+        bus_socket_set_options(dbus_server, controller->peer_socket_options);
 
         /* Add anonymous node */
-        node = manager_add_node(manager, NULL);
+        node = controller_add_node(controller, NULL);
         if (node == NULL) {
                 return -1;
         }
 
         if (!node_set_agent_bus(node, dbus_server)) {
-                manager_remove_node(manager, steal_pointer(&node));
+                controller_remove_node(controller, steal_pointer(&node));
                 return -1;
         }
 
         return 0;
 }
 
-static bool manager_setup_node_connection_handler(Manager *manager) {
+static bool controller_setup_node_connection_handler(Controller *controller) {
         int r = 0;
         int accept_fd = -1;
         _cleanup_fd_ int tcp_fd = -1;
@@ -426,7 +426,7 @@ static bool manager_setup_node_connection_handler(Manager *manager) {
         if (n == 1) {
                 accept_fd = SD_LISTEN_FDS_START;
         } else {
-                tcp_fd = create_tcp_socket(manager->port);
+                tcp_fd = create_tcp_socket(controller->port);
                 if (tcp_fd < 0) {
                         bc_log_errorf("Failed to create TCP socket: %s", strerror(errno));
                         return false;
@@ -435,7 +435,12 @@ static bool manager_setup_node_connection_handler(Manager *manager) {
         }
 
         r = sd_event_add_io(
-                        manager->event, &event_source, accept_fd, EPOLLIN, manager_accept_node_connection, manager);
+                        controller->event,
+                        &event_source,
+                        accept_fd,
+                        EPOLLIN,
+                        controller_accept_node_connection,
+                        controller);
         if (r < 0) {
                 bc_log_errorf("Failed to add io event: %s", strerror(-r));
                 return false;
@@ -451,17 +456,17 @@ static bool manager_setup_node_connection_handler(Manager *manager) {
 
         (void) sd_event_source_set_description(event_source, "node-accept-socket");
 
-        manager->node_connection_source = steal_pointer(&event_source);
+        controller->node_connection_source = steal_pointer(&event_source);
 
         return true;
 }
 
 /************************************************************************
- ****** org.eclipse.bluechi.Manager.Ping ******************
+ ****** org.eclipse.bluechi.Controller.Ping ******************
  ************************************************************************/
 
 /* This is a test method for now, it just returns what you passed */
-static int manager_method_ping(sd_bus_message *m, UNUSED void *userdata, UNUSED sd_bus_error *ret_error) {
+static int controller_method_ping(sd_bus_message *m, UNUSED void *userdata, UNUSED sd_bus_error *ret_error) {
         const char *arg = NULL;
 
         int r = sd_bus_message_read(m, "s", &arg);
@@ -473,7 +478,7 @@ static int manager_method_ping(sd_bus_message *m, UNUSED void *userdata, UNUSED
 
 
 /************************************************************************
- ************** org.eclipse.bluechi.Manager.ListUnits *****
+ ************** org.eclipse.bluechi.Controller.ListUnits *****
  ************************************************************************/
 
 typedef struct ListUnitsRequest {
@@ -510,7 +515,7 @@ static void list_unit_request_freep(ListUnitsRequest **reqp) {
 #define _cleanup_list_unit_request_ _cleanup_(list_unit_request_freep)
 
 
-static int manager_method_list_units_encode_reply(ListUnitsRequest *req, sd_bus_message *reply) {
+static int controller_method_list_units_encode_reply(ListUnitsRequest *req, sd_bus_message *reply) {
         int r = sd_bus_message_open_container(reply, SD_BUS_TYPE_ARRAY, NODE_AND_UNIT_INFO_STRUCT_TYPESTRING);
         if (r < 0) {
                 return r;
@@ -581,7 +586,7 @@ static int manager_method_list_units_encode_reply(ListUnitsRequest *req, sd_bus_
 }
 
 
-static void manager_method_list_units_done(ListUnitsRequest *req) {
+static void controller_method_list_units_done(ListUnitsRequest *req) {
         /* All sub_req-requests are done, collect results and free when done */
         UNUSED _cleanup_list_unit_request_ ListUnitsRequest *free_me = req;
 
@@ -596,7 +601,7 @@ static void manager_method_list_units_done(ListUnitsRequest *req) {
                 return;
         }
 
-        r = manager_method_list_units_encode_reply(req, reply);
+        r = controller_method_list_units_encode_reply(req, reply);
         if (r < 0) {
                 sd_bus_reply_method_errorf(
                                 req->request_message,
@@ -613,13 +618,13 @@ static void manager_method_list_units_done(ListUnitsRequest *req) {
         }
 }
 
-static void manager_method_list_units_maybe_done(ListUnitsRequest *req) {
+static void controller_method_list_units_maybe_done(ListUnitsRequest *req) {
         if (req->n_done == req->n_sub_req) {
-                manager_method_list_units_done(req);
+                controller_method_list_units_done(req);
         }
 }
 
-static int manager_list_units_callback(
+static int controller_list_units_callback(
                 AgentRequest *agent_req, sd_bus_message *m, UNUSED sd_bus_error *ret_error) {
         ListUnitsRequest *req = agent_req->userdata;
         int i = 0;
@@ -635,27 +640,27 @@ static int manager_list_units_callback(
         req->sub_req[i].m = sd_bus_message_ref(m);
         req->n_done++;
 
-        manager_method_list_units_maybe_done(req);
+        controller_method_list_units_maybe_done(req);
 
         return 0;
 }
 
 
-static int manager_method_list_units(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
-        Manager *manager = userdata;
+static int controller_method_list_units(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
+        Controller *controller = userdata;
         ListUnitsRequest *req = NULL;
         Node *node = NULL;
 
-        req = malloc0_array(sizeof(*req), sizeof(req->sub_req[0]), manager->number_of_nodes);
+        req = malloc0_array(sizeof(*req), sizeof(req->sub_req[0]), controller->number_of_nodes);
         if (req == NULL) {
                 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_NO_MEMORY, "Out of memory");
         }
         req->request_message = sd_bus_message_ref(m);
 
         int i = 0;
-        LIST_FOREACH(nodes, node, manager->nodes) {
+        LIST_FOREACH(nodes, node, controller->nodes) {
                 _cleanup_agent_request_ AgentRequest *agent_req = node_request_list_units(
-                                node, manager_list_units_callback, req, NULL);
+                                node, controller_list_units_callback, req, NULL);
                 if (agent_req) {
                         req->sub_req[i].agent_req = steal_pointer(&agent_req);
                         req->sub_req[i].node = node_ref(node);
@@ -665,23 +670,23 @@ static int manager_method_list_units(sd_bus_message *m, void *userdata, UNUSED s
         }
 
 // Disabling -Wanalyzer-malloc-leak temporarily due to false-positive
-//      Leak detected is based on the assumption that manager_method_list_units_maybe_done is only
+//      Leak detected is based on the assumption that controller_method_list_units_maybe_done is only
 //      called once directly after iterating over the list - when the conditional to free req is false.
-//      However, it does not take into account that manager_list_units_callback calls it for each node.
+//      However, it does not take into account that controller_list_units_callback calls it for each node.
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
 
-        manager_method_list_units_maybe_done(req);
+        controller_method_list_units_maybe_done(req);
 
         return 1;
 }
 #pragma GCC diagnostic pop
 
 /************************************************************************
- ***** org.eclipse.bluechi.Manager.ListNodes **************
+ ***** org.eclipse.bluechi.Controller.ListNodes **************
  ************************************************************************/
 
-static int manager_method_list_encode_node(sd_bus_message *reply, Node *node) {
+static int controller_method_list_encode_node(sd_bus_message *reply, Node *node) {
         int r = sd_bus_message_open_container(reply, SD_BUS_TYPE_STRUCT, "sos");
         if (r < 0) {
                 return r;
@@ -694,8 +699,8 @@ static int manager_method_list_encode_node(sd_bus_message *reply, Node *node) {
         return sd_bus_message_close_container(reply);
 }
 
-static int manager_method_list_nodes(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
-        Manager *manager = userdata;
+static int controller_method_list_nodes(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
+        Controller *controller = userdata;
         _cleanup_sd_bus_message_ sd_bus_message *reply = NULL;
         Node *node = NULL;
 
@@ -717,8 +722,8 @@ static int manager_method_list_nodes(sd_bus_message *m, void *userdata, UNUSED s
                                 strerror(-r));
         }
 
-        LIST_FOREACH(nodes, node, manager->nodes) {
-                r = manager_method_list_encode_node(reply, node);
+        LIST_FOREACH(nodes, node, controller->nodes) {
+                r = controller_method_list_encode_node(reply, node);
                 if (r < 0) {
                         return sd_bus_reply_method_errorf(
                                         reply, SD_BUS_ERROR_FAILED, "Failed to encode a node: %s", strerror(-r));
@@ -735,11 +740,11 @@ static int manager_method_list_nodes(sd_bus_message *m, void *userdata, UNUSED s
 }
 
 /************************************************************************
- **** org.eclipse.bluechi.Manager.GetNode *****************
+ **** org.eclipse.bluechi.Controller.GetNode *****************
  ************************************************************************/
 
-static int manager_method_get_node(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
-        Manager *manager = userdata;
+static int controller_method_get_node(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
+        Controller *controller = userdata;
         _cleanup_sd_bus_message_ sd_bus_message *reply = NULL;
         Node *node = NULL;
         const char *node_name = NULL;
@@ -750,7 +755,7 @@ static int manager_method_get_node(sd_bus_message *m, void *userdata, UNUSED sd_
                                 m, SD_BUS_ERROR_INVALID_ARGS, "Invalid argument for the node name");
         }
 
-        node = manager_find_node(manager, node_name);
+        node = controller_find_node(controller, node_name);
         if (node == NULL) {
                 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_SERVICE_UNKNOWN, "Node not found");
         }
@@ -777,14 +782,14 @@ static int manager_method_get_node(sd_bus_message *m, void *userdata, UNUSED sd_
 }
 
 /************************************************************************
- ***** org.eclipse.bluechi.Manager.CreateMonitor **********
+ ***** org.eclipse.bluechi.Controller.CreateMonitor **********
  ************************************************************************/
 
-static int manager_method_create_monitor(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
-        Manager *manager = userdata;
+static int controller_method_create_monitor(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
+        Controller *controller = userdata;
         _cleanup_sd_bus_message_ sd_bus_message *reply = NULL;
 
-        _cleanup_monitor_ Monitor *monitor = monitor_new(manager, sd_bus_message_get_sender(m));
+        _cleanup_monitor_ Monitor *monitor = monitor_new(controller, sd_bus_message_get_sender(m));
         if (monitor == NULL) {
                 return sd_bus_reply_method_errorf(reply, SD_BUS_ERROR_FAILED, "Failed to create new monitor");
         }
@@ -817,28 +822,28 @@ static int manager_method_create_monitor(sd_bus_message *m, void *userdata, UNUS
         }
 
         /* We reported it to the client, now keep it alive and keep track of it */
-        LIST_APPEND(monitors, manager->monitors, monitor_ref(monitor));
+        LIST_APPEND(monitors, controller->monitors, monitor_ref(monitor));
         return 1;
 }
 
 /************************************************************************
- ***** org.eclipse.bluechi.Manager.EnableMetrics **********
+ ***** org.eclipse.bluechi.Controller.EnableMetrics **********
  ************************************************************************/
-static int manager_method_metrics_enable(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
-        Manager *manager = userdata;
+static int controller_method_metrics_enable(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
+        Controller *controller = userdata;
         Node *node = NULL;
         int r = 0;
-        if (manager->metrics_enabled) {
+        if (controller->metrics_enabled) {
                 return sd_bus_reply_method_errorf(
                                 m, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Metrics already enabled");
         }
-        r = metrics_export(manager);
+        r = metrics_export(controller);
         if (r < 0) {
                 return sd_bus_reply_method_errorf(
                                 m, SD_BUS_ERROR_FAILED, "Failed to register metrics service: %s", strerror(-r));
         }
-        manager->metrics_enabled = true;
-        LIST_FOREACH(nodes, node, manager->nodes) {
+        controller->metrics_enabled = true;
+        LIST_FOREACH(nodes, node, controller->nodes) {
                 node_enable_metrics(node);
         }
         bc_log_debug("Metrics enabled");
@@ -846,19 +851,19 @@ static int manager_method_metrics_enable(sd_bus_message *m, void *userdata, UNUS
 }
 
 /************************************************************************
- ***** org.eclipse.bluechi.Manager.DisableMetrics *********
+ ***** org.eclipse.bluechi.Controller.DisableMetrics *********
  ************************************************************************/
-static int manager_method_metrics_disable(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
-        Manager *manager = userdata;
+static int controller_method_metrics_disable(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
+        Controller *controller = userdata;
         Node *node = NULL;
-        if (!manager->metrics_enabled) {
+        if (!controller->metrics_enabled) {
                 return sd_bus_reply_method_errorf(
                                 m, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Metrics already disabled");
         }
-        sd_bus_slot_unrefp(&manager->metrics_slot);
-        manager->metrics_slot = NULL;
-        manager->metrics_enabled = false;
-        LIST_FOREACH(nodes, node, manager->nodes) {
+        sd_bus_slot_unrefp(&controller->metrics_slot);
+        controller->metrics_slot = NULL;
+        controller->metrics_enabled = false;
+        LIST_FOREACH(nodes, node, controller->nodes) {
                 node_disable_metrics(node);
         }
         bc_log_debug("Metrics disabled");
@@ -866,10 +871,11 @@ static int manager_method_metrics_disable(sd_bus_message *m, void *userdata, UNU
 }
 
 /*************************************************************************
- *** org.eclipse.bluechi.Manager.SetLogLevel ***************
+ *** org.eclipse.bluechi.Controller.SetLogLevel ***************
  *************************************************************************/
 
-static int manager_method_set_log_level(sd_bus_message *m, UNUSED void *userdata, UNUSED sd_bus_error *ret_error) {
+static int controller_method_set_log_level(
+                sd_bus_message *m, UNUSED void *userdata, UNUSED sd_bus_error *ret_error) {
         const char *level = NULL;
 
         int r = sd_bus_message_read(m, "s", &level);
@@ -889,35 +895,39 @@ static int manager_method_set_log_level(sd_bus_message *m, UNUSED void *userdata
 }
 
 /********************************************************
- **** org.eclipse.bluechi.Manager.Status ****************
+ **** org.eclipse.bluechi.Controller.Status ****************
  ********************************************************/
 
-static char *manager_get_system_status(Manager *manager) {
-        if (manager->number_of_nodes_online == 0) {
+static char *controller_get_system_status(Controller *controller) {
+        if (controller->number_of_nodes_online == 0) {
                 return "down";
-        } else if (manager->number_of_nodes_online == manager->number_of_nodes) {
+        } else if (controller->number_of_nodes_online == controller->number_of_nodes) {
                 return "up";
         }
         return "degraded";
 }
 
-void manager_check_system_status(Manager *manager, int prev_number_of_nodes_online) {
-        int diff = manager->number_of_nodes_online - prev_number_of_nodes_online;
+void controller_check_system_status(Controller *controller, int prev_number_of_nodes_online) {
+        int diff = controller->number_of_nodes_online - prev_number_of_nodes_online;
         // clang-format off
         if ((prev_number_of_nodes_online == 0) ||                                       // at least one node online
-                (prev_number_of_nodes_online == manager->number_of_nodes) ||            // at least one node offline
-                ((prev_number_of_nodes_online + diff) == manager->number_of_nodes) ||   // all nodes online
+                (prev_number_of_nodes_online == controller->number_of_nodes) ||            // at least one node offline
+                ((prev_number_of_nodes_online + diff) == controller->number_of_nodes) ||   // all nodes online
                 ((prev_number_of_nodes_online + diff) == 0)) {                          // all nodes offline
                 // clang-format on
                 int r = sd_bus_emit_properties_changed(
-                                manager->api_bus, BC_MANAGER_OBJECT_PATH, MANAGER_INTERFACE, "Status", NULL);
+                                controller->api_bus,
+                                BC_CONTROLLER_OBJECT_PATH,
+                                CONTROLLER_INTERFACE,
+                                "Status",
+                                NULL);
                 if (r < 0) {
                         bc_log_errorf("Failed to emit status property changed: %s", strerror(-r));
                 }
         }
 }
 
-static int manager_property_get_status(
+static int controller_property_get_status(
                 UNUSED sd_bus *bus,
                 UNUSED const char *path,
                 UNUSED const char *interface,
@@ -925,21 +935,21 @@ static int manager_property_get_status(
                 sd_bus_message *reply,
                 void *userdata,
                 UNUSED sd_bus_error *ret_error) {
-        Manager *manager = userdata;
+        Controller *controller = userdata;
 
-        return sd_bus_message_append(reply, "s", manager_get_system_status(manager));
+        return sd_bus_message_append(reply, "s", controller_get_system_status(controller));
 }
 
-static const sd_bus_vtable manager_vtable[] = {
+static const sd_bus_vtable controller_vtable[] = {
         SD_BUS_VTABLE_START(0),
-        SD_BUS_METHOD("Ping", "s", "s", manager_method_ping, 0),
-        SD_BUS_METHOD("ListUnits", "", NODE_AND_UNIT_INFO_STRUCT_ARRAY_TYPESTRING, manager_method_list_units, 0),
-        SD_BUS_METHOD("ListNodes", "", "a(sos)", manager_method_list_nodes, 0),
-        SD_BUS_METHOD("GetNode", "s", "o", manager_method_get_node, 0),
-        SD_BUS_METHOD("CreateMonitor", "", "o", manager_method_create_monitor, 0),
-        SD_BUS_METHOD("SetLogLevel", "s", "", manager_method_set_log_level, 0),
-        SD_BUS_METHOD("EnableMetrics", "", "", manager_method_metrics_enable, 0),
-        SD_BUS_METHOD("DisableMetrics", "", "", manager_method_metrics_disable, 0),
+        SD_BUS_METHOD("Ping", "s", "s", controller_method_ping, 0),
+        SD_BUS_METHOD("ListUnits", "", NODE_AND_UNIT_INFO_STRUCT_ARRAY_TYPESTRING, controller_method_list_units, 0),
+        SD_BUS_METHOD("ListNodes", "", "a(sos)", controller_method_list_nodes, 0),
+        SD_BUS_METHOD("GetNode", "s", "o", controller_method_get_node, 0),
+        SD_BUS_METHOD("CreateMonitor", "", "o", controller_method_create_monitor, 0),
+        SD_BUS_METHOD("SetLogLevel", "s", "", controller_method_set_log_level, 0),
+        SD_BUS_METHOD("EnableMetrics", "", "", controller_method_metrics_enable, 0),
+        SD_BUS_METHOD("DisableMetrics", "", "", controller_method_metrics_disable, 0),
         SD_BUS_SIGNAL_WITH_NAMES("JobNew", "uo", SD_BUS_PARAM(id) SD_BUS_PARAM(job), 0),
         SD_BUS_SIGNAL_WITH_NAMES(
                         "JobRemoved",
@@ -947,12 +957,12 @@ static const sd_bus_vtable manager_vtable[] = {
                         SD_BUS_PARAM(id) SD_BUS_PARAM(job) SD_BUS_PARAM(node) SD_BUS_PARAM(unit)
                                         SD_BUS_PARAM(result),
                         0),
-        SD_BUS_PROPERTY("Status", "s", manager_property_get_status, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+        SD_BUS_PROPERTY("Status", "s", controller_property_get_status, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
         SD_BUS_VTABLE_END
 };
 
-static int manager_dbus_filter(UNUSED sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
-        Manager *manager = userdata;
+static int controller_dbus_filter(UNUSED sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
+        Controller *controller = userdata;
         const char *object_path = sd_bus_message_get_path(m);
         const char *iface = sd_bus_message_get_interface(m);
 
@@ -965,7 +975,7 @@ static int manager_dbus_filter(UNUSED sd_bus_message *m, void *userdata, UNUSED
         }
 
         if (iface != NULL && streq(iface, NODE_INTERFACE)) {
-                Node *node = manager_find_node_by_path(manager, object_path);
+                Node *node = controller_find_node_by_path(controller, object_path);
 
                 /* All Node interface objects fail if the node is offline */
                 if (node && !node_has_agent(node)) {
@@ -976,26 +986,26 @@ static int manager_dbus_filter(UNUSED sd_bus_message *m, void *userdata, UNUSED
         return 0;
 }
 
-void manager_remove_monitor(Manager *manager, Monitor *monitor) {
-        LIST_REMOVE(monitors, manager->monitors, monitor);
+void controller_remove_monitor(Controller *controller, Monitor *monitor) {
+        LIST_REMOVE(monitors, controller->monitors, monitor);
         monitor_unref(monitor);
 }
 
-static void manager_client_disconnected(Manager *manager, const char *client_id) {
+static void controller_client_disconnected(Controller *controller, const char *client_id) {
         /* Free any monitors owned by the client */
 
         Monitor *monitor = NULL;
         Monitor *next_monitor = NULL;
-        LIST_FOREACH_SAFE(monitors, monitor, next_monitor, manager->monitors) {
+        LIST_FOREACH_SAFE(monitors, monitor, next_monitor, controller->monitors) {
                 if (streq(monitor->owner, client_id)) {
                         monitor_close(monitor);
-                        manager_remove_monitor(manager, monitor);
+                        controller_remove_monitor(controller, monitor);
                 }
         }
 }
 
-static int manager_name_owner_changed(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
-        Manager *manager = userdata;
+static int controller_name_owner_changed(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
+        Controller *controller = userdata;
         const char *name = NULL;
         const char *old_owner = NULL;
         const char *new_owner = NULL;
@@ -1006,89 +1016,90 @@ static int manager_name_owner_changed(sd_bus_message *m, void *userdata, UNUSED
         }
 
         if (*name == ':' && *new_owner == 0) {
-                manager_client_disconnected(manager, name);
+                controller_client_disconnected(controller, name);
         }
 
         return 0;
 }
 
-bool manager_start(Manager *manager) {
+bool controller_start(Controller *controller) {
         bc_log_infof("Starting bluechi-controller %s", CONFIG_H_BC_VERSION);
-        if (manager == NULL) {
+        if (controller == NULL) {
                 return false;
         }
 
 #ifdef USE_USER_API_BUS
-        manager->api_bus = user_bus_open(manager->event);
+        controller->api_bus = user_bus_open(controller->event);
 #else
-        manager->api_bus = system_bus_open(manager->event);
+        controller->api_bus = system_bus_open(controller->event);
 #endif
-        if (manager->api_bus == NULL) {
+        if (controller->api_bus == NULL) {
                 bc_log_error("Failed to open api dbus");
                 return false;
         }
 
         /* Export all known nodes */
         Node *node = NULL;
-        LIST_FOREACH(nodes, node, manager->nodes) {
+        LIST_FOREACH(nodes, node, controller->nodes) {
                 if (!node_export(node)) {
                         return false;
                 }
         }
 
         int r = sd_bus_request_name(
-                        manager->api_bus, manager->api_bus_service_name, SD_BUS_NAME_REPLACE_EXISTING);
+                        controller->api_bus, controller->api_bus_service_name, SD_BUS_NAME_REPLACE_EXISTING);
         if (r < 0) {
                 bc_log_errorf("Failed to acquire service name on api dbus: %s", strerror(-r));
                 return false;
         }
 
-        r = sd_bus_add_filter(manager->api_bus, &manager->filter_slot, manager_dbus_filter, manager);
+        r = sd_bus_add_filter(
+                        controller->api_bus, &controller->filter_slot, controller_dbus_filter, controller);
         if (r < 0) {
-                bc_log_errorf("Failed to add manager filter: %s", strerror(-r));
+                bc_log_errorf("Failed to add controller filter: %s", strerror(-r));
                 return false;
         }
 
         r = sd_bus_match_signal(
-                        manager->api_bus,
-                        &manager->name_owner_changed_slot,
+                        controller->api_bus,
+                        &controller->name_owner_changed_slot,
                         "org.freedesktop.DBus",
                         "/org/freedesktop/DBus",
                         "org.freedesktop.DBus",
                         "NameOwnerChanged",
-                        manager_name_owner_changed,
-                        manager);
+                        controller_name_owner_changed,
+                        controller);
         if (r < 0) {
                 bc_log_errorf("Failed to add nameloist filter: %s", strerror(-r));
                 return false;
         }
 
         r = sd_bus_add_object_vtable(
-                        manager->api_bus,
-                        &manager->manager_slot,
-                        BC_MANAGER_OBJECT_PATH,
-                        MANAGER_INTERFACE,
-                        manager_vtable,
-                        manager);
+                        controller->api_bus,
+                        &controller->controller_slot,
+                        BC_CONTROLLER_OBJECT_PATH,
+                        CONTROLLER_INTERFACE,
+                        controller_vtable,
+                        controller);
         if (r < 0) {
-                bc_log_errorf("Failed to add manager vtable: %s", strerror(-r));
+                bc_log_errorf("Failed to add controller vtable: %s", strerror(-r));
                 return false;
         }
 
-        if (!manager_setup_node_connection_handler(manager)) {
+        if (!controller_setup_node_connection_handler(controller)) {
                 return false;
         }
 
         ShutdownHook hook;
-        hook.shutdown = (ShutdownHookFn) manager_stop;
-        hook.userdata = manager;
-        r = event_loop_add_shutdown_signals(manager->event, &hook);
+        hook.shutdown = (ShutdownHookFn) controller_stop;
+        hook.userdata = controller;
+        r = event_loop_add_shutdown_signals(controller->event, &hook);
         if (r < 0) {
-                bc_log_errorf("Failed to add signals to manager event loop: %s", strerror(-r));
+                bc_log_errorf("Failed to add signals to controller event loop: %s", strerror(-r));
                 return false;
         }
 
-        r = sd_event_loop(manager->event);
+        r = sd_event_loop(controller->event);
         if (r < 0) {
                 bc_log_errorf("Starting event loop failed: %s", strerror(-r));
                 return false;
@@ -1097,43 +1108,43 @@ bool manager_start(Manager *manager) {
         return true;
 }
 
-void manager_stop(Manager *manager) {
-        if (manager == NULL) {
+void controller_stop(Controller *controller) {
+        if (controller == NULL) {
                 return;
         }
 
-        bc_log_debug("Stopping manager");
+        bc_log_debug("Stopping controller");
 
         Job *job = NULL;
         Job *next_job = NULL;
-        LIST_FOREACH_SAFE(jobs, job, next_job, manager->jobs) {
-                manager_remove_job(manager, job, "cancelled due to shutdown");
+        LIST_FOREACH_SAFE(jobs, job, next_job, controller->jobs) {
+                controller_remove_job(controller, job, "cancelled due to shutdown");
         }
 
         Subscription *sub = NULL;
         Subscription *next_sub = NULL;
-        LIST_FOREACH_SAFE(all_subscriptions, sub, next_sub, manager->all_subscriptions) {
-                manager_remove_subscription(manager, sub);
+        LIST_FOREACH_SAFE(all_subscriptions, sub, next_sub, controller->all_subscriptions) {
+                controller_remove_subscription(controller, sub);
         }
 
         Monitor *monitor = NULL;
         Monitor *next_monitor = NULL;
-        LIST_FOREACH_SAFE(monitors, monitor, next_monitor, manager->monitors) {
-                manager_remove_monitor(manager, monitor);
+        LIST_FOREACH_SAFE(monitors, monitor, next_monitor, controller->monitors) {
+                controller_remove_monitor(controller, monitor);
         }
 
         Node *node = NULL;
         Node *next_node = NULL;
-        LIST_FOREACH_SAFE(nodes, node, next_node, manager->nodes) {
-                manager_remove_node(manager, node);
+        LIST_FOREACH_SAFE(nodes, node, next_node, controller->nodes) {
+                controller_remove_node(controller, node);
         }
-        LIST_FOREACH_SAFE(nodes, node, next_node, manager->anonymous_nodes) {
-                manager_remove_node(manager, node);
+        LIST_FOREACH_SAFE(nodes, node, next_node, controller->anonymous_nodes) {
+                controller_remove_node(controller, node);
         }
 
         /*
          * We won't handle any other events incl. node disconnected since we exit the event loop
-         * right afterwards. Therefore, check the manager state and emit signal here.
+         * right afterwards. Therefore, check the controller state and emit signal here.
          */
-        manager_check_system_status(manager, manager->number_of_nodes_online);
+        controller_check_system_status(controller, controller->number_of_nodes_online);
 }
diff --git a/src/controller/controller.h b/src/controller/controller.h
new file mode 100644
index 0000000000..e1fbfcc581
--- /dev/null
+++ b/src/controller/controller.h
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include "libbluechi/common/cfg.h"
+#include "libbluechi/common/common.h"
+#include "libbluechi/socket.h"
+
+#include "types.h"
+
+struct Controller {
+        int ref_count;
+
+        uint16_t port;
+        char *api_bus_service_name;
+
+        sd_event *event;
+        sd_event_source *node_connection_source;
+
+        sd_bus *api_bus;
+        sd_bus_slot *controller_slot;
+        sd_bus_slot *filter_slot;
+        sd_bus_slot *name_owner_changed_slot;
+        sd_bus_slot *metrics_slot;
+
+        bool metrics_enabled;
+
+        SocketOptions *peer_socket_options;
+
+        int number_of_nodes;
+        int number_of_nodes_online;
+        LIST_HEAD(Node, nodes);
+        LIST_HEAD(Node, anonymous_nodes);
+
+        LIST_HEAD(Job, jobs);
+        LIST_HEAD(Monitor, monitors);
+        LIST_HEAD(Subscription, all_subscriptions);
+
+        struct config *config;
+};
+
+Controller *controller_new(void);
+Controller *controller_ref(Controller *controller);
+void controller_unref(Controller *controller);
+
+bool controller_set_port(Controller *controller, const char *port);
+bool controller_parse_config(Controller *controller, const char *configfile);
+
+bool controller_start(Controller *controller);
+void controller_stop(Controller *controller);
+
+void controller_check_system_status(Controller *controller, int prev_number_of_nodes_online);
+
+Node *controller_find_node(Controller *controller, const char *name);
+Node *controller_find_node_by_path(Controller *controller, const char *path);
+void controller_remove_node(Controller *controller, Node *node);
+
+Node *controller_add_node(Controller *controller, const char *name);
+
+bool controller_add_job(Controller *controller, Job *job);
+void controller_remove_job(Controller *controller, Job *job, const char *result);
+void controller_finish_job(Controller *controller, uint32_t job_id, const char *result);
+void controller_job_state_changed(Controller *controller, uint32_t job_id, const char *state);
+
+void controller_remove_monitor(Controller *controller, Monitor *monitor);
+
+void controller_add_subscription(Controller *controller, Subscription *sub);
+void controller_remove_subscription(Controller *controller, Subscription *sub);
+
+DEFINE_CLEANUP_FUNC(Controller, controller_unref)
+#define _cleanup_controller_ _cleanup_(controller_unrefp)
diff --git a/src/manager/job.c b/src/controller/job.c
similarity index 92%
rename from src/manager/job.c
rename to src/controller/job.c
index dafaee05f3..38cc0e37eb 100644
--- a/src/manager/job.c
+++ b/src/controller/job.c
@@ -1,9 +1,9 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #include <stddef.h>
 
+#include "controller.h"
 #include "job.h"
 #include "libbluechi/log/log.h"
-#include "manager.h"
 #include "node.h"
 
 static int job_property_get_nodename(
@@ -92,10 +92,10 @@ void job_unref(Job *job) {
 
 bool job_export(Job *job) {
         Node *node = job->node;
-        Manager *manager = node->manager;
+        Controller *controller = node->controller;
 
         int r = sd_bus_add_object_vtable(
-                        manager->api_bus, &job->export_slot, job->object_path, JOB_INTERFACE, job_vtable, job);
+                        controller->api_bus, &job->export_slot, job->object_path, JOB_INTERFACE, job_vtable, job);
         if (r < 0) {
                 bc_log_errorf("Failed to add job vtable: %s", strerror(-r));
                 return false;
@@ -106,12 +106,12 @@ bool job_export(Job *job) {
 
 void job_set_state(Job *job, JobState state) {
         Node *node = job->node;
-        Manager *manager = node->manager;
+        Controller *controller = node->controller;
 
         job->state = state;
 
         int r = sd_bus_emit_properties_changed(
-                        manager->api_bus, job->object_path, JOB_INTERFACE, "State", NULL);
+                        controller->api_bus, job->object_path, JOB_INTERFACE, "State", NULL);
         if (r < 0) {
                 bc_log_errorf("Failed to emit status property changed: %s", strerror(-r));
         }
diff --git a/src/manager/job.h b/src/controller/job.h
similarity index 100%
rename from src/manager/job.h
rename to src/controller/job.h
diff --git a/src/manager/main.c b/src/controller/main.c
similarity index 90%
rename from src/manager/main.c
rename to src/controller/main.c
index 95ff482a33..0c4db5881b 100644
--- a/src/manager/main.c
+++ b/src/controller/main.c
@@ -7,7 +7,7 @@
 #include "libbluechi/common/parse-util.h"
 #include "libbluechi/service/shutdown.h"
 
-#include "manager.h"
+#include "controller.h"
 
 const struct option options[] = {
         {ARG_PORT,     required_argument, 0, ARG_PORT_SHORT   },
@@ -81,23 +81,23 @@ int main(int argc, char *argv[]) {
                 return EXIT_SUCCESS;
         }
 
-        _cleanup_manager_ Manager *manager = manager_new();
-        if (manager == NULL) {
+        _cleanup_controller_ Controller *controller = controller_new();
+        if (controller == NULL) {
                 return EXIT_FAILURE;
         }
 
         /* First load config */
-        if (!manager_parse_config(manager, opt_config)) {
+        if (!controller_parse_config(controller, opt_config)) {
                 return EXIT_FAILURE;
         }
 
         /* Then override individual options */
 
-        if (opt_port && !manager_set_port(manager, opt_port)) {
+        if (opt_port && !controller_set_port(controller, opt_port)) {
                 return EXIT_FAILURE;
         }
 
-        if (manager_start(manager)) {
+        if (controller_start(controller)) {
                 return EXIT_SUCCESS;
         }
         return EXIT_FAILURE;
diff --git a/src/manager/meson.build b/src/controller/meson.build
similarity index 93%
rename from src/manager/meson.build
rename to src/controller/meson.build
index 20622a1e8e..eb92b92645 100644
--- a/src/manager/meson.build
+++ b/src/controller/meson.build
@@ -3,8 +3,8 @@
 # orch build configuration
 
 orch_src = [
-    'manager.h',
-    'manager.c',
+    'controller.h',
+    'controller.c',
     'node.h',
     'node.c',
     'job.h',
diff --git a/src/manager/metrics.c b/src/controller/metrics.c
similarity index 94%
rename from src/manager/metrics.c
rename to src/controller/metrics.c
index 4636e7687b..20d3a32408 100644
--- a/src/manager/metrics.c
+++ b/src/controller/metrics.c
@@ -4,8 +4,8 @@
 #include "libbluechi/common/parse-util.h"
 #include "libbluechi/log/log.h"
 
+#include "controller.h"
 #include "job.h"
-#include "manager.h"
 #include "metrics.h"
 #include "node.h"
 
@@ -27,10 +27,10 @@ static const sd_bus_vtable metrics_api_vtable[] = {
         SD_BUS_VTABLE_END
 };
 
-int metrics_export(Manager *manager) {
+int metrics_export(Controller *controller) {
         int r = sd_bus_add_object_vtable(
-                        manager->api_bus,
-                        &manager->metrics_slot,
+                        controller->api_bus,
+                        &controller->metrics_slot,
                         METRICS_OBJECT_PATH,
                         METRICS_INTERFACE,
                         metrics_api_vtable,
@@ -59,7 +59,7 @@ static int node_metrics_match_agent_job(sd_bus_message *m, void *userdata, UNUSE
                       systemd_job_time,
                       node->name);
         r = sd_bus_emit_signal(
-                        node->manager->api_bus,
+                        node->controller->api_bus,
                         METRICS_OBJECT_PATH,
                         METRICS_INTERFACE,
                         "AgentJobMetrics",
@@ -120,7 +120,7 @@ void metrics_produce_job_report(Job *job) {
                       unit_net_start_time_micros);
 
         r = sd_bus_emit_signal(
-                        job->node->manager->api_bus,
+                        job->node->controller->api_bus,
                         METRICS_OBJECT_PATH,
                         METRICS_INTERFACE,
                         "StartUnitJobMetrics",
diff --git a/src/manager/metrics.h b/src/controller/metrics.h
similarity index 82%
rename from src/manager/metrics.h
rename to src/controller/metrics.h
index 785e86c581..6888cdfb50 100644
--- a/src/manager/metrics.h
+++ b/src/controller/metrics.h
@@ -5,6 +5,6 @@
 
 #include "types.h"
 
-int metrics_export(Manager *manager);
+int metrics_export(Controller *controller);
 bool metrics_node_signal_matching_register(Node *node);
 void metrics_produce_job_report(Job *job);
diff --git a/src/manager/monitor.c b/src/controller/monitor.c
similarity index 92%
rename from src/manager/monitor.c
rename to src/controller/monitor.c
index 090eeb2a2d..62aa8ae48e 100644
--- a/src/manager/monitor.c
+++ b/src/controller/monitor.c
@@ -1,8 +1,8 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #include "libbluechi/log/log.h"
 
+#include "controller.h"
 #include "job.h"
-#include "manager.h"
 #include "monitor.h"
 #include "node.h"
 
@@ -138,7 +138,7 @@ static const sd_bus_vtable monitor_vtable[] = {
         SD_BUS_VTABLE_END
 };
 
-Monitor *monitor_new(Manager *manager, const char *owner) {
+Monitor *monitor_new(Controller *controller, const char *owner) {
         static uint32_t next_id = 0;
         _cleanup_monitor_ Monitor *monitor = malloc0(sizeof(Monitor));
         if (monitor == NULL) {
@@ -147,7 +147,7 @@ Monitor *monitor_new(Manager *manager, const char *owner) {
 
         monitor->ref_count = 1;
         monitor->id = ++next_id;
-        monitor->manager = manager;
+        monitor->controller = controller;
         LIST_INIT(monitors, monitor);
         LIST_HEAD_INIT(monitor->subscriptions);
         LIST_HEAD_INIT(monitor->peers);
@@ -183,10 +183,10 @@ void monitor_unref(Monitor *monitor) {
 }
 
 bool monitor_export(Monitor *monitor) {
-        Manager *manager = monitor->manager;
+        Controller *controller = monitor->controller;
 
         int r = sd_bus_add_object_vtable(
-                        manager->api_bus,
+                        controller->api_bus,
                         &monitor->export_slot,
                         monitor->object_path,
                         MONITOR_INTERFACE,
@@ -201,12 +201,12 @@ bool monitor_export(Monitor *monitor) {
 }
 
 void monitor_close(Monitor *monitor) {
-        Manager *manager = monitor->manager;
+        Controller *controller = monitor->controller;
 
         Subscription *sub = NULL;
         Subscription *next_sub = NULL;
         LIST_FOREACH_SAFE(subscriptions, sub, next_sub, monitor->subscriptions) {
-                manager_remove_subscription(manager, sub);
+                controller_remove_subscription(controller, sub);
                 LIST_REMOVE(subscriptions, monitor->subscriptions, sub);
                 subscription_unref(sub);
         }
@@ -230,7 +230,7 @@ void monitor_close(Monitor *monitor) {
 
 static int monitor_method_close(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
         _cleanup_monitor_ Monitor *monitor = monitor_ref(userdata);
-        Manager *manager = monitor->manager;
+        Controller *controller = monitor->controller;
 
         /* Ensure we don't close it twice somehow */
         if (monitor->export_slot == NULL) {
@@ -238,7 +238,7 @@ static int monitor_method_close(sd_bus_message *m, void *userdata, UNUSED sd_bus
         }
 
         monitor_close(monitor);
-        manager_remove_monitor(manager, monitor);
+        controller_remove_monitor(controller, monitor);
 
         return sd_bus_reply_method_return(m, "");
 }
@@ -249,7 +249,7 @@ static int monitor_method_close(sd_bus_message *m, void *userdata, UNUSED sd_bus
 
 static int monitor_method_subscribe(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
         Monitor *monitor = userdata;
-        Manager *manager = monitor->manager;
+        Controller *controller = monitor->controller;
         const char *node = NULL;
         const char *unit = NULL;
 
@@ -277,7 +277,7 @@ static int monitor_method_subscribe(sd_bus_message *m, void *userdata, UNUSED sd
         }
 
         LIST_APPEND(subscriptions, monitor->subscriptions, subscription_ref(sub));
-        manager_add_subscription(manager, sub);
+        controller_add_subscription(controller, sub);
 
         return sd_bus_reply_method_return(m, "u", sub->id);
 }
@@ -288,7 +288,7 @@ static int monitor_method_subscribe(sd_bus_message *m, void *userdata, UNUSED sd
 
 static int monitor_method_subscribe_list(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
         Monitor *monitor = userdata;
-        Manager *manager = monitor->manager;
+        Controller *controller = monitor->controller;
 
         const char *node = NULL;
         int r = sd_bus_message_read(m, "s", &node);
@@ -348,7 +348,7 @@ static int monitor_method_subscribe_list(sd_bus_message *m, void *userdata, UNUS
         }
 
         LIST_APPEND(subscriptions, monitor->subscriptions, subscription_ref(sub));
-        manager_add_subscription(manager, sub);
+        controller_add_subscription(controller, sub);
 
         return sd_bus_reply_method_return(m, "u", sub->id);
 }
@@ -372,7 +372,7 @@ static Subscription *monitor_find_subscription(Monitor *monitor, uint32_t sub_id
 
 static int monitor_method_unsubscribe(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
         Monitor *monitor = userdata;
-        Manager *manager = monitor->manager;
+        Controller *controller = monitor->controller;
         uint32_t sub_id = 0;
 
         int r = sd_bus_message_read(m, "u", &sub_id);
@@ -390,7 +390,7 @@ static int monitor_method_unsubscribe(sd_bus_message *m, void *userdata, UNUSED
                                 m, SD_BUS_ERROR_FAILED, "Subscription '%d' not found", sub_id);
         }
 
-        manager_remove_subscription(manager, sub);
+        controller_remove_subscription(controller, sub);
         LIST_REMOVE(subscriptions, monitor->subscriptions, sub);
         subscription_unref(sub);
 
@@ -543,14 +543,14 @@ static sd_bus_message *assemble_unit_state_changed_signal(
 int monitor_on_unit_property_changed(
                 void *userdata, const char *node, const char *unit, const char *interface, sd_bus_message *m) {
         Monitor *monitor = (Monitor *) userdata;
-        Manager *manager = monitor->manager;
+        Controller *controller = monitor->controller;
 
         int r = 0;
         _cleanup_sd_bus_message_ sd_bus_message *sig = NULL;
 
         sig = assemble_unit_property_changed_signal(monitor, node, unit, interface, m);
         if (sig != NULL) {
-                r = sd_bus_send_to(manager->api_bus, sig, monitor->owner, NULL);
+                r = sd_bus_send_to(controller->api_bus, sig, monitor->owner, NULL);
                 if (r < 0) {
                         bc_log_errorf("Monitor: %s, failed to send UnitPropertyChanged signal to monitor owner: %s",
                                       monitor->object_path,
@@ -565,7 +565,7 @@ int monitor_on_unit_property_changed(
         LIST_FOREACH_SAFE(peers, peer, next_peer, monitor->peers) {
                 sig = assemble_unit_property_changed_signal(monitor, node, unit, interface, m);
                 if (sig != NULL) {
-                        r = sd_bus_send_to(manager->api_bus, sig, peer->name, NULL);
+                        r = sd_bus_send_to(controller->api_bus, sig, peer->name, NULL);
                         if (r < 0) {
                                 bc_log_errorf("Monitor: %s, failed to send UnitPropertyChanged signal to peer '%s': %s",
                                               monitor->object_path,
@@ -582,14 +582,14 @@ int monitor_on_unit_property_changed(
 
 int monitor_on_unit_new(void *userdata, const char *node, const char *unit, const char *reason) {
         Monitor *monitor = (Monitor *) userdata;
-        Manager *manager = monitor->manager;
+        Controller *controller = monitor->controller;
 
         int r = 0;
         _cleanup_sd_bus_message_ sd_bus_message *sig = NULL;
 
         sig = assemble_unit_new_signal(monitor, node, unit, reason);
         if (sig != NULL) {
-                r = sd_bus_send_to(manager->api_bus, sig, monitor->owner, NULL);
+                r = sd_bus_send_to(controller->api_bus, sig, monitor->owner, NULL);
                 if (r < 0) {
                         bc_log_errorf("Monitor: %s, failed to send UnitNew signal to monitor owner: %s",
                                       monitor->object_path,
@@ -604,7 +604,7 @@ int monitor_on_unit_new(void *userdata, const char *node, const char *unit, cons
         LIST_FOREACH_SAFE(peers, peer, next_peer, monitor->peers) {
                 sig = assemble_unit_new_signal(monitor, node, unit, reason);
                 if (sig != NULL) {
-                        r = sd_bus_send_to(manager->api_bus, sig, peer->name, NULL);
+                        r = sd_bus_send_to(controller->api_bus, sig, peer->name, NULL);
                         if (r < 0) {
                                 bc_log_errorf("Monitor: %s, failed to send signal to peer '%s': %s",
                                               monitor->object_path,
@@ -627,14 +627,14 @@ int monitor_on_unit_state_changed(
                 const char *substate,
                 const char *reason) {
         Monitor *monitor = (Monitor *) userdata;
-        Manager *manager = monitor->manager;
+        Controller *controller = monitor->controller;
 
         int r = 0;
         _cleanup_sd_bus_message_ sd_bus_message *sig = NULL;
 
         sig = assemble_unit_state_changed_signal(monitor, node, unit, active_state, substate, reason);
         if (sig != NULL) {
-                r = sd_bus_send_to(manager->api_bus, sig, monitor->owner, NULL);
+                r = sd_bus_send_to(controller->api_bus, sig, monitor->owner, NULL);
                 if (r < 0) {
                         bc_log_errorf("Monitor: %s, failed to send signal to monitor owner: %s",
                                       monitor->object_path,
@@ -649,7 +649,7 @@ int monitor_on_unit_state_changed(
         LIST_FOREACH_SAFE(peers, peer, next_peer, monitor->peers) {
                 sig = assemble_unit_state_changed_signal(monitor, node, unit, active_state, substate, reason);
                 if (sig != NULL) {
-                        r = sd_bus_send_to(manager->api_bus, sig, peer->name, NULL);
+                        r = sd_bus_send_to(controller->api_bus, sig, peer->name, NULL);
                         if (r < 0) {
                                 bc_log_errorf("Monitor: %s, failed to send UnitStateChanged signal to peer '%s': %s",
                                               monitor->object_path,
@@ -666,14 +666,14 @@ int monitor_on_unit_state_changed(
 
 int monitor_on_unit_removed(void *userdata, const char *node, const char *unit, const char *reason) {
         Monitor *monitor = (Monitor *) userdata;
-        Manager *manager = monitor->manager;
+        Controller *controller = monitor->controller;
 
         int r = 0;
         _cleanup_sd_bus_message_ sd_bus_message *sig = NULL;
 
         sig = assemble_unit_removed_signal(monitor, node, unit, reason);
         if (sig != NULL) {
-                r = sd_bus_send_to(manager->api_bus, sig, monitor->owner, NULL);
+                r = sd_bus_send_to(controller->api_bus, sig, monitor->owner, NULL);
                 if (r < 0) {
                         bc_log_errorf("Monitor: %s, failed to send signal to monitor owner: %s",
                                       monitor->object_path,
@@ -688,7 +688,7 @@ int monitor_on_unit_removed(void *userdata, const char *node, const char *unit,
         LIST_FOREACH_SAFE(peers, peer, next_peer, monitor->peers) {
                 sig = assemble_unit_removed_signal(monitor, node, unit, reason);
                 if (sig != NULL) {
-                        r = sd_bus_send_to(manager->api_bus, sig, peer->name, NULL);
+                        r = sd_bus_send_to(controller->api_bus, sig, peer->name, NULL);
                         if (r < 0) {
                                 bc_log_errorf("Monitor: %s, failed to send UnitRemoved signal to peer '%s': %s",
                                               monitor->object_path,
@@ -706,11 +706,11 @@ int monitor_on_unit_removed(void *userdata, const char *node, const char *unit,
 
 static sd_bus_message *assemble_unit_new_signal(
                 Monitor *monitor, const char *node, const char *unit, const char *reason) {
-        Manager *manager = monitor->manager;
+        Controller *controller = monitor->controller;
 
         _cleanup_sd_bus_message_ sd_bus_message *sig = NULL;
         int r = sd_bus_message_new_signal(
-                        manager->api_bus, &sig, monitor->object_path, MONITOR_INTERFACE, "UnitNew");
+                        controller->api_bus, &sig, monitor->object_path, MONITOR_INTERFACE, "UnitNew");
         if (r < 0) {
                 bc_log_errorf("Monitor: %s, failed to create UnitNew signal: %s",
                               monitor->object_path,
@@ -731,11 +731,11 @@ static sd_bus_message *assemble_unit_new_signal(
 
 static sd_bus_message *assemble_unit_removed_signal(
                 Monitor *monitor, const char *node, const char *unit, const char *reason) {
-        Manager *manager = monitor->manager;
+        Controller *controller = monitor->controller;
 
         _cleanup_sd_bus_message_ sd_bus_message *sig = NULL;
         int r = sd_bus_message_new_signal(
-                        manager->api_bus, &sig, monitor->object_path, MONITOR_INTERFACE, "UnitRemoved");
+                        controller->api_bus, &sig, monitor->object_path, MONITOR_INTERFACE, "UnitRemoved");
         if (r < 0) {
                 bc_log_errorf("Monitor: %s, failed to create UnitRemoved signal: %s",
                               monitor->object_path,
@@ -756,11 +756,15 @@ static sd_bus_message *assemble_unit_removed_signal(
 
 static sd_bus_message *assemble_unit_property_changed_signal(
                 Monitor *monitor, const char *node, const char *unit, const char *interface, sd_bus_message *m) {
-        Manager *manager = monitor->manager;
+        Controller *controller = monitor->controller;
 
         _cleanup_sd_bus_message_ sd_bus_message *sig = NULL;
         int r = sd_bus_message_new_signal(
-                        manager->api_bus, &sig, monitor->object_path, MONITOR_INTERFACE, "UnitPropertiesChanged");
+                        controller->api_bus,
+                        &sig,
+                        monitor->object_path,
+                        MONITOR_INTERFACE,
+                        "UnitPropertiesChanged");
         if (r < 0) {
                 bc_log_errorf("Monitor: %s, failed to create UnitPropertiesChanged signal: %s",
                               monitor->object_path,
@@ -810,11 +814,11 @@ static sd_bus_message *assemble_unit_state_changed_signal(
                 const char *active_state,
                 const char *substate,
                 const char *reason) {
-        Manager *manager = monitor->manager;
+        Controller *controller = monitor->controller;
 
         _cleanup_sd_bus_message_ sd_bus_message *sig = NULL;
         int r = sd_bus_message_new_signal(
-                        manager->api_bus, &sig, monitor->object_path, MONITOR_INTERFACE, "UnitStateChanged");
+                        controller->api_bus, &sig, monitor->object_path, MONITOR_INTERFACE, "UnitStateChanged");
         if (r < 0) {
                 bc_log_errorf("Monitor: %s, failed to create UnitStateChanged signal: %s",
                               monitor->object_path,
@@ -835,11 +839,11 @@ static sd_bus_message *assemble_unit_state_changed_signal(
 
 static void monitor_emit_peer_removed(void *userdata, MonitorPeer *peer, const char *reason) {
         Monitor *monitor = (Monitor *) userdata;
-        Manager *manager = monitor->manager;
+        Controller *controller = monitor->controller;
 
         _cleanup_sd_bus_message_ sd_bus_message *sig = NULL;
         int r = sd_bus_message_new_signal(
-                        manager->api_bus, &sig, monitor->object_path, MONITOR_INTERFACE, "PeerRemoved");
+                        controller->api_bus, &sig, monitor->object_path, MONITOR_INTERFACE, "PeerRemoved");
         if (r < 0) {
                 bc_log_errorf("Monitor: %s, failed to create PeerRemoved signal: %s",
                               monitor->object_path,
@@ -855,7 +859,7 @@ static void monitor_emit_peer_removed(void *userdata, MonitorPeer *peer, const c
                 return;
         }
 
-        r = sd_bus_send_to(manager->api_bus, sig, peer->name, NULL);
+        r = sd_bus_send_to(controller->api_bus, sig, peer->name, NULL);
         if (r < 0) {
                 bc_log_errorf("Monitor: %s, failed to send PeerRemoved signal: %s",
                               monitor->object_path,
diff --git a/src/manager/monitor.h b/src/controller/monitor.h
similarity index 96%
rename from src/manager/monitor.h
rename to src/controller/monitor.h
index 2dad13a013..a7f21b7809 100644
--- a/src/manager/monitor.h
+++ b/src/controller/monitor.h
@@ -34,7 +34,7 @@ struct Subscription {
         LIST_HEAD(SubscribedUnit, subscribed_units);
 
         LIST_FIELDS(Subscription, subscriptions);     /* List in Monitor */
-        LIST_FIELDS(Subscription, all_subscriptions); /* List in Manager */
+        LIST_FIELDS(Subscription, all_subscriptions); /* List in Controller */
 
         unit_new_handler_func_t *handle_unit_new;
         unit_removed_handler_func_t *handle_unit_removed;
@@ -67,7 +67,7 @@ struct Monitor {
         char *owner;
         LIST_HEAD(MonitorPeer, peers);
 
-        Manager *manager; /* weak ref */
+        Controller *controller; /* weak ref */
 
         sd_bus_slot *export_slot;
         char *object_path;
@@ -77,7 +77,7 @@ struct Monitor {
         LIST_FIELDS(Monitor, monitors);
 };
 
-Monitor *monitor_new(Manager *manager, const char *owner);
+Monitor *monitor_new(Controller *controller, const char *owner);
 Monitor *monitor_ref(Monitor *monitor);
 void monitor_unref(Monitor *monitor);
 
diff --git a/src/manager/node.c b/src/controller/node.c
similarity index 96%
rename from src/manager/node.c
rename to src/controller/node.c
index 5418e7d1fb..09bacb7519 100644
--- a/src/manager/node.c
+++ b/src/controller/node.c
@@ -4,8 +4,8 @@
 #include "libbluechi/common/time-util.h"
 #include "libbluechi/log/log.h"
 
+#include "controller.h"
 #include "job.h"
-#include "manager.h"
 #include "metrics.h"
 #include "monitor.h"
 #include "node.h"
@@ -52,7 +52,7 @@ static int node_property_get_last_seen(
                 void *userdata,
                 sd_bus_error *ret_error);
 
-static const sd_bus_vtable internal_manager_controller_vtable[] = {
+static const sd_bus_vtable internal_controller_controller_vtable[] = {
         SD_BUS_VTABLE_START(0), SD_BUS_METHOD("Register", "s", "", node_method_register, 0), SD_BUS_VTABLE_END
 };
 
@@ -128,14 +128,14 @@ static int unit_subscriptions_compare(const void *a, const void *b, UNUSED void
 }
 
 
-Node *node_new(Manager *manager, const char *name) {
+Node *node_new(Controller *controller, const char *name) {
         _cleanup_node_ Node *node = malloc0(sizeof(Node));
         if (node == NULL) {
                 return NULL;
         }
 
         node->ref_count = 1;
-        node->manager = manager;
+        node->controller = controller;
         LIST_INIT(nodes, node);
         LIST_HEAD_INIT(node->outstanding_requests);
         LIST_HEAD_INIT(node->proxy_monitors);
@@ -219,12 +219,17 @@ void node_shutdown(Node *node) {
 }
 
 bool node_export(Node *node) {
-        Manager *manager = node->manager;
+        Controller *controller = node->controller;
 
         assert(node->name != NULL);
 
         int r = sd_bus_add_object_vtable(
-                        manager->api_bus, &node->export_slot, node->object_path, NODE_INTERFACE, node_vtable, node);
+                        controller->api_bus,
+                        &node->export_slot,
+                        node->object_path,
+                        NODE_INTERFACE,
+                        node_vtable,
+                        node);
         if (r < 0) {
                 bc_log_errorf("Failed to add node vtable: %s", strerror(-r));
                 return false;
@@ -329,7 +334,7 @@ static struct hashmap *node_compute_unique_monitor_subscriptions(Node *node, con
 
 static int node_match_job_state_changed(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *error) {
         Node *node = userdata;
-        Manager *manager = node->manager;
+        Controller *controller = node->controller;
         uint32_t bc_job_id = 0;
         const char *state = NULL;
 
@@ -339,7 +344,7 @@ static int node_match_job_state_changed(sd_bus_message *m, void *userdata, UNUSE
                 return 0;
         }
 
-        manager_job_state_changed(manager, bc_job_id, state);
+        controller_job_state_changed(controller, bc_job_id, state);
         return 1;
 }
 
@@ -489,7 +494,7 @@ static int node_match_unit_removed(sd_bus_message *m, void *userdata, UNUSED sd_
 
 static int node_match_job_done(UNUSED sd_bus_message *m, UNUSED void *userdata, UNUSED sd_bus_error *error) {
         Node *node = userdata;
-        Manager *manager = node->manager;
+        Controller *controller = node->controller;
         uint32_t bc_job_id = 0;
         const char *result = NULL;
 
@@ -499,7 +504,7 @@ static int node_match_job_done(UNUSED sd_bus_message *m, UNUSED void *userdata,
                 return 0;
         }
 
-        manager_finish_job(manager, bc_job_id, result);
+        controller_finish_job(controller, bc_job_id, result);
         return 1;
 }
 
@@ -528,7 +533,7 @@ static ProxyMonitor *node_find_proxy_monitor(Node *node, const char *target_node
 
 static int node_on_match_proxy_new(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *error) {
         Node *node = userdata;
-        Manager *manager = node->manager;
+        Controller *controller = node->controller;
 
         const char *target_node_name = NULL;
         const char *unit_name = NULL;
@@ -551,7 +556,7 @@ static int node_on_match_proxy_new(sd_bus_message *m, void *userdata, UNUSED sd_
                 return -ENOMEM;
         }
 
-        Node *target_node = manager_find_node(manager, target_node_name);
+        Node *target_node = controller_find_node(controller, target_node_name);
         if (target_node == NULL) {
                 bc_log_error("Proxy requested for non-existing node");
                 proxy_monitor_send_error(monitor, "No such node");
@@ -575,7 +580,7 @@ static int node_on_match_proxy_new(sd_bus_message *m, void *userdata, UNUSED sd_
 
         /* We now have a valid monitor, add it to the list and enable monitor.
            From this point we should not send errors. */
-        manager_add_subscription(manager, monitor->subscription);
+        controller_add_subscription(controller, monitor->subscription);
         LIST_APPEND(monitors, node->proxy_monitors, proxy_monitor_ref(monitor));
 
         /* TODO: What about !!node_is_online(target_node) ? Tell now or wait for it to connect? */
@@ -584,11 +589,11 @@ static int node_on_match_proxy_new(sd_bus_message *m, void *userdata, UNUSED sd_
 }
 
 void node_remove_proxy_monitor(Node *node, ProxyMonitor *monitor) {
-        Manager *manager = node->manager;
+        Controller *controller = node->controller;
 
         proxy_monitor_close(monitor);
 
-        manager_remove_subscription(manager, monitor->subscription);
+        controller_remove_subscription(controller, monitor->subscription);
         LIST_REMOVE(monitors, node->proxy_monitors, monitor);
 
         proxy_monitor_unref(monitor);
@@ -633,10 +638,10 @@ bool node_set_agent_bus(Node *node, sd_bus *bus) {
                 // can be called. We can't reconnect it during migration.
                 r = sd_bus_add_object_vtable(
                                 bus,
-                                &node->internal_manager_slot,
-                                INTERNAL_MANAGER_OBJECT_PATH,
-                                INTERNAL_MANAGER_INTERFACE,
-                                internal_manager_controller_vtable,
+                                &node->internal_controller_slot,
+                                INTERNAL_CONTROLLER_OBJECT_PATH,
+                                INTERNAL_CONTROLLER_INTERFACE,
+                                internal_controller_controller_vtable,
                                 node);
                 if (r < 0) {
                         node_unset_agent_bus(node);
@@ -758,7 +763,7 @@ bool node_set_agent_bus(Node *node, sd_bus *bus) {
                 }
 
                 r = sd_bus_emit_properties_changed(
-                                node->manager->api_bus, node->object_path, NODE_INTERFACE, "Status", NULL);
+                                node->controller->api_bus, node->object_path, NODE_INTERFACE, "Status", NULL);
                 if (r < 0) {
                         bc_log_errorf("Failed to emit status property changed: %s", strerror(-r));
                 }
@@ -814,8 +819,8 @@ void node_unset_agent_bus(Node *node) {
         sd_bus_slot_unrefp(&node->disconnect_slot);
         node->disconnect_slot = NULL;
 
-        sd_bus_slot_unrefp(&node->internal_manager_slot);
-        node->internal_manager_slot = NULL;
+        sd_bus_slot_unrefp(&node->internal_controller_slot);
+        node->internal_controller_slot = NULL;
 
         sd_bus_slot_unrefp(&node->metrics_matching_slot);
         node->metrics_matching_slot = NULL;
@@ -825,17 +830,17 @@ void node_unset_agent_bus(Node *node) {
 
         if (was_online) {
                 int r = sd_bus_emit_properties_changed(
-                                node->manager->api_bus, node->object_path, NODE_INTERFACE, "Status", NULL);
+                                node->controller->api_bus, node->object_path, NODE_INTERFACE, "Status", NULL);
                 if (r < 0) {
                         bc_log_errorf("Failed to emit status property changed: %s", strerror(-r));
                 }
         }
 }
 
-/* org.eclipse.bluechi.internal.Manager.Register(in s name)) */
+/* org.eclipse.bluechi.internal.Controller.Register(in s name)) */
 static int node_method_register(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
         Node *node = userdata;
-        Manager *manager = node->manager;
+        Controller *controller = node->controller;
         char *name = NULL;
         _cleanup_free_ char *description = NULL;
 
@@ -851,7 +856,7 @@ static int node_method_register(sd_bus_message *m, void *userdata, UNUSED sd_bus
                 return r;
         }
 
-        Node *named_node = manager_find_node(manager, name);
+        Node *named_node = controller_find_node(controller, name);
         if (named_node == NULL) {
                 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_SERVICE_UNKNOWN, "Unexpected node name");
         }
@@ -873,14 +878,14 @@ static int node_method_register(sd_bus_message *m, void *userdata, UNUSED sd_bus
                                 m, SD_BUS_ERROR_FAILED, "Internal error: Couldn't set agent bus");
         }
 
-        if (manager->metrics_enabled) {
+        if (controller->metrics_enabled) {
                 node_enable_metrics(named_node);
         }
 
         node_unset_agent_bus(node);
 
         /* update number of online nodes and check the new system state */
-        manager_check_system_status(manager, manager->number_of_nodes_online++);
+        controller_check_system_status(controller, controller->number_of_nodes_online++);
 
         bc_log_infof("Registered managed node from fd %d as '%s'", sd_bus_get_fd(agent_bus), name);
 
@@ -889,7 +894,7 @@ static int node_method_register(sd_bus_message *m, void *userdata, UNUSED sd_bus
 
 static int node_disconnected(UNUSED sd_bus_message *message, void *userdata, UNUSED sd_bus_error *error) {
         Node *node = userdata;
-        Manager *manager = node->manager;
+        Controller *controller = node->controller;
         void *item = NULL;
         size_t i = 0;
 
@@ -963,17 +968,17 @@ static int node_disconnected(UNUSED sd_bus_message *message, void *userdata, UNU
         /* Remove anonymous nodes when they disconnect */
         if (node->name == NULL) {
                 bc_log_info("Anonymous node disconnected");
-                manager_remove_node(manager, node);
+                controller_remove_node(controller, node);
         } else {
                 bc_log_infof("Node '%s' disconnected", node->name);
                 /* Remove all jobs associated with the registered node that got disconnected. */
-                if (!LIST_IS_EMPTY(manager->jobs)) {
+                if (!LIST_IS_EMPTY(controller->jobs)) {
                         Job *job = NULL;
                         Job *next_job = NULL;
-                        LIST_FOREACH_SAFE(jobs, job, next_job, manager->jobs) {
+                        LIST_FOREACH_SAFE(jobs, job, next_job, controller->jobs) {
                                 if (strcmp(job->node->name, node->name) == 0) {
                                         bc_log_debugf("Removing job %d from node %s", job->id, job->node->name);
-                                        LIST_REMOVE(jobs, manager->jobs, job);
+                                        LIST_REMOVE(jobs, controller->jobs, job);
                                         job_unref(job);
                                 }
                         }
@@ -981,7 +986,7 @@ static int node_disconnected(UNUSED sd_bus_message *message, void *userdata, UNU
                 node_unset_agent_bus(node);
 
                 /* update number of online nodes and check the new system state */
-                manager_check_system_status(manager, manager->number_of_nodes_online--);
+                controller_check_system_status(controller, controller->number_of_nodes_online--);
         }
 
         return 0;
@@ -1410,7 +1415,7 @@ static JobSetup *job_setup_new(sd_bus_message *request_message, Node *node, cons
 
 static int unit_lifecycle_method_callback(AgentRequest *req, sd_bus_message *m, UNUSED sd_bus_error *ret_error) {
         Node *node = req->node;
-        Manager *manager = node->manager;
+        Controller *controller = node->controller;
         JobSetup *setup = req->userdata;
 
         if (sd_bus_message_is_method_error(m, NULL)) {
@@ -1418,7 +1423,7 @@ static int unit_lifecycle_method_callback(AgentRequest *req, sd_bus_message *m,
                 return sd_bus_reply_method_error(setup->request_message, sd_bus_message_get_error(m));
         }
 
-        if (!manager_add_job(manager, setup->job)) {
+        if (!controller_add_job(controller, setup->job)) {
                 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_FAILED, "Failed to add a job");
         }
 
@@ -1450,7 +1455,7 @@ static int node_run_unit_lifecycle_method(
                 return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_NO_MEMORY, "Out of memory");
         }
 
-        if (node->manager->metrics_enabled) {
+        if (node->controller->metrics_enabled) {
                 setup->job->job_start_micros = start_time;
         }
 
diff --git a/src/manager/node.h b/src/controller/node.h
similarity index 94%
rename from src/manager/node.h
rename to src/controller/node.h
index 086bd714eb..2cbd90d363 100644
--- a/src/manager/node.h
+++ b/src/controller/node.h
@@ -36,14 +36,14 @@ int agent_request_cancel(AgentRequest *r);
 struct Node {
         int ref_count;
 
-        Manager *manager; /* weak ref */
+        Controller *controller; /* weak ref */
 
         /* public bus api */
         sd_bus_slot *export_slot;
 
         /* internal bus api */
         sd_bus *agent_bus;
-        sd_bus_slot *internal_manager_slot;
+        sd_bus_slot *internal_controller_slot;
         sd_bus_slot *disconnect_slot;
         sd_bus_slot *metrics_matching_slot;
 
@@ -62,7 +62,7 @@ struct Node {
         bool is_shutdown;
 };
 
-Node *node_new(Manager *manager, const char *name);
+Node *node_new(Controller *controller, const char *name);
 Node *node_ref(Node *node);
 void node_unref(Node *node);
 void node_shutdown(Node *node);
diff --git a/src/manager/proxy_monitor.c b/src/controller/proxy_monitor.c
similarity index 99%
rename from src/manager/proxy_monitor.c
rename to src/controller/proxy_monitor.c
index 9e80ad72f4..483ca060c5 100644
--- a/src/manager/proxy_monitor.c
+++ b/src/controller/proxy_monitor.c
@@ -1,8 +1,8 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #include "libbluechi/log/log.h"
 
+#include "controller.h"
 #include "job.h"
-#include "manager.h"
 #include "monitor.h"
 #include "node.h"
 #include "proxy_monitor.h"
diff --git a/src/manager/proxy_monitor.h b/src/controller/proxy_monitor.h
similarity index 100%
rename from src/manager/proxy_monitor.h
rename to src/controller/proxy_monitor.h
diff --git a/src/manager/types.h b/src/controller/types.h
similarity index 91%
rename from src/manager/types.h
rename to src/controller/types.h
index 4ec8484f51..3a064424d3 100644
--- a/src/manager/types.h
+++ b/src/controller/types.h
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
-typedef struct Manager Manager;
+typedef struct Controller Controller;
 typedef struct Node Node;
 typedef struct AgentRequest AgentRequest;
 typedef struct Job Job;
diff --git a/src/libbluechi/common/cfg.c b/src/libbluechi/common/cfg.c
index 6924f9e4ee..c5b998054c 100644
--- a/src/libbluechi/common/cfg.c
+++ b/src/libbluechi/common/cfg.c
@@ -448,7 +448,7 @@ int cfg_agent_def_conf(struct config *config) {
                 return result;
         }
 
-        if ((result = cfg_set_value(config, CFG_MANAGER_HOST, BC_DEFAULT_HOST)) != 0) {
+        if ((result = cfg_set_value(config, CFG_CONTROLLER_HOST, BC_DEFAULT_HOST)) != 0) {
                 return result;
         }
 
@@ -457,14 +457,14 @@ int cfg_agent_def_conf(struct config *config) {
                 return result;
         }
 
-        if ((result = cfg_set_value(config, CFG_MANAGER_PORT, BC_DEFAULT_PORT)) != 0) {
+        if ((result = cfg_set_value(config, CFG_CONTROLLER_PORT, BC_DEFAULT_PORT)) != 0) {
                 return result;
         }
 
         return 0;
 }
 
-int cfg_manager_def_conf(struct config *config) {
+int cfg_controller_def_conf(struct config *config) {
         int result = 0;
 
         result = cfg_set_default_section(config, CFG_SECT_BLUECHI);
@@ -476,7 +476,7 @@ int cfg_manager_def_conf(struct config *config) {
                 return result;
         }
 
-        if ((result = cfg_set_value(config, CFG_MANAGER_PORT, BC_DEFAULT_PORT)) != 0) {
+        if ((result = cfg_set_value(config, CFG_CONTROLLER_PORT, BC_DEFAULT_PORT)) != 0) {
                 return result;
         }
 
diff --git a/src/libbluechi/common/cfg.h b/src/libbluechi/common/cfg.h
index bff0c82d7a..b6038618c2 100644
--- a/src/libbluechi/common/cfg.h
+++ b/src/libbluechi/common/cfg.h
@@ -11,9 +11,9 @@
 #define CFG_LOG_LEVEL "LogLevel"
 #define CFG_LOG_TARGET "LogTarget"
 #define CFG_LOG_IS_QUIET "LogIsQuiet"
-#define CFG_MANAGER_HOST "ControllerHost"
-#define CFG_MANAGER_PORT "ControllerPort"
-#define CFG_MANAGER_ADDRESS "ControllerAddress"
+#define CFG_CONTROLLER_HOST "ControllerHost"
+#define CFG_CONTROLLER_PORT "ControllerPort"
+#define CFG_CONTROLLER_ADDRESS "ControllerAddress"
 #define CFG_NODE_NAME "NodeName"
 #define CFG_ALLOWED_NODE_NAMES "AllowedNodeNames"
 #define CFG_HEARTBEAT_INTERVAL "HeartbeatInterval"
@@ -29,7 +29,7 @@
 #define CFG_SECT_GLOBAL ""
 
 /*
- * Configuration section for bluechi manager.
+ * Configuration section for bluechi controller.
  */
 #define CFG_SECT_BLUECHI "bluechi-controller"
 
@@ -203,6 +203,6 @@ const char *cfg_dump(struct config *config);
 int cfg_agent_def_conf(struct config *config);
 
 /*
- * Populate the default manager configuration from the source code
+ * Populate the default controller configuration from the source code
  */
-int cfg_manager_def_conf(struct config *config);
+int cfg_controller_def_conf(struct config *config);
diff --git a/src/libbluechi/common/protocol.h b/src/libbluechi/common/protocol.h
index ade259cc4a..58ab699f4a 100644
--- a/src/libbluechi/common/protocol.h
+++ b/src/libbluechi/common/protocol.h
@@ -32,12 +32,12 @@
 #define BC_OBJECT_PATH "/org/eclipse/bluechi"
 
 /* Public objects */
-#define BC_MANAGER_OBJECT_PATH BC_OBJECT_PATH
+#define BC_CONTROLLER_OBJECT_PATH BC_OBJECT_PATH
 #define BC_AGENT_OBJECT_PATH BC_OBJECT_PATH
 
 /* Public interfaces */
 #define BC_INTERFACE_BASE_NAME "org.eclipse.bluechi"
-#define MANAGER_INTERFACE BC_INTERFACE_BASE_NAME ".Manager"
+#define CONTROLLER_INTERFACE BC_INTERFACE_BASE_NAME ".Controller"
 #define AGENT_INTERFACE BC_INTERFACE_BASE_NAME ".Agent"
 #define NODE_INTERFACE BC_INTERFACE_BASE_NAME ".Node"
 #define JOB_INTERFACE BC_INTERFACE_BASE_NAME ".Job"
@@ -50,13 +50,13 @@
 #define METRICS_OBJECT_PATH BC_OBJECT_PATH "/metrics"
 
 /* Internal objects */
-#define INTERNAL_MANAGER_OBJECT_PATH BC_OBJECT_PATH "/internal"
+#define INTERNAL_CONTROLLER_OBJECT_PATH BC_OBJECT_PATH "/internal"
 #define INTERNAL_AGENT_OBJECT_PATH BC_OBJECT_PATH "/internal/agent"
 #define INTERNAL_PROXY_OBJECT_PATH_PREFIX BC_OBJECT_PATH "/internal/proxy"
 #define INTERNAL_AGENT_METRICS_OBJECT_PATH INTERNAL_AGENT_OBJECT_PATH "/metrics"
 
 /* Internal interfaces */
-#define INTERNAL_MANAGER_INTERFACE BC_INTERFACE_BASE_NAME ".internal.Manager"
+#define INTERNAL_CONTROLLER_INTERFACE BC_INTERFACE_BASE_NAME ".internal.Controller"
 #define INTERNAL_AGENT_INTERFACE BC_INTERFACE_BASE_NAME ".internal.Agent"
 #define INTERNAL_PROXY_INTERFACE BC_INTERFACE_BASE_NAME ".internal.Proxy"
 #define INTERNAL_AGENT_METRICS_INTERFACE INTERNAL_AGENT_INTERFACE ".Metrics"
diff --git a/src/manager/manager.h b/src/manager/manager.h
deleted file mode 100644
index 1b1bb04639..0000000000
--- a/src/manager/manager.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#pragma once
-
-#include <inttypes.h>
-#include <stdbool.h>
-
-#include "libbluechi/common/cfg.h"
-#include "libbluechi/common/common.h"
-#include "libbluechi/socket.h"
-
-#include "types.h"
-
-struct Manager {
-        int ref_count;
-
-        uint16_t port;
-        char *api_bus_service_name;
-
-        sd_event *event;
-        sd_event_source *node_connection_source;
-
-        sd_bus *api_bus;
-        sd_bus_slot *manager_slot;
-        sd_bus_slot *filter_slot;
-        sd_bus_slot *name_owner_changed_slot;
-        sd_bus_slot *metrics_slot;
-
-        bool metrics_enabled;
-
-        SocketOptions *peer_socket_options;
-
-        int number_of_nodes;
-        int number_of_nodes_online;
-        LIST_HEAD(Node, nodes);
-        LIST_HEAD(Node, anonymous_nodes);
-
-        LIST_HEAD(Job, jobs);
-        LIST_HEAD(Monitor, monitors);
-        LIST_HEAD(Subscription, all_subscriptions);
-
-        struct config *config;
-};
-
-Manager *manager_new(void);
-Manager *manager_ref(Manager *manager);
-void manager_unref(Manager *manager);
-
-bool manager_set_port(Manager *manager, const char *port);
-bool manager_parse_config(Manager *manager, const char *configfile);
-
-bool manager_start(Manager *manager);
-void manager_stop(Manager *manager);
-
-void manager_check_system_status(Manager *manager, int prev_number_of_nodes_online);
-
-Node *manager_find_node(Manager *manager, const char *name);
-Node *manager_find_node_by_path(Manager *manager, const char *path);
-void manager_remove_node(Manager *manager, Node *node);
-
-Node *manager_add_node(Manager *manager, const char *name);
-
-bool manager_add_job(Manager *manager, Job *job);
-void manager_remove_job(Manager *manager, Job *job, const char *result);
-void manager_finish_job(Manager *manager, uint32_t job_id, const char *result);
-void manager_job_state_changed(Manager *manager, uint32_t job_id, const char *state);
-
-void manager_remove_monitor(Manager *manager, Monitor *monitor);
-
-void manager_add_subscription(Manager *manager, Subscription *sub);
-void manager_remove_subscription(Manager *manager, Subscription *sub);
-
-DEFINE_CLEANUP_FUNC(Manager, manager_unref)
-#define _cleanup_manager_ _cleanup_(manager_unrefp)


Test patch:
diff --git a/src/libbluechi/test/common/cfg/cfg_def_conf_test.c b/src/libbluechi/test/common/cfg/cfg_def_conf_test.c
index 52e172de5d..b54ce45cba 100644
--- a/src/libbluechi/test/common/cfg/cfg_def_conf_test.c
+++ b/src/libbluechi/test/common/cfg/cfg_def_conf_test.c
@@ -97,20 +97,20 @@ bool test_cfg_agent_def_conf() {
                         CFG_NODE_NAME);
                 result = false;
         }
-        value = cfg_get_value(config, CFG_MANAGER_HOST);
+        value = cfg_get_value(config, CFG_CONTROLLER_HOST);
         if (!streq(value, BC_DEFAULT_HOST)) {
                 fprintf(stderr,
                         "Expected config option %s to have default value '%s', but got '%s'\n",
-                        CFG_MANAGER_HOST,
+                        CFG_CONTROLLER_HOST,
                         BC_DEFAULT_HOST,
                         value);
                 result = false;
         }
-        value = cfg_get_value(config, CFG_MANAGER_PORT);
+        value = cfg_get_value(config, CFG_CONTROLLER_PORT);
         if (!streq(value, BC_DEFAULT_PORT)) {
                 fprintf(stderr,
                         "Expected config option %s to have default value '%s', but got '%s'\n",
-                        CFG_MANAGER_PORT,
+                        CFG_CONTROLLER_PORT,
                         BC_DEFAULT_PORT,
                         value);
                 result = false;
@@ -129,11 +129,11 @@ bool test_cfg_agent_def_conf() {
         return result;
 }
 
-bool test_cfg_manager_def_conf() {
+bool test_cfg_controller_def_conf() {
         struct config *config = NULL;
         cfg_initialize(&config);
 
-        int r = cfg_manager_def_conf(config);
+        int r = cfg_controller_def_conf(config);
         if (r < 0) {
                 fprintf(stderr, "Unexpected error while setting agent default values: %s", strerror(-r));
                 cfg_dispose(config);
@@ -208,12 +208,12 @@ bool test_cfg_manager_def_conf() {
                 result = false;
         }
 
-        /* Manager specific options */
-        value = cfg_get_value(config, CFG_MANAGER_PORT);
+        /* Controller specific options */
+        value = cfg_get_value(config, CFG_CONTROLLER_PORT);
         if (!streq(value, BC_DEFAULT_PORT)) {
                 fprintf(stderr,
                         "Expected config option %s to have default value '%s', but got '%s'\n",
-                        CFG_MANAGER_PORT,
+                        CFG_CONTROLLER_PORT,
                         BC_DEFAULT_PORT,
                         value);
                 result = false;
@@ -236,7 +236,7 @@ int main() {
         bool result = true;
 
         result = result && test_cfg_agent_def_conf();
-        result = result && test_cfg_manager_def_conf();
+        result = result && test_cfg_controller_def_conf();
 
         if (result) {
                 return EXIT_SUCCESS;
diff --git a/tests/bluechi_test/config.py b/tests/bluechi_test/config.py
index eb4a809794..add8bf2ec9 100644
--- a/tests/bluechi_test/config.py
+++ b/tests/bluechi_test/config.py
@@ -76,9 +76,9 @@ def __init__(
             self,
             file_name: str,
             node_name: str = "",
-            manager_host: str = "",
-            manager_port: str = "8420",
-            manager_address: str = "",
+            controller_host: str = "",
+            controller_port: str = "8420",
+            controller_address: str = "",
             heartbeat_interval: str = "2000",
             log_level: str = "DEBUG",
             log_target: str = "journald",
@@ -86,9 +86,9 @@ def __init__(
         super().__init__(file_name)
 
         self.node_name = node_name
-        self.manager_host = manager_host
-        self.manager_port = manager_port
-        self.manager_address = manager_address
+        self.controller_host = controller_host
+        self.controller_port = controller_port
+        self.controller_address = controller_address
         self.heartbeat_interval = heartbeat_interval
         self.log_level = log_level
         self.log_target = log_target
@@ -97,9 +97,9 @@ def __init__(
     def serialize(self) -> str:
         return f"""[bluechi-agent]
 NodeName={self.node_name}
-ControllerHost={self.manager_host}
-ControllerPort={self.manager_port}
-ControllerAddress={self.manager_address}
+ControllerHost={self.controller_host}
+ControllerPort={self.controller_port}
+ControllerAddress={self.controller_address}
 HeartbeatInterval={self.heartbeat_interval}
 LogLevel={self.log_level}
 LogTarget={self.log_target}
@@ -112,9 +112,9 @@ def get_confd_dir(self) -> str:
     def deep_copy(self) -> "BluechiNodeConfig":
         cfg = BluechiNodeConfig(self.file_name)
         cfg.node_name = self.node_name
-        cfg.manager_host = self.manager_host
-        cfg.manager_port = self.manager_port
-        cfg.manager_address = self.manager_address
+        cfg.controller_host = self.controller_host
+        cfg.controller_port = self.controller_port
+        cfg.controller_address = self.controller_address
         cfg.heartbeat_interval = self.heartbeat_interval
         cfg.log_level = self.log_level
         cfg.log_target = self.log_target
diff --git a/tests/bluechi_test/container_scripts/create_monitor.py b/tests/bluechi_test/container_scripts/create_monitor.py
index 505683acb7..a22682b84a 100644
--- a/tests/bluechi_test/container_scripts/create_monitor.py
+++ b/tests/bluechi_test/container_scripts/create_monitor.py
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 import sys
-from bluechi.api import Manager, Monitor
+from bluechi.api import Controller, Monitor
 from dasbus.loop import EventLoop
 
 if len(sys.argv) != 3:
@@ -12,7 +12,7 @@
 service = sys.argv[2]
 
 loop = EventLoop()
-mgr = Manager()
+mgr = Controller()
 monitor_path = mgr.create_monitor()
 monitor = Monitor(monitor_path)
 monitor.subscribe(node, service)
diff --git a/tests/bluechi_test/fixtures.py b/tests/bluechi_test/fixtures.py
index 4fe481d04d..eeed2ea379 100644
--- a/tests/bluechi_test/fixtures.py
+++ b/tests/bluechi_test/fixtures.py
@@ -96,8 +96,8 @@ def bluechi_ctrl_default_config(bluechi_ctrl_svc_port: str):
 def bluechi_node_default_config(bluechi_ctrl_svc_port: str):
     return BluechiNodeConfig(
         file_name="agent.conf",
-        manager_host=get_primary_ip(),
-        manager_port=bluechi_ctrl_svc_port)
+        controller_host=get_primary_ip(),
+        controller_port=bluechi_ctrl_svc_port)
 
 
 @pytest.fixture(scope='function')
diff --git a/tests/tests/tier0/bluechi-agent-invalid-port-configuration/test_agent_invalid_port_configuration.py b/tests/tests/tier0/bluechi-agent-invalid-port-configuration/test_agent_invalid_port_configuration.py
index 0399eff28f..ecfc0edcc9 100644
--- a/tests/tests/tier0/bluechi-agent-invalid-port-configuration/test_agent_invalid_port_configuration.py
+++ b/tests/tests/tier0/bluechi-agent-invalid-port-configuration/test_agent_invalid_port_configuration.py
@@ -24,11 +24,11 @@ def test_agent_invalid_port_configuration(
 
     node_foo_cfg = bluechi_node_default_config.deep_copy()
     node_foo_cfg.node_name = NODE_FOO
-    node_foo_cfg.manager_port = "8420"
+    node_foo_cfg.controller_port = "8420"
 
     node_bar_cfg = bluechi_node_default_config.deep_copy()
     node_bar_cfg.node_name = NODE_BAR
-    node_bar_cfg.manager_port = "842O"
+    node_bar_cfg.controller_port = "842O"
 
     bluechi_ctrl_default_config.allowed_node_names = [NODE_FOO, NODE_BAR]
     bluechi_test.set_bluechi_controller_config(bluechi_ctrl_default_config)
diff --git a/tests/tests/tier0/bluechi-agent-resolve-fqdn/test_bluechi_agent_resolve_fqdn.py b/tests/tests/tier0/bluechi-agent-resolve-fqdn/test_bluechi_agent_resolve_fqdn.py
index d284398fae..115dc52417 100644
--- a/tests/tests/tier0/bluechi-agent-resolve-fqdn/test_bluechi_agent_resolve_fqdn.py
+++ b/tests/tests/tier0/bluechi-agent-resolve-fqdn/test_bluechi_agent_resolve_fqdn.py
@@ -14,15 +14,15 @@
 def create_local_node_config() -> BluechiNodeConfig:
     return BluechiNodeConfig(
         file_name="agent.conf",
-        manager_host=get_primary_ip(),
-        manager_port='8420')
+        controller_host=get_primary_ip(),
+        controller_port='8420')
 
 
 def verify_resolving_fqdn(ctrl: BluechiControllerContainer, _: Dict[str, BluechiNodeContainer]):
     # create config for local bluechi-agent and adding config to controller container
     local_node_cfg = create_local_node_config()
     local_node_cfg.node_name = local_node_name
-    local_node_cfg.manager_host = "localhost"
+    local_node_cfg.controller_host = "localhost"
     ctrl.create_file(local_node_cfg.get_confd_dir(), local_node_cfg.file_name, local_node_cfg.serialize())
 
     ctrl.systemctl_start_and_wait("bluechi-agent", 1)
diff --git a/tests/tests/tier0/bluechi-and-agent-on-same-machine/test_bluechi_and_agent_on_same_machine.py b/tests/tests/tier0/bluechi-and-agent-on-same-machine/test_bluechi_and_agent_on_same_machine.py
index b1e1ab1dd2..a6e1e27de6 100644
--- a/tests/tests/tier0/bluechi-and-agent-on-same-machine/test_bluechi_and_agent_on_same_machine.py
+++ b/tests/tests/tier0/bluechi-and-agent-on-same-machine/test_bluechi_and_agent_on_same_machine.py
@@ -17,8 +17,8 @@ def exec(ctrl: BluechiControllerContainer, nodes: Dict[str, BluechiNodeContainer
     node_foo_config = BluechiNodeConfig(
         file_name="agent.conf",
         node_name=node_foo_name,
-        manager_host="localhost",
-        manager_port=ctrl.config.port,
+        controller_host="localhost",
+        controller_port=ctrl.config.port,
     )
     ctrl.create_file(node_foo_config.get_confd_dir(), node_foo_config.file_name, node_foo_config.serialize())
     result, _, wait_result = ctrl.systemctl_start_and_wait("bluechi-agent", 1)
diff --git a/tests/tests/tier0/bluechi-anonymous-node/python/node_foo_not_connected.py b/tests/tests/tier0/bluechi-anonymous-node/python/node_foo_not_connected.py
index ea84da1c59..910b4d985c 100644
--- a/tests/tests/tier0/bluechi-anonymous-node/python/node_foo_not_connected.py
+++ b/tests/tests/tier0/bluechi-anonymous-node/python/node_foo_not_connected.py
@@ -2,13 +2,13 @@
 
 import unittest
 
-from bluechi.api import Manager
+from bluechi.api import Controller
 
 
 class TestNodeFooNotConnected(unittest.TestCase):
 
     def test_node_foo_not_connected(self):
-        mgr = Manager()
+        mgr = Controller()
 
         nodes = mgr.list_nodes()
         assert len(nodes) == 1
diff --git a/tests/tests/tier0/metrics-start-unit/python/start_unit_job_metrics.py b/tests/tests/tier0/metrics-start-unit/python/start_unit_job_metrics.py
index 57386dbe15..118c831328 100644
--- a/tests/tests/tier0/metrics-start-unit/python/start_unit_job_metrics.py
+++ b/tests/tests/tier0/metrics-start-unit/python/start_unit_job_metrics.py
@@ -2,7 +2,7 @@
 
 import unittest
 
-from bluechi.api import Manager, Metrics, Node, UInt64
+from bluechi.api import Controller, Metrics, Node, UInt64
 from dasbus.loop import EventLoop
 
 
@@ -11,7 +11,7 @@ class TestStartUnitJobMetrics(unittest.TestCase):
     def setUp(self) -> None:
         self.loop = EventLoop()
 
-        self.mgr = Manager()
+        self.mgr = Controller()
         self.mgr.enable_metrics()
 
         self.metrics = Metrics()
diff --git a/tests/tests/tier0/monitor-agent-loses-connection/test_monitor_agent_loses_connection.py b/tests/tests/tier0/monitor-agent-loses-connection/test_monitor_agent_loses_connection.py
index 6204216769..4e93f8f8d1 100644
--- a/tests/tests/tier0/monitor-agent-loses-connection/test_monitor_agent_loses_connection.py
+++ b/tests/tests/tier0/monitor-agent-loses-connection/test_monitor_agent_loses_connection.py
@@ -16,8 +16,8 @@ def start_agent_in_ctrl_container(ctrl: BluechiControllerContainer):
     node_foo_config = BluechiNodeConfig(
         file_name="agent.conf",
         node_name=node_foo_name,
-        manager_host="localhost",
-        manager_port=ctrl.config.port,
+        controller_host="localhost",
+        controller_port=ctrl.config.port,
     )
     ctrl.create_file(node_foo_config.get_confd_dir(), node_foo_config.file_name, node_foo_config.serialize())
     result, _, wait_result = ctrl.systemctl_start_and_wait("bluechi-agent", 1)
diff --git a/tests/tests/tier0/monitor-listener-owner-added-as-peer/python/added_owner_as_peer.py b/tests/tests/tier0/monitor-listener-owner-added-as-peer/python/added_owner_as_peer.py
index c0ec896d69..3f4aa09970 100644
--- a/tests/tests/tier0/monitor-listener-owner-added-as-peer/python/added_owner_as_peer.py
+++ b/tests/tests/tier0/monitor-listener-owner-added-as-peer/python/added_owner_as_peer.py
@@ -2,7 +2,7 @@
 
 import unittest
 
-from bluechi.api import Manager, Monitor
+from bluechi.api import Controller, Monitor
 from dasbus.error import DBusError
 
 node = "node-foo"
@@ -13,7 +13,7 @@ class TestListenerAddedIsOwner(unittest.TestCase):
 
     def test_listener_added_is_owner(self):
 
-        mgr = Manager()
+        mgr = Controller()
         monitor_path = mgr.create_monitor()
         monitor = Monitor(monitor_path)
 
diff --git a/tests/tests/tier0/monitor-multiple-nodes-and-units/python/monitor.py b/tests/tests/tier0/monitor-multiple-nodes-and-units/python/monitor.py
index 8279bdb273..0295087a3d 100644
--- a/tests/tests/tier0/monitor-multiple-nodes-and-units/python/monitor.py
+++ b/tests/tests/tier0/monitor-multiple-nodes-and-units/python/monitor.py
@@ -4,7 +4,7 @@
 
 from dasbus.loop import EventLoop
 
-from bluechi.api import Manager, Monitor, Node, Structure
+from bluechi.api import Controller, Monitor, Node, Structure
 
 node_name_foo = "node-foo"
 node_name_bar = "node-bar"
@@ -17,7 +17,7 @@ class TestMonitorMultipleNodesAndUnits(unittest.TestCase):
 
     def setUp(self) -> None:
         self.loop = EventLoop()
-        self.mgr = Manager()
+        self.mgr = Controller()
 
         self.times_new_called = 0
         self.times_state_changed_called = 0
diff --git a/tests/tests/tier0/monitor-node-disconnect/python/monitor.py b/tests/tests/tier0/monitor-node-disconnect/python/monitor.py
index cd00fe5d3f..eb9d06493e 100644
--- a/tests/tests/tier0/monitor-node-disconnect/python/monitor.py
+++ b/tests/tests/tier0/monitor-node-disconnect/python/monitor.py
@@ -6,7 +6,7 @@
 from dasbus.loop import EventLoop
 from dasbus.typing import Variant
 
-from bluechi.api import Manager, Node
+from bluechi.api import Controller, Node
 
 
 class TestNodeDisconnect(unittest.TestCase):
@@ -20,7 +20,7 @@ def on_state_change(state: Variant):
             self.node_state = state.get_string()
             loop.quit()
 
-        mgr = Manager()
+        mgr = Controller()
         nodes = mgr.list_nodes()
         if len(nodes) < 1:
             raise Exception("No connected node found")
diff --git a/tests/tests/tier0/monitor-open-close/python/monitor.py b/tests/tests/tier0/monitor-open-close/python/monitor.py
index 9c440444e2..17ab5aa9d8 100644
--- a/tests/tests/tier0/monitor-open-close/python/monitor.py
+++ b/tests/tests/tier0/monitor-open-close/python/monitor.py
@@ -4,7 +4,7 @@
 
 from dasbus.error import DBusError
 
-from bluechi.api import Manager, Monitor
+from bluechi.api import Controller, Monitor
 
 # Subscribing to a closed monitor should result in a DBusError since the monitor has removed.
 # In this test we first subscribe to an open monitor to verify everything works, then close
@@ -14,7 +14,7 @@
 class TestOpenClose(unittest.TestCase):
 
     def test_open_close(self):
-        mgr = Manager()
+        mgr = Controller()
         monitor_path = mgr.create_monitor()
         monitor = Monitor(monitor_path=monitor_path)
         monitor.subscribe('not-important-node', 'not-important-unit')
diff --git a/tests/tests/tier0/monitor-specific-node-and-unit/python/monitor.py b/tests/tests/tier0/monitor-specific-node-and-unit/python/monitor.py
index 24c8fe590b..d9f233f667 100644
--- a/tests/tests/tier0/monitor-specific-node-and-unit/python/monitor.py
+++ b/tests/tests/tier0/monitor-specific-node-and-unit/python/monitor.py
@@ -4,7 +4,7 @@
 
 from dasbus.loop import EventLoop
 
-from bluechi.api import Manager, Monitor, Node, Structure
+from bluechi.api import Controller, Monitor, Node, Structure
 
 node_name_foo = "node-foo"
 
@@ -15,7 +15,7 @@ class TestMonitorSpecificNodeAndUnit(unittest.TestCase):
 
     def setUp(self) -> None:
         self.loop = EventLoop()
-        self.mgr = Manager()
+        self.mgr = Controller()
 
         self.times_new_called = 0
         self.times_state_changed_called = 0
diff --git a/tests/tests/tier0/monitor-system-status-ctrl-stop/python/system-monitor.py b/tests/tests/tier0/monitor-system-status-ctrl-stop/python/system-monitor.py
index fe4c864ce8..64187a88cd 100644
--- a/tests/tests/tier0/monitor-system-status-ctrl-stop/python/system-monitor.py
+++ b/tests/tests/tier0/monitor-system-status-ctrl-stop/python/system-monitor.py
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
-from bluechi.api import Manager
+from bluechi.api import Controller
 from dasbus.loop import EventLoop
 from dasbus.typing import Variant
 
@@ -26,7 +26,7 @@ def on_system_status_changed(status: Variant):
 
     loop = EventLoop()
 
-    mgr = Manager()
+    mgr = Controller()
     mgr.on_status_changed(on_system_status_changed)
 
     loop.run()
diff --git a/tests/tests/tier0/monitor-system-status/python/system-monitor.py b/tests/tests/tier0/monitor-system-status/python/system-monitor.py
index fe4c864ce8..64187a88cd 100644
--- a/tests/tests/tier0/monitor-system-status/python/system-monitor.py
+++ b/tests/tests/tier0/monitor-system-status/python/system-monitor.py
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
-from bluechi.api import Manager
+from bluechi.api import Controller
 from dasbus.loop import EventLoop
 from dasbus.typing import Variant
 
@@ -26,7 +26,7 @@ def on_system_status_changed(status: Variant):
 
     loop = EventLoop()
 
-    mgr = Manager()
+    mgr = Controller()
     mgr.on_status_changed(on_system_status_changed)
 
     loop.run()
diff --git a/tests/tests/tier0/monitor-unsubscribe/python/unsubscribe-automatically.py b/tests/tests/tier0/monitor-unsubscribe/python/unsubscribe-automatically.py
index 3680f9e7d1..a988d8e69b 100644
--- a/tests/tests/tier0/monitor-unsubscribe/python/unsubscribe-automatically.py
+++ b/tests/tests/tier0/monitor-unsubscribe/python/unsubscribe-automatically.py
@@ -4,7 +4,7 @@
 
 from dasbus.loop import EventLoop
 
-from bluechi.api import Manager, Monitor, Node
+from bluechi.api import Controller, Monitor, Node
 
 
 node_name_foo = "node-foo"
@@ -15,7 +15,7 @@ class TestUnsubscribe(unittest.TestCase):
 
     def setUp(self) -> None:
         self.loop = EventLoop()
-        self.mgr = Manager()
+        self.mgr = Controller()
         monitor_path = self.mgr.create_monitor()
         self.monitor = Monitor(monitor_path=monitor_path)
 
diff --git a/tests/tests/tier0/monitor-wildcard-node-reconnect/python/monitor.py b/tests/tests/tier0/monitor-wildcard-node-reconnect/python/monitor.py
index 40f5b08fb4..66a6d6dea6 100644
--- a/tests/tests/tier0/monitor-wildcard-node-reconnect/python/monitor.py
+++ b/tests/tests/tier0/monitor-wildcard-node-reconnect/python/monitor.py
@@ -5,7 +5,7 @@
 from dasbus.error import DBusError
 from dasbus.loop import EventLoop
 
-from bluechi.api import Manager, Monitor, Node
+from bluechi.api import Controller, Monitor, Node
 
 
 class TestMonitorWildcardNodeReconnect(unittest.TestCase):
@@ -15,7 +15,7 @@ def setUp(self) -> None:
         self.expected_nodes_unit_removed = ["node-foo"]
 
         self.loop = EventLoop()
-        self.mgr = Manager()
+        self.mgr = Controller()
         self.monitor = Monitor(self.mgr.create_monitor())
 
         def on_unit_new(node: str, unit: str, reason: str) -> None:
diff --git a/tests/tests/tier0/monitor-wildcard-unit-changes/python/monitor.py b/tests/tests/tier0/monitor-wildcard-unit-changes/python/monitor.py
index c2dc51c83d..b64eaeeb7e 100644
--- a/tests/tests/tier0/monitor-wildcard-unit-changes/python/monitor.py
+++ b/tests/tests/tier0/monitor-wildcard-unit-changes/python/monitor.py
@@ -4,7 +4,7 @@
 
 from dasbus.loop import EventLoop
 
-from bluechi.api import Manager, Monitor, Node, Structure
+from bluechi.api import Controller, Monitor, Node, Structure
 
 # In this test, first the wildcard subscription is created and then the systemd units on both nodes
 # are started. These systemd only units start and exit, therefore triggering all lifecycle events.
@@ -37,7 +37,7 @@ def setUp(self) -> None:
         }
 
         self.loop = EventLoop()
-        self.mgr = Manager()
+        self.mgr = Controller()
         self.monitor = Monitor(self.mgr.create_monitor())
 
         def on_unit_new(node: str, unit: str, reason: str) -> None: