Skip to content

Commit

Permalink
Add support for unit file enable/disable and daemon-reload
Browse files Browse the repository at this point in the history
Add Reload, EnableUnitFiles and DisableUnitFiles in Node and internal Agent
Implement and use passthough methods in manager node and agent
Implement hirtectl enable/disable/daemon-reload
hirtectl - call daemon-reload after unit enable/disable
Update the man page
Add doc and example

Signed-off-by: Ygal Blum <[email protected]>
  • Loading branch information
ygalblum authored and engelmi committed May 31, 2023
1 parent 2c042bf commit f67706b
Show file tree
Hide file tree
Showing 9 changed files with 434 additions and 2 deletions.
13 changes: 13 additions & 0 deletions data/org.containers.hirte.Node.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,22 @@
<arg name="runtime" type="b" direction="in" />
<arg name="keyvalues" type="a(sv)" direction="in" />
</method>
<method name="EnableUnitFiles">
<arg name="files" type="as" direction="in" />
<arg name="runtime" type="b" direction="in" />
<arg name="force" type="b" direction="in" />
<arg name="carries_install_info" type="b" direction="out" />
<arg name="changes" type="a{sss}" direction="out" />
</method>
<method name="DisableUnitFiles">
<arg name="files" type="as" direction="in" />
<arg name="runtime" type="b" direction="in" />
<arg name="changes" type="a{sss}" direction="out" />
</method>
<method name="ListUnits">
<arg name="units" type="a(ssssssouso)" direction="out" />
</method>
<method name="Reload" />

<property name="Name" type="s" access="read" />
<property name="Status" type="s" access="read" />
Expand Down
13 changes: 13 additions & 0 deletions data/org.containers.hirte.internal.Agent.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,18 @@
<arg name="runtime" type="b" direction="in" />
<arg name="keyvalues" type="a(sv)" direction="in" />
</method>
<method name="EnableUnitFiles">
<arg name="files" type="as" direction="in" />
<arg name="runtime" type="b" direction="in" />
<arg name="force" type="b" direction="in" />
<arg name="carries_install_info" type="b" direction="out" />
<arg name="changes" type="a{sss}" direction="out" />
</method>
<method name="DisableUnitFiles">
<arg name="files" type="as" direction="in" />
<arg name="runtime" type="b" direction="in" />
<arg name="changes" type="a{sss}" direction="out" />
</method>
<method name="ListUnits">
<arg name="units" type="a(ssssssouso)" direction="out" />
</method>
Expand All @@ -60,6 +72,7 @@
<method name="StopDep">
<arg name="unit" type="s" direction="in" />
</method>
<method name="Reload" />

<signal name="JobDone">
<arg name="id" type="u" />
Expand Down
33 changes: 33 additions & 0 deletions doc/api-examples/enable-unit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/python3

import sys
from collections import namedtuple
import dasbus.connection
bus = dasbus.connection.SystemMessageBus()

EnabledServiceInfo = namedtuple("EnabledServicesInfo", ["op_type", "symlink_file", "symlink_dest"])
EnableResponse = namedtuple("EnableResponse", ["carries_install_info", "enabled_services_info"])

if len(sys.argv) < 2:
print(f"Usage: {sys.argv[0]} node_name unit_name...")
sys.exit(1)

node_name = sys.argv[1]

manager = bus.get_proxy("org.containers.hirte", "/org/containers/hirte")
node_path = manager.GetNode(node_name)
node = bus.get_proxy("org.containers.hirte", node_path)

response = node.EnableUnitFiles(sys.argv[2:], False, False)
enable_response = EnableResponse(*response)
if enable_response.carries_install_info:
print("The unit files included enablement information")
else:
print("The unit files did not include any enablement information")

for e in enable_response.enabled_services_info:
enabled_service_info = EnabledServiceInfo(*e)
if enabled_service_info.op_type == "symlink":
print(f"Created symlink {enabled_service_info.symlink_file} -> {enabled_service_info.symlink_dest}")
elif enabled_service_info.op_type == "unlink":
print(f"Removed \"{enabled_service_info.symlink_file}\".")
21 changes: 21 additions & 0 deletions doc/docs/api/description.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,23 @@ Object path: `/org/containers/hirte/node/$name`

Kill a unit on the node. Arguments and semantics are equivalent to the systemd `KillUnit()` method.

* `EnableUnitFiles(in as files, in b runtime, in b force, out b carries_install_info, out a(sss) changes);`

`EnableUnitFiles()` may be used to enable one or more units in the system (by creating symlinks to them in /etc/ or /run/).
It takes a list of unit files to enable
(either just file names or full absolute paths if the unit files are residing outside the usual unit search paths)
and two booleans: the first controls whether the unit shall be enabled for runtime only (true, /run/), or persistently (false, /etc/).
The second one controls whether symlinks pointing to other units shall be replaced if necessary.
This method returns one boolean and an array of the changes made.
The boolean signals whether the unit files contained any enablement information (i.e. an [Install] section).
The changes array consists of structures with three strings: the type of the change (one of "symlink" or "unlink"),
the file name of the symlink and the destination of the symlink.

* `DisableUnitFiles(in as files, in b runtime, out a(sss) changes);`

`DisableUnitFiles()` is similar to `EnableUnitFiles()` but
disables the specified units by removing all symlinks to them in /etc/ and /run/

* `GetUnitProperties(in s name, in s interface, out a{sv} props)`

Returns the current properties for a named unit on the node. The returned properties are the same as you would
Expand All @@ -165,6 +182,10 @@ Object path: `/org/containers/hirte/node/$name`
Returns all the currently loaded systemd units on this node. The returned structure is the same as the one returned
by the systemd `ListUnits()` call.

* `Reload()`

`Reload()` may be invoked to reload all unit files.

#### Properties

* `Name` - `s`
Expand Down
8 changes: 8 additions & 0 deletions doc/docs/api/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,11 @@ pip3 install dasbus
```

---

### Enable unit files

```python
--8<-- "api-examples/enable-unit.py"
```

---
12 changes: 10 additions & 2 deletions doc/man/hirtectl.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,22 @@ Print usage statement and exit.

Performs one of the listed lifecycle operations on the given systemd unit for the `hirte-agent`.

### **hirtectl** [*enable|disable*] [*agent*] [*unit1*,*...*]

Enable/Disable the list of systemd unit files for the `hirte-agent`.

### **hirtectl** *list-units* [*agent*]

Fetches information about all systemd units on the hirte-agents. If [hirte-agent] is not specified, all agents are queried.

### **hirtectl** *monitor* [*agent*] [*unit1*,*unit2*,*...*]

Creates a monitor on the given agent to observe changes in the specified units. Wildcards **\*** to match all agents and/or units are also supported.
Creates a monitor on the given agent to observe changes in the specified units. Wildcards **\*** to match all agents and/or units are also supported.

**Example:**

hirtectl monitor \\\* dbus.service,apache2.service
hirtectl monitor \\\* dbus.service,apache2.service

### **hirtectl** [*daemon-reload*] [*agent*]

Performs `daemon-reload` for the `hirte-agent`.
45 changes: 45 additions & 0 deletions src/agent/agent.c
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,48 @@ static AgentUnitInfo *agent_ensure_unit_info(Agent *agent, const char *unit) {
return info;
}

static int agent_method_passthrough_to_systemd_cb(
sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
_cleanup_systemd_request_ SystemdRequest *req = userdata;

if (sd_bus_message_is_method_error(m, NULL)) {
return sd_bus_reply_method_error(req->request_message, sd_bus_message_get_error(m));
}

_cleanup_sd_bus_message_ sd_bus_message *reply = NULL;
int r = sd_bus_message_new_method_return(req->request_message, &reply);
if (r < 0) {
return r;
}

r = sd_bus_message_copy(reply, m, true);
if (r < 0) {
return r;
}

return sd_bus_message_send(reply);
}

static int agent_method_passthrough_to_systemd(sd_bus_message *m, void *userdata, UNUSED sd_bus_error *ret_error) {
Agent *agent = userdata;
_cleanup_systemd_request_ SystemdRequest *req = agent_create_request(
agent, m, sd_bus_message_get_member(m));
if (req == NULL) {
return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_FAILED, "Internal error");
}

int r = sd_bus_message_copy(req->message, m, true);
if (r < 0) {
return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_FAILED, "Internal error");
}

if (!systemd_request_start(req, agent_method_passthrough_to_systemd_cb)) {
return sd_bus_reply_method_errorf(m, SD_BUS_ERROR_FAILED, "Internal error");
}

return 1;
}

/*************************************************************************
********** org.containers.hirte.internal.Agent.ListUnits ****************
************************************************************************/
Expand Down Expand Up @@ -1324,6 +1366,9 @@ static const sd_bus_vtable internal_agent_vtable[] = {
SD_BUS_SIGNAL_WITH_NAMES("Heartbeat", "s", SD_BUS_PARAM(agent_name), 0),
SD_BUS_METHOD("StartDep", "s", "", agent_method_start_dep, 0),
SD_BUS_METHOD("StopDep", "s", "", agent_method_stop_dep, 0),
SD_BUS_METHOD("EnableUnitFiles", "asbb", "ba(sss)", agent_method_passthrough_to_systemd, 0),
SD_BUS_METHOD("DisableUnitFiles", "asb", "a(sss)", agent_method_passthrough_to_systemd, 0),
SD_BUS_METHOD("Reload", "", "", agent_method_passthrough_to_systemd, 0),
SD_BUS_VTABLE_END
};

Expand Down
Loading

0 comments on commit f67706b

Please sign in to comment.