From c2756a68401102786be343712c0c35acbd73d28d Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 28 Jun 2013 04:12:58 +0200 Subject: core: add transient units Transient units can be created via the bus API. They are configured via the method call parameters rather than on-disk files. They are subject to normal GC. Transient units currently may only be created for services (however, we will extend this), and currently only ExecStart= and the cgroup parameters can be configured (also to be extended). Transient units require a unique name, that previously had no configuration file on disk. A tool systemd-run is added that makes use of this functionality to run arbitrary command lines as transient services: $ systemd-run /bin/ping www.heise.de Will cause systemd to create a new transient service and run ping in it. --- src/core/dbus-service.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) (limited to 'src/core/dbus-service.c') diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c index 867ef7e54c..c2031c3bf1 100644 --- a/src/core/dbus-service.c +++ b/src/core/dbus-service.c @@ -21,6 +21,8 @@ #include +#include "strv.h" +#include "path-util.h" #include "dbus-unit.h" #include "dbus-execute.h" #include "dbus-kill.h" @@ -162,6 +164,124 @@ DBusHandlerResult bus_service_message_handler(Unit *u, DBusConnection *connectio return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps); } +static int bus_service_set_transient_properties( + Service *s, + const char *name, + DBusMessageIter *i, + UnitSetPropertiesMode mode, + DBusError *error) { + + int r; + + assert(name); + assert(s); + assert(i); + + if (streq(name, "ExecStart")) { + DBusMessageIter sub; + unsigned n = 0; + + if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY || + dbus_message_iter_get_element_type(i) != DBUS_TYPE_STRUCT) + return -EINVAL; + + dbus_message_iter_recurse(i, &sub); + while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) { + _cleanup_strv_free_ char **argv = NULL; + DBusMessageIter sub2; + dbus_bool_t ignore; + const char *path; + + dbus_message_iter_recurse(&sub, &sub2); + + if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0) + return -EINVAL; + + if (!path_is_absolute(path)) { + dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path); + return -EINVAL; + } + + r = bus_parse_strv_iter(&sub2, &argv); + if (r < 0) + return r; + + dbus_message_iter_next(&sub2); + + if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) < 0) + return -EINVAL; + + if (mode != UNIT_CHECK) { + ExecCommand *c; + + c = new0(ExecCommand, 1); + if (!c) + return -ENOMEM; + + c->path = strdup(path); + if (!c->path) { + free(c); + return -ENOMEM; + } + + c->argv = argv; + argv = NULL; + + c->ignore = ignore; + + path_kill_slashes(c->path); + exec_command_append_list(&s->exec_command[SERVICE_EXEC_START], c); + } + + n++; + dbus_message_iter_next(&sub); + } + + if (mode != UNIT_CHECK) { + _cleanup_free_ char *buf = NULL; + _cleanup_fclose_ FILE *f = NULL; + ExecCommand *c; + size_t size = 0; + + if (n == 0) { + exec_command_free_list(s->exec_command[SERVICE_EXEC_START]); + s->exec_command[SERVICE_EXEC_START] = NULL; + } + + f = open_memstream(&buf, &size); + if (!f) + return -ENOMEM; + + fputs("ExecStart=\n", f); + + LIST_FOREACH(command, c, s->exec_command[SERVICE_EXEC_START]) { + char **a; + fputs("ExecStart=", f); + + if (c->ignore) + fputc('-', f); + + fputc('@', f); + fputs(c->path, f); + + STRV_FOREACH(a, c->argv) { + fputc(' ', f); + fputs(*a, f); + } + + fputc('\n', f); + } + + fflush(f); + unit_write_drop_in_private_section(UNIT(s), mode, "exec-start", buf); + } + + return 1; + } + + return 0; +} + int bus_service_set_property( Unit *u, const char *name, @@ -180,6 +300,14 @@ int bus_service_set_property( if (r != 0) return r; + if (u->transient && u->load_state == UNIT_STUB) { + /* This is a transient unit, let's load a little more */ + + r = bus_service_set_transient_properties(s, name, i, mode, error); + if (r != 0) + return r; + } + return 0; } -- cgit v1.2.3-54-g00ecf