[systemd-devel] [PATCH 1/3] dbus: introduce new method call NewTransientUnit
WaLyong Cho
walyong.cho at samsung.com
Mon Oct 6 22:20:08 PDT 2014
It similar with StartTransientUnit but the NewTransientUnit does not
start the unit immediately. Newly generated transient unit can be
activated by "systemctl start".
---
src/core/dbus-manager.c | 99 +++++++++++++++++++++++++++++-----
src/core/org.freedesktop.systemd1.conf | 4 ++
src/core/service.c | 12 +++++
3 files changed, 103 insertions(+), 12 deletions(-)
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 533ce43..84c913b 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -615,10 +615,15 @@ static int method_set_unit_properties(sd_bus *bus, sd_bus_message *message, void
return bus_unit_method_set_properties(bus, message, u, error);
}
-static int method_start_transient_unit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
+static int new_transient_unit_from_message(sd_bus *bus,
+ sd_bus_message *message,
+ void *userdata,
+ sd_bus_error *error,
+ Unit **unit,
+ JobMode *mode,
+ bool keep) {
const char *name, *smode;
Manager *m = userdata;
- JobMode mode;
UnitType t;
Unit *u;
int r;
@@ -631,7 +636,9 @@ static int method_start_transient_unit(sd_bus *bus, sd_bus_message *message, voi
if (r < 0)
return r;
if (r == 0)
- return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+ /* No authorization for now, but the async polkit
+ * stuff will call us again when it has it */
+ return 1;
r = sd_bus_message_read(message, "ss", &name, &smode);
if (r < 0)
@@ -639,14 +646,22 @@ static int method_start_transient_unit(sd_bus *bus, sd_bus_message *message, voi
t = unit_name_to_type(name);
if (t < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit type.");
+ return sd_bus_error_setf(error,
+ SD_BUS_ERROR_INVALID_ARGS,
+ "Invalid unit type.");
if (!unit_vtable[t]->can_transient)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit type %s does not support transient units.", unit_type_to_string(t));
-
- mode = job_mode_from_string(smode);
- if (mode < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s is invalid.", smode);
+ return sd_bus_error_setf(error,
+ SD_BUS_ERROR_INVALID_ARGS,
+ "Unit type %s does not support transient units.",
+ unit_type_to_string(t));
+
+ *mode = job_mode_from_string(smode);
+ if (*mode < 0)
+ return sd_bus_error_setf(error,
+ SD_BUS_ERROR_INVALID_ARGS,
+ "Job mode %s is invalid.",
+ smode);
r = selinux_access_check(message, "start", error);
if (r < 0)
@@ -656,8 +671,12 @@ static int method_start_transient_unit(sd_bus *bus, sd_bus_message *message, voi
if (r < 0)
return r;
- if (u->load_state != UNIT_NOT_FOUND || set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0)
- return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name);
+ if (u->load_state != UNIT_NOT_FOUND ||
+ set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0)
+ return sd_bus_error_setf(error,
+ BUS_ERROR_UNIT_EXISTS,
+ "Unit %s already exists.",
+ name);
/* OK, the unit failed to load and is unreferenced, now let's
* fill in the transient data instead */
@@ -675,10 +694,65 @@ static int method_start_transient_unit(sd_bus *bus, sd_bus_message *message, voi
if (r < 0)
return r;
+ *unit = u;
manager_dispatch_load_queue(m);
+ return 0;
+}
+
+static int method_new_transient_unit(sd_bus *bus,
+ sd_bus_message *message,
+ void *userdata,
+ sd_bus_error *error) {
+ _cleanup_free_ char *path = NULL;
+ JobMode mode;
+ Unit *u = NULL;
+ int r;
+
+ r = new_transient_unit_from_message(bus,
+ message,
+ userdata,
+ error,
+ &u,
+ &mode,
+ true);
+
+ if (r != 0)
+ return r;
+
+ path = unit_dbus_path(u);
+ if (!path)
+ return -ENOMEM;
+
+ return sd_bus_reply_method_return(message, "o", path);
+}
+
+static int method_start_transient_unit(sd_bus *bus,
+ sd_bus_message *message,
+ void *userdata,
+ sd_bus_error *error) {
+ JobMode mode;
+ Unit *u = NULL;
+ int r;
+
+ r = new_transient_unit_from_message(bus,
+ message,
+ userdata,
+ error,
+ &u,
+ &mode,
+ false);
+ if (r != 0)
+ return r;
+
/* Finally, start it */
- return bus_unit_queue_job(bus, message, u, JOB_START, mode, false, error);
+ return bus_unit_queue_job(bus,
+ message,
+ u,
+ JOB_START,
+ mode,
+ false,
+ error);
}
static int method_get_job(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
@@ -1881,6 +1955,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetUnitProperties", "sba(sv)", NULL, method_set_unit_properties, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("NewTransientUnit", "ssa(sv)a(sa(sv))", "o", method_new_transient_unit, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetJob", "u", "o", method_get_job, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CancelJob", "u", NULL, method_cancel_job, SD_BUS_VTABLE_UNPRIVILEGED),
diff --git a/src/core/org.freedesktop.systemd1.conf b/src/core/org.freedesktop.systemd1.conf
index 3e13825..2b8648e 100644
--- a/src/core/org.freedesktop.systemd1.conf
+++ b/src/core/org.freedesktop.systemd1.conf
@@ -144,6 +144,10 @@
<allow send_destination="org.freedesktop.systemd1"
send_interface="org.freedesktop.systemd1.Manager"
+ send_member="NewTransientUnit"/>
+
+ <allow send_destination="org.freedesktop.systemd1"
+ send_interface="org.freedesktop.systemd1.Manager"
send_member="StartTransientUnit"/>
<allow send_destination="org.freedesktop.systemd1"
diff --git a/src/core/service.c b/src/core/service.c
index 395e0ca..52c0981 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -467,6 +467,14 @@ static int service_load(Unit *u) {
}
}
+ /* If transient service unit is generated by NewTransientUnit
+ * then this unit will be removed by gabage collector
+ * soon. But we want this unit is remained until be actived by
+ * other. And we don't know who is the other. So just prevent
+ * gabage collected. */
+ if (u->transient)
+ u->no_gc = true;
+
return service_verify(s);
}
@@ -1642,6 +1650,10 @@ static int service_start(Unit *u) {
assert(s);
+ /* Make sure be gabage collected transient service unit. */
+ if (u->transient)
+ u->no_gc = false;
+
/* We cannot fulfill this request right now, try again later
* please! */
if (s->state == SERVICE_STOP ||
--
1.9.3
More information about the systemd-devel
mailing list