chiark / gitweb /
machined: port over to libsystemd-bus
authorLennart Poettering <lennart@poettering.net>
Wed, 30 Oct 2013 01:06:55 +0000 (02:06 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 30 Oct 2013 01:08:57 +0000 (02:08 +0100)
Makefile.am
src/libsystemd-bus/bus-util.h
src/machine/machine-dbus.c
src/machine/machine.c
src/machine/machine.h
src/machine/machined-dbus.c
src/machine/machined.c
src/machine/machined.h
src/shared/strv.h

index 85b2325..0ed33fd 100644 (file)
@@ -3709,15 +3709,14 @@ libsystemd_machine_core_la_SOURCES = \
        src/machine/machine-dbus.c
 
 libsystemd_machine_core_la_CFLAGS = \
-       $(AM_CFLAGS) \
-       $(DBUS_CFLAGS)
+       $(AM_CFLAGS)
 
 libsystemd_machine_core_la_LIBADD = \
        libsystemd-label.la \
        libsystemd-audit.la \
        libsystemd-shared.la \
        libsystemd-daemon.la \
-       libsystemd-dbus.la \
+       libsystemd-bus.la \
        libsystemd-id128-internal.la \
        libudev.la
 
@@ -3743,8 +3742,7 @@ test_machine_tables_SOURCES = \
        src/machine/test-machine-tables.c
 
 test_machine_tables_CFLAGS = \
-       $(AM_CFLAGS) \
-       $(DBUS_CFLAGS)
+       $(AM_CFLAGS)
 
 test_machine_tables_LDADD = \
        libsystemd-machine-core.la
index 9b270c8..cf00436 100644 (file)
@@ -43,5 +43,40 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus*, sd_bus_unref);
 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, sd_bus_message_unref);
 
 #define _cleanup_bus_unref_ _cleanup_(sd_bus_unrefp)
-#define _cleanup_bus_error_free_ _cleanup_(sd_bus_error_free)
 #define _cleanup_bus_message_unref_ _cleanup_(sd_bus_message_unrefp)
+#define _cleanup_bus_error_free_ _cleanup_(sd_bus_error_free)
+
+#define BUS_DEFINE_PROPERTY_GET_ENUM(function, name, type)              \
+        int function(sd_bus *bus,                                       \
+                     const char *path,                                  \
+                     const char *interface,                             \
+                     const char *property,                              \
+                     sd_bus_message *reply,                             \
+                     sd_bus_error *error,                               \
+                     void *userdata) {                                  \
+                                                                        \
+                const char *value;                                      \
+                type *field = userdata;                                 \
+                int r;                                                  \
+                                                                        \
+                assert(bus);                                            \
+                assert(reply);                                          \
+                assert(field);                                          \
+                                                                        \
+                value = strempty(name##_to_string(*field));             \
+                                                                        \
+                r = sd_bus_message_append_basic(reply, 's', value);     \
+                if (r < 0)                                              \
+                        return r;                                       \
+                                                                        \
+                return 1;                                               \
+        }                                                               \
+        struct __useless_struct_to_allow_trailing_semicolon__
+
+#define BUS_ERROR_NO_SUCH_UNIT "org.freedesktop.systemd1.NoSuchUnit"
+#define BUS_ERROR_LOAD_FAILED "org.freedesktop.systemd1.LoadFailed"
+#define BUS_ERROR_JOB_FAILED "org.freedesktop.systemd1.JobFailed"
+
+#define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine"
+#define BUS_ERROR_NO_MACHINE_FOR_PID "org.freedesktop.machine1.NoMachineForPID"
+#define BUS_ERROR_MACHINE_EXISTS "org.freedesktop.machine1.MachineExists"
index ceab96e..150a3f7 100644 (file)
 #include <errno.h>
 #include <string.h>
 
-#include "machined.h"
+#include "bus-util.h"
 #include "machine.h"
-#include "dbus-common.h"
-
-#define BUS_MACHINE_INTERFACE \
-        " <interface name=\"org.freedesktop.machine1.Machine\">\n"        \
-        "  <method name=\"Terminate\"/>\n"                              \
-        "  <method name=\"Kill\">\n"                                    \
-        "   <arg name=\"who\" type=\"s\"/>\n"                           \
-        "   <arg name=\"signal\" type=\"s\"/>\n"                        \
-        "  </method>\n"                                                 \
-        "  <property name=\"Name\" type=\"s\" access=\"read\"/>\n"      \
-        "  <property name=\"Id\" type=\"ay\" access=\"read\"/>\n"        \
-        "  <property name=\"Timestamp\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"TimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
-        "  <property name=\"Service\" type=\"s\" access=\"read\"/>\n"   \
-        "  <property name=\"Scope\" type=\"s\" access=\"read\"/>\n"     \
-        "  <property name=\"Leader\" type=\"u\" access=\"read\"/>\n"    \
-        "  <property name=\"Class\" type=\"s\" access=\"read\"/>\n"     \
-        "  <property name=\"State\" type=\"s\" access=\"read\"/>\n"     \
-        "  <property name=\"RootDirectory\" type=\"s\" access=\"read\"/>\n" \
-        " </interface>\n"
-
-#define INTROSPECTION                                                   \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_MACHINE_INTERFACE                                           \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE                                    \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_GENERIC_INTERFACES_LIST                  \
-        "org.freedesktop.machine1.Machine\0"
-
-static int bus_machine_append_id(DBusMessageIter *i, const char *property, void *data) {
-        DBusMessageIter sub;
-        Machine *m = data;
-        dbus_bool_t b;
-        void *p;
-
-        assert(i);
-        assert(property);
-        assert(m);
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "y", &sub))
-                return -ENOMEM;
+static int property_get_id(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
 
-        p = &m->id;
-        b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &p, 16);
-        if (!b)
-                return -ENOMEM;
+        Machine *m = userdata;
+        int r;
 
-        if (!dbus_message_iter_close_container(i, &sub))
-                return -ENOMEM;
+        assert(bus);
+        assert(reply);
+        assert(m);
+
+        r = sd_bus_message_append_array(reply, 'y', &m->id, 16);
+        if (r < 0)
+                return r;
 
-        return 0;
+        return 1;
 }
 
-static int bus_machine_append_state(DBusMessageIter *i, const char *property, void *data) {
-        Machine *m = data;
+static int property_get_state(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                sd_bus_error *error,
+                void *userdata) {
+
+        Machine *m = userdata;
         const char *state;
+        int r;
 
-        assert(i);
-        assert(property);
+        assert(bus);
+        assert(reply);
         assert(m);
 
         state = machine_state_to_string(machine_get_state(m));
 
-        if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &state))
-                return -ENOMEM;
+        r = sd_bus_message_append_basic(reply, 's', state);
+        if (r < 0)
+                return r;
 
-        return 0;
+        return 1;
 }
 
-static int get_machine_for_path(Manager *m, const char *path, Machine **_machine) {
-        _cleanup_free_ char *e = NULL;
-        Machine *machine;
-
-        assert(m);
-        assert(path);
-        assert(_machine);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, machine_class, MachineClass);
 
-        if (!startswith(path, "/org/freedesktop/machine1/machine/"))
-                return -EINVAL;
+static int method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Machine *m = userdata;
+        int r;
 
-        e = bus_path_unescape(path + 34);
-        if (!e)
-                return -ENOMEM;
+        assert(bus);
+        assert(message);
+        assert(m);
 
-        machine = hashmap_get(m->machines, e);
-        if (!machine)
-                return -ENOENT;
+        r = machine_stop(m);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-        *_machine = machine;
-        return 0;
+        return sd_bus_reply_method_return(bus, message, NULL);
 }
 
-static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_machine_append_class, machine_class, MachineClass);
-
-static const BusProperty bus_machine_machine_properties[] = {
-        { "Name",                   bus_property_append_string,        "s", offsetof(Machine, name),               true },
-        { "Id",                     bus_machine_append_id,            "ay", 0 },
-        { "Timestamp",              bus_property_append_usec,          "t", offsetof(Machine, timestamp.realtime)  },
-        { "TimestampMonotonic",     bus_property_append_usec,          "t", offsetof(Machine, timestamp.monotonic) },
-        { "Service",                bus_property_append_string,        "s", offsetof(Machine, service),            true },
-        { "Scope",                  bus_property_append_string,        "s", offsetof(Machine, scope),              true },
-        { "Leader",                 bus_property_append_pid,           "u", offsetof(Machine, leader)              },
-        { "Class",                  bus_machine_append_class,          "s", offsetof(Machine, class)               },
-        { "State",                  bus_machine_append_state,          "s", 0                                      },
-        { "RootDirectory",          bus_property_append_string,        "s", offsetof(Machine, root_directory),     true },
-        { NULL, }
-};
-
-static DBusHandlerResult machine_message_dispatch(
-                Machine *m,
-                DBusConnection *connection,
-                DBusMessage *message) {
-
-        DBusError error;
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+static int method_kill(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Machine *m = userdata;
+        const char *swho;
+        int32_t signo;
+        KillWho who;
         int r;
 
-        assert(m);
-        assert(connection);
+        assert(bus);
         assert(message);
+        assert(m);
 
-        if (dbus_message_is_method_call(message, "org.freedesktop.machine1.Machine", "Terminate")) {
-
-                r = machine_stop(m);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, NULL, r);
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.machine1.Machine", "Kill")) {
-                const char *swho;
-                int32_t signo;
-                KillWho who;
-
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &swho,
-                                    DBUS_TYPE_INT32, &signo,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                if (isempty(swho))
-                        who = KILL_ALL;
-                else {
-                        who = kill_who_from_string(swho);
-                        if (who < 0)
-                                return bus_send_error_reply(connection, message, &error, -EINVAL);
-                }
-
-                if (signo <= 0 || signo >= _NSIG)
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                r = machine_kill(m, who, signo);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, NULL, r);
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-        } else {
-                const BusBoundProperties bps[] = {
-                        { "org.freedesktop.machine1.Machine", bus_machine_machine_properties, m },
-                        { NULL, }
-                };
-
-                return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
-        }
+        r = sd_bus_message_read(message, "si", &swho, &signo);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-        if (reply) {
-                if (!bus_maybe_send_reply(connection, message, reply))
-                        goto oom;
+        if (isempty(swho))
+                who = KILL_ALL;
+        else {
+                who = kill_who_from_string(swho);
+                if (who < 0)
+                        return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
         }
 
-        return DBUS_HANDLER_RESULT_HANDLED;
+        if (signo <= 0 || signo >= _NSIG)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
 
-oom:
-        dbus_error_free(&error);
+        r = machine_kill(m, who, signo);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+        return sd_bus_reply_method_return(bus, message, NULL);
 }
 
-static DBusHandlerResult machine_message_handler(
-                DBusConnection *connection,
-                DBusMessage *message,
-                void *userdata) {
-
-        Manager *manager = userdata;
-        Machine *m;
-        int r;
+const sd_bus_vtable machine_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Machine, name), 0),
+        SD_BUS_PROPERTY("Id", "ay", property_get_id, 0, 0),
+        SD_BUS_PROPERTY("Timestamp", "t", NULL, offsetof(Machine, timestamp.realtime), 0),
+        SD_BUS_PROPERTY("TimestampMonotonic", "t", NULL, offsetof(Machine, timestamp.monotonic), 0),
+        SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Machine, service), 0),
+        SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Machine, scope), 0),
+        SD_BUS_PROPERTY("Leader", "u", NULL, offsetof(Machine, leader), 0),
+        SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Machine, class), 0),
+        SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
+        SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(Machine, root_directory), 0),
+        SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, 0),
+        SD_BUS_METHOD("Kill", "si", NULL, method_kill, 0),
+        SD_BUS_VTABLE_END
+};
 
-        r = get_machine_for_path(manager, dbus_message_get_path(message), &m);
-        if (r < 0) {
+int machine_object_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) {
+        _cleanup_free_ char *e = NULL;
+        Manager *m = userdata;
+        Machine *machine;
+        const char *p;
 
-                if (r == -ENOMEM)
-                        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+        assert(bus);
+        assert(path);
+        assert(interface);
+        assert(found);
+        assert(m);
 
-                if (r == -ENOENT) {
-                        DBusError e;
+        p = startswith(path, "/org/freedesktop/machine1/machine/");
+        if (!p)
+                return 0;
 
-                        dbus_error_init(&e);
-                        dbus_set_error_const(&e, DBUS_ERROR_UNKNOWN_OBJECT, "Unknown machine");
-                        return bus_send_error_reply(connection, message, &e, r);
-                }
+        e = bus_path_unescape(p);
+        if (!e)
+                return -ENOMEM;
 
-                return bus_send_error_reply(connection, message, NULL, r);
-        }
+        machine = hashmap_get(m->machines, e);
+        if (!machine)
+                return 0;
 
-        return machine_message_dispatch(m, connection, message);
+        *found = machine;
+        return 1;
 }
 
-const DBusObjectPathVTable bus_machine_vtable = {
-        .message_function = machine_message_handler
-};
-
 char *machine_bus_path(Machine *m) {
         _cleanup_free_ char *e = NULL;
 
@@ -260,105 +182,44 @@ char *machine_bus_path(Machine *m) {
 }
 
 int machine_send_signal(Machine *m, bool new_machine) {
-        _cleanup_dbus_message_unref_ DBusMessage *msg = NULL;
         _cleanup_free_ char *p = NULL;
 
         assert(m);
 
-        msg = dbus_message_new_signal("/org/freedesktop/machine1",
-                                    "org.freedesktop.machine1.Manager",
-                                    new_machine ? "MachineNew" : "MachineRemoved");
-
-        if (!m)
-                return -ENOMEM;
-
         p = machine_bus_path(m);
         if (!p)
                 return -ENOMEM;
 
-        if (!dbus_message_append_args(
-                            msg,
-                            DBUS_TYPE_STRING, &m->name,
-                            DBUS_TYPE_OBJECT_PATH, &p,
-                            DBUS_TYPE_INVALID))
-                return -ENOMEM;
-
-        if (!dbus_connection_send(m->manager->bus, msg, NULL))
-                return -ENOMEM;
-
-        return 0;
+        return sd_bus_emit_signal(
+                        m->manager->bus,
+                        "/org/freedesktop/machine1",
+                        "org.freedesktop.machine1.Manager",
+                        new_machine ? "MachineNew" : "MachineRemoved",
+                        "so", m->name, p);
 }
 
-int machine_send_changed(Machine *m, const char *properties) {
-        _cleanup_dbus_message_unref_ DBusMessage *msg = NULL;
+int machine_send_create_reply(Machine *m, sd_bus_error *error) {
+        _cleanup_bus_message_unref_ sd_bus_message *c = NULL;
         _cleanup_free_ char *p = NULL;
 
         assert(m);
 
-        if (!m->started)
-                return 0;
-
-        p = machine_bus_path(m);
-        if (!p)
-                return -ENOMEM;
-
-        msg = bus_properties_changed_new(p, "org.freedesktop.machine1.Machine", properties);
-        if (!msg)
-                return -ENOMEM;
-
-        if (!dbus_connection_send(m->manager->bus, msg, NULL))
-                return -ENOMEM;
-
-        return 0;
-}
-
-int machine_send_create_reply(Machine *m, DBusError *error) {
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
-
-        assert(m);
-
         if (!m->create_message)
                 return 0;
 
-        if (error) {
-                DBusError buffer;
-
-                dbus_error_init(&buffer);
-
-                if (!error || !dbus_error_is_set(error)) {
-                        dbus_set_error_const(&buffer, DBUS_ERROR_INVALID_ARGS, "Invalid Arguments");
-                        error = &buffer;
-                }
-
-                reply = dbus_message_new_error(m->create_message, error->name, error->message);
-                dbus_error_free(&buffer);
-
-                if (!reply)
-                        return log_oom();
-        } else {
-                _cleanup_free_ char *p = NULL;
-
-                p = machine_bus_path(m);
-                if (!p)
-                        return log_oom();
-
-                reply = dbus_message_new_method_return(m->create_message);
-                if (!reply)
-                        return log_oom();
-
-                if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &p, DBUS_TYPE_INVALID))
-                        return log_oom();
-        }
+        c = m->create_message;
+        m->create_message = NULL;
 
         /* Update the machine state file before we notify the client
          * about the result. */
         machine_save(m);
 
-        if (!dbus_connection_send(m->manager->bus, reply, NULL))
-                return log_oom();
+        if (error)
+                return sd_bus_reply_method_error(m->manager->bus, c, error);
 
-        dbus_message_unref(m->create_message);
-        m->create_message = NULL;
+        p = machine_bus_path(m);
+        if (!p)
+                return -ENOMEM;
 
-        return 0;
+        return sd_bus_reply_method_return(m->manager->bus, c, "o", p);
 }
index f78b0cf..be669f0 100644 (file)
@@ -23,7 +23,7 @@
 #include <unistd.h>
 #include <errno.h>
 
-#include <systemd/sd-messages.h>
+#include "sd-messages.h"
 
 #include "util.h"
 #include "mkdir.h"
@@ -32,8 +32,9 @@
 #include "fileio.h"
 #include "special.h"
 #include "unit-name.h"
-#include "dbus-common.h"
 #include "machine.h"
+#include "bus-util.h"
+#include "bus-error.h"
 
 Machine* machine_new(Manager *manager, const char *name) {
         Machine *m;
@@ -84,8 +85,7 @@ void machine_free(Machine *m) {
 
         hashmap_remove(m->manager->machines, m->name);
 
-        if (m->create_message)
-                dbus_message_unref(m->create_message);
+        sd_bus_message_unref(m->create_message);
 
         free(m->name);
         free(m->state_file);
@@ -217,19 +217,14 @@ int machine_load(Machine *m) {
         return r;
 }
 
-static int machine_start_scope(Machine *m, DBusMessageIter *iter) {
-        _cleanup_free_ char *description = NULL;
-        DBusError error;
-        char *job;
+static int machine_start_scope(Machine *m, sd_bus_message *properties, sd_bus_error *error) {
         int r = 0;
 
         assert(m);
 
-        dbus_error_init(&error);
-
         if (!m->scope) {
                 _cleanup_free_ char *escaped = NULL;
-                char *scope;
+                char *scope, *description, *job;
 
                 escaped = unit_name_escape(m->name);
                 if (!escaped)
@@ -239,13 +234,11 @@ static int machine_start_scope(Machine *m, DBusMessageIter *iter) {
                 if (!scope)
                         return log_oom();
 
-                description = strappend(m->class == MACHINE_VM ? "Virtual Machine " : "Container ", m->name);
+                description = strappenda(m->class == MACHINE_VM ? "Virtual Machine " : "Container ", m->name);
 
-                r = manager_start_scope(m->manager, scope, m->leader, SPECIAL_MACHINE_SLICE, description, iter, &error, &job);
+                r = manager_start_scope(m->manager, scope, m->leader, SPECIAL_MACHINE_SLICE, description, properties, error, &job);
                 if (r < 0) {
-                        log_error("Failed to start machine scope: %s", bus_error(&error, r));
-                        dbus_error_free(&error);
-
+                        log_error("Failed to start machine scope: %s", bus_error_message(error, r));
                         free(scope);
                         return r;
                 } else {
@@ -262,7 +255,7 @@ static int machine_start_scope(Machine *m, DBusMessageIter *iter) {
         return r;
 }
 
-int machine_start(Machine *m, DBusMessageIter *iter) {
+int machine_start(Machine *m, sd_bus_message *properties, sd_bus_error *error) {
         int r;
 
         assert(m);
@@ -271,7 +264,7 @@ int machine_start(Machine *m, DBusMessageIter *iter) {
                 return 0;
 
         /* Create cgroup */
-        r = machine_start_scope(m, iter);
+        r = machine_start_scope(m, properties, error);
         if (r < 0)
                 return r;
 
@@ -296,21 +289,18 @@ int machine_start(Machine *m, DBusMessageIter *iter) {
 }
 
 static int machine_stop_scope(Machine *m) {
-        DBusError error;
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         char *job;
         int r;
 
         assert(m);
 
-        dbus_error_init(&error);
-
         if (!m->scope)
                 return 0;
 
         r = manager_stop_unit(m->manager, m->scope, &error, &job);
         if (r < 0) {
-                log_error("Failed to stop machine scope: %s", bus_error(&error, r));
-                dbus_error_free(&error);
+                log_error("Failed to stop machine scope: %s", bus_error_message(&error, r));
                 return r;
         }
 
@@ -352,15 +342,15 @@ int machine_check_gc(Machine *m, bool drop_not_started) {
         assert(m);
 
         if (drop_not_started && !m->started)
-                return 0;
+                return false;
 
-        if (m->scope_job)
-                return 1;
+        if (m->scope_job && manager_job_is_active(m->manager, m->scope_job))
+                return true;
 
-        if (m->scope)
-                return manager_unit_is_active(m->manager, m->scope) != 0;
+        if (m->scope && manager_unit_is_active(m->manager, m->scope))
+                return true;
 
-        return 0;
+        return false;
 }
 
 void machine_add_to_gc_queue(Machine *m) {
index c5d52a9..bfb28d1 100644 (file)
@@ -73,7 +73,7 @@ struct Machine {
         bool in_gc_queue:1;
         bool started:1;
 
-        DBusMessage *create_message;
+        sd_bus_message *create_message;
 
         LIST_FIELDS(Machine, gc_queue);
 };
@@ -82,22 +82,21 @@ Machine* machine_new(Manager *manager, const char *name);
 void machine_free(Machine *m);
 int machine_check_gc(Machine *m, bool drop_not_started);
 void machine_add_to_gc_queue(Machine *m);
-int machine_start(Machine *m, DBusMessageIter *iter);
+int machine_start(Machine *m, sd_bus_message *properties, sd_bus_error *error);
 int machine_stop(Machine *m);
 int machine_save(Machine *m);
 int machine_load(Machine *m);
 int machine_kill(Machine *m, KillWho who, int signo);
 
-char *machine_bus_path(Machine *s);
-
 MachineState machine_get_state(Machine *u);
 
-extern const DBusObjectPathVTable bus_machine_vtable;
+extern const sd_bus_vtable machine_vtable[];
 
-int machine_send_signal(Machine *m, bool new_machine);
-int machine_send_changed(Machine *m, const char *properties);
+char *machine_bus_path(Machine *s);
+int machine_object_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata);
 
-int machine_send_create_reply(Machine *m, DBusError *error);
+int machine_send_signal(Machine *m, bool new_machine);
+int machine_send_create_reply(Machine *m, sd_bus_error *error);
 
 const char* machine_class_to_string(MachineClass t) _const_;
 MachineClass machine_class_from_string(const char *s) _pure_;
index 2b622d1..6035597 100644 (file)
 #include <unistd.h>
 #include <pwd.h>
 
-#include <systemd/sd-id128.h>
-#include <systemd/sd-messages.h>
+#include "sd-id128.h"
+#include "sd-messages.h"
 
-#include "machined.h"
-#include "dbus-common.h"
 #include "strv.h"
 #include "mkdir.h"
 #include "path-util.h"
 #include "special.h"
-#include "sleep-config.h"
 #include "fileio-label.h"
 #include "label.h"
 #include "utf8.h"
 #include "unit-name.h"
-#include "bus-errors.h"
-#include "virt.h"
-#include "cgroup-util.h"
-
-#define BUS_MANAGER_INTERFACE                                           \
-        " <interface name=\"org.freedesktop.machine1.Manager\">\n"      \
-        "  <method name=\"GetMachine\">\n"                              \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"machine\" type=\"o\" direction=\"out\"/>\n"     \
-        "  </method>\n"                                                 \
-        "  <method name=\"GetMachineByPID\">\n"                         \
-        "   <arg name=\"pid\" type=\"u\" direction=\"in\"/>\n"          \
-        "   <arg name=\"machine\" type=\"o\" direction=\"out\"/>\n"     \
-        "  </method>\n"                                                 \
-        "  <method name=\"ListMachines\">\n"                            \
-        "   <arg name=\"machines\" type=\"a(ssso)\" direction=\"out\"/>\n" \
-        "  </method>\n"                                                 \
-        "  <method name=\"CreateMachine\">\n"                           \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"id\" type=\"ay\" direction=\"in\"/>\n"          \
-        "   <arg name=\"service\" type=\"s\" direction=\"in\"/>\n"      \
-        "   <arg name=\"class\" type=\"s\" direction=\"in\"/>\n"        \
-        "   <arg name=\"leader\" type=\"u\" direction=\"in\"/>\n"       \
-        "   <arg name=\"root_directory\" type=\"s\" direction=\"in\"/>\n" \
-        "   <arg name=\"scope_properties\" type=\"a(sv)\" direction=\"in\"/>\n" \
-        "   <arg name=\"path\" type=\"o\" direction=\"out\"/>\n"        \
-        "  </method>\n"                                                 \
-        "  <method name=\"KillMachine\">\n"                             \
-        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
-        "   <arg name=\"who\" type=\"s\" direction=\"in\"/>\n"          \
-        "   <arg name=\"signal\" type=\"s\" direction=\"in\"/>\n"       \
-        "  </method>\n"                                                 \
-        "  <method name=\"TerminateMachine\">\n"                        \
-        "   <arg name=\"id\" type=\"s\" direction=\"in\"/>\n"           \
-        "  </method>\n"                                                 \
-        "  <signal name=\"MachineNew\">\n"                              \
-        "   <arg name=\"machine\" type=\"s\"/>\n"                       \
-        "   <arg name=\"path\" type=\"o\"/>\n"                          \
-        "  </signal>\n"                                                 \
-        "  <signal name=\"MachineRemoved\">\n"                          \
-        "   <arg name=\"machine\" type=\"s\"/>\n"                       \
-        "   <arg name=\"path\" type=\"o\"/>\n"                          \
-        "  </signal>\n"                                                 \
-        " </interface>\n"
-
-#define INTROSPECTION_BEGIN                                             \
-        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
-        "<node>\n"                                                      \
-        BUS_MANAGER_INTERFACE                                           \
-        BUS_PROPERTIES_INTERFACE                                        \
-        BUS_PEER_INTERFACE                                              \
-        BUS_INTROSPECTABLE_INTERFACE
-
-#define INTROSPECTION_END                                               \
-        "</node>\n"
-
-#define INTERFACES_LIST                              \
-        BUS_GENERIC_INTERFACES_LIST                  \
-        "org.freedesktop.machine1.Manager\0"
+#include "bus-util.h"
+#include "time-util.h"
+#include "machined.h"
 
 static bool valid_machine_name(const char *p) {
         size_t l;
@@ -115,95 +56,170 @@ static bool valid_machine_name(const char *p) {
         return true;
 }
 
-static int bus_manager_create_machine(Manager *manager, DBusMessage *message) {
+static int method_get_machine(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_free_ char *p = NULL;
+        Manager *m = userdata;
+        Machine *machine;
+        const char *name;
+        int r;
+
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        machine = hashmap_get(m->machines, name);
+        if (!machine)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
+
+        p = machine_bus_path(machine);
+        if (!p)
+                return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
+
+        return sd_bus_reply_method_return(bus, message, "o", p);
+}
+
+static int method_get_machine_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_free_ char *p = NULL;
+        Manager *m = userdata;
+        Machine *machine = NULL;
+        uint32_t pid;
+        int r;
+
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        r = sd_bus_message_read(message, "u", &pid);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        r = manager_get_machine_by_pid(m, pid, &machine);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+        if (!machine)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_MACHINE_FOR_PID, "PID %lu does not belong to any known machine", (unsigned long) pid);
+
+        p = machine_bus_path(machine);
+        if (!p)
+                return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
+
+        return sd_bus_reply_method_return(bus, message, "o", p);
+}
+
+static int method_list_machines(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        Manager *m = userdata;
+        Machine *machine;
+        Iterator i;
+        int r;
+
+        assert(bus);
+        assert(message);
+        assert(m);
+
+        r = sd_bus_message_new_method_return(bus, message, &reply);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        r = sd_bus_message_open_container(reply, 'a', "(ssso)");
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        HASHMAP_FOREACH(machine, m->machines, i) {
+                _cleanup_free_ char *p = NULL;
+
+                p = machine_bus_path(machine);
+                if (!p)
+                        return sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
+
+                r = sd_bus_message_append(reply, "(ssso)",
+                                          machine->name,
+                                          strempty(machine_class_to_string(machine->class)),
+                                          machine->service,
+                                          p);
+                if (r < 0)
+                        return sd_bus_reply_method_errno(bus, message, r, NULL);
+        }
 
+        r = sd_bus_message_close_container(reply);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+
+        return sd_bus_send(bus, reply, NULL);
+}
+
+static int method_create_machine(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         const char *name, *service, *class, *root_directory;
-        DBusMessageIter iter, sub;
+        Manager *manager = userdata;
         MachineClass c;
         uint32_t leader;
         sd_id128_t id;
+        const void *v;
         Machine *m;
-        int n, r;
-        void *v;
+        size_t n;
+        int r;
 
-        assert(manager);
+        assert(bus);
         assert(message);
+        assert(manager);
 
-        if (!dbus_message_iter_init(message, &iter) ||
-            dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
-                return -EINVAL;
-
-        dbus_message_iter_get_basic(&iter, &name);
-
-        if (!valid_machine_name(name) ||
-            !dbus_message_iter_next(&iter) ||
-            dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
-            dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE)
-                return -EINVAL;
-
-        dbus_message_iter_recurse(&iter, &sub);
-        dbus_message_iter_get_fixed_array(&sub, &v, &n);
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
+        if (!valid_machine_name(name))
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine name");
 
+        r = sd_bus_message_read_array(message, 'y', &v, &n);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
         if (n == 0)
                 id = SD_ID128_NULL;
         else if (n == 16)
                 memcpy(&id, v, n);
         else
-                return -EINVAL;
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine ID parameter");
 
-        if (!dbus_message_iter_next(&iter) ||
-            dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
-                return -EINVAL;
-
-        dbus_message_iter_get_basic(&iter, &service);
-
-        if (!dbus_message_iter_next(&iter) ||
-            dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
-                return -EINVAL;
-
-        dbus_message_iter_get_basic(&iter, &class);
+        r = sd_bus_message_read(message, "ssus", &service, &class, &leader, &root_directory);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
         if (isempty(class))
                 c = _MACHINE_CLASS_INVALID;
         else {
                 c = machine_class_from_string(class);
                 if (c < 0)
-                        return -EINVAL;
+                        return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine class parameter");
         }
 
-        if (!dbus_message_iter_next(&iter) ||
-            dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
-                return -EINVAL;
-
-        dbus_message_iter_get_basic(&iter, &leader);
-        if (!dbus_message_iter_next(&iter) ||
-            dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
-                return -EINVAL;
+        if (leader == 1)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
 
-        dbus_message_iter_get_basic(&iter, &root_directory);
+        if (!isempty(root_directory) && !path_is_absolute(root_directory))
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Root directory must be empty or an absolute path");
 
-        if (!(isempty(root_directory) || path_is_absolute(root_directory)))
-                return -EINVAL;
+        r = sd_bus_message_enter_container(message, 'a', "(sv)");
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-        if (!dbus_message_iter_next(&iter) ||
-            dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
-            dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT)
-                return -EINVAL;
+        if (leader == 0) {
+                assert_cc(sizeof(uint32_t) == sizeof(pid_t));
 
-        dbus_message_iter_recurse(&iter, &sub);
+                r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), (pid_t*) &leader);
+                if (r < 0)
+                        return sd_bus_reply_method_errno(bus, message, r, NULL);
+        }
 
         if (hashmap_get(manager->machines, name))
-                return -EEXIST;
-
-        if (leader <= 0) {
-                leader = bus_get_unix_process_id(manager->bus, dbus_message_get_sender(message), NULL);
-                if (leader == 0)
-                        return -EINVAL;
-        }
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_MACHINE_EXISTS, "Machine '%s' already exists", name);
 
         r = manager_add_machine(manager, name, &m);
         if (r < 0)
-                return r;
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
         m->leader = leader;
         m->class = c;
@@ -212,7 +228,7 @@ static int bus_manager_create_machine(Manager *manager, DBusMessage *message) {
         if (!isempty(service)) {
                 m->service = strdup(service);
                 if (!m->service) {
-                        r = -ENOMEM;
+                        r = sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
                         goto fail;
                 }
         }
@@ -220,18 +236,20 @@ static int bus_manager_create_machine(Manager *manager, DBusMessage *message) {
         if (!isempty(root_directory)) {
                 m->root_directory = strdup(root_directory);
                 if (!m->root_directory) {
-                        r = -ENOMEM;
+                        r = sd_bus_reply_method_errno(bus, message, -ENOMEM, NULL);
                         goto fail;
                 }
         }
 
-        r = machine_start(m, &sub);
-        if (r < 0)
+        r = machine_start(m, message, &error);
+        if (r < 0) {
+                r = sd_bus_reply_method_errno(bus, message, r, &error);
                 goto fail;
+        }
 
-        m->create_message = dbus_message_ref(message);
+        m->create_message = sd_bus_message_ref(message);
 
-        return 0;
+        return 1;
 
 fail:
         machine_add_to_gc_queue(m);
@@ -239,486 +257,224 @@ fail:
         return r;
 }
 
-static DBusHandlerResult manager_message_handler(
-                DBusConnection *connection,
-                DBusMessage *message,
-                void *userdata) {
-
+static int method_terminate_machine(sd_bus *bus, sd_bus_message *message, void *userdata) {
         Manager *m = userdata;
-
-        DBusError error;
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+        Machine *machine;
+        const char *name;
         int r;
 
-        assert(connection);
+        assert(bus);
         assert(message);
         assert(m);
 
-        dbus_error_init(&error);
-
-        if (dbus_message_is_method_call(message, "org.freedesktop.machine1.Manager", "GetMachine")) {
-                Machine *machine;
-                const char *name;
-                char *p;
-                bool b;
-
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &name,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                machine = hashmap_get(m->machines, name);
-                if (!machine)
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                p = machine_bus_path(machine);
-                if (!p)
-                        goto oom;
-
-                b = dbus_message_append_args(
-                                reply,
-                                DBUS_TYPE_OBJECT_PATH, &p,
-                                DBUS_TYPE_INVALID);
-                free(p);
-
-                if (!b)
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.machine1.Manager", "GetMachineByPID")) {
-                uint32_t pid;
-                char *p;
-                Machine *machine;
-                bool b;
-
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_UINT32, &pid,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                r = manager_get_machine_by_pid(m, pid, &machine);
-                if (r <= 0)
-                        return bus_send_error_reply(connection, message, NULL, r < 0 ? r : -ENOENT);
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                p = machine_bus_path(machine);
-                if (!p)
-                        goto oom;
-
-                b = dbus_message_append_args(
-                                reply,
-                                DBUS_TYPE_OBJECT_PATH, &p,
-                                DBUS_TYPE_INVALID);
-                free(p);
-
-                if (!b)
-                        goto oom;
-
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.machine1.Manager", "ListMachines")) {
-                Machine *machine;
-                Iterator i;
-                DBusMessageIter iter, sub;
-
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                dbus_message_iter_init_append(reply, &iter);
-
-                if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssso)", &sub))
-                        goto oom;
-
-                HASHMAP_FOREACH(machine, m->machines, i) {
-                        _cleanup_free_ char *p = NULL;
-                        DBusMessageIter sub2;
-                        const char *class;
-
-                        if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
-                                goto oom;
-
-                        p = machine_bus_path(machine);
-                        if (!p)
-                                goto oom;
-
-                        class = strempty(machine_class_to_string(machine->class));
-
-                        if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &machine->name) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &class) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &machine->service) ||
-                            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) {
-                                free(p);
-                                goto oom;
-                        }
-
-                        if (!dbus_message_iter_close_container(&sub, &sub2))
-                                goto oom;
-                }
+        r = sd_bus_message_read(message, "s", &name);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                if (!dbus_message_iter_close_container(&iter, &sub))
-                        goto oom;
+        machine = hashmap_get(m->machines, name);
+        if (!machine)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.machine1.Manager", "CreateMachine")) {
+        r = machine_stop(machine);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                r = bus_manager_create_machine(m, message);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, NULL, r);
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.machine1.Manager", "KillMachine")) {
-                const char *swho;
-                int32_t signo;
-                KillWho who;
-                const char *name;
-                Machine *machine;
+static int method_kill_machine(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        Machine *machine;
+        const char *name;
+        const char *swho;
+        int32_t signo;
+        KillWho who;
+        int r;
 
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &name,
-                                    DBUS_TYPE_STRING, &swho,
-                                    DBUS_TYPE_INT32, &signo,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
-
-                if (isempty(swho))
-                        who = KILL_ALL;
-                else {
-                        who = kill_who_from_string(swho);
-                        if (who < 0)
-                                return bus_send_error_reply(connection, message, &error, -EINVAL);
-                }
+        assert(bus);
+        assert(message);
+        assert(m);
 
-                if (signo <= 0 || signo >= _NSIG)
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
+        r = sd_bus_message_read(message, "ssi", &name, &swho, &signo);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                machine = hashmap_get(m->machines, name);
-                if (!machine)
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
+        if (isempty(swho))
+                who = KILL_ALL;
+        else {
+                who = kill_who_from_string(swho);
+                if (who < 0)
+                        return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
+        }
 
-                r = machine_kill(machine, who, signo);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, NULL, r);
+        if (signo <= 0 || signo >= _NSIG)
+                return sd_bus_reply_method_errorf(bus, message, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        machine = hashmap_get(m->machines, name);
+        if (!machine)
+                return sd_bus_reply_method_errorf(bus, message, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.machine1.Manager", "TerminateMachine")) {
-                const char *name;
-                Machine *machine;
+        r = machine_kill(machine, who, signo);
+        if (r < 0)
+                return sd_bus_reply_method_errno(bus, message, r, NULL);
 
-                if (!dbus_message_get_args(
-                                    message,
-                                    &error,
-                                    DBUS_TYPE_STRING, &name,
-                                    DBUS_TYPE_INVALID))
-                        return bus_send_error_reply(connection, message, &error, -EINVAL);
+        return sd_bus_reply_method_return(bus, message, NULL);
+}
 
-                machine = hashmap_get(m->machines, name);
-                if (!machine)
-                        return bus_send_error_reply(connection, message, &error, -ENOENT);
+const sd_bus_vtable manager_vtable[] = {
+        SD_BUS_VTABLE_START(0),
+        SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, 0),
+        SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid, 0),
+        SD_BUS_METHOD("ListMachines", NULL, "a(ssso)", method_list_machines, 0),
+        SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine, 0),
+        SD_BUS_METHOD("KillMachine", "ssi", NULL, method_kill_machine, 0),
+        SD_BUS_METHOD("TerminateMachine", "s", NULL, method_terminate_machine, 0),
+        SD_BUS_SIGNAL("MachineNew", "so", 0),
+        SD_BUS_SIGNAL("MachineRemoved", "so", 0),
+        SD_BUS_VTABLE_END
+};
 
-                r = machine_stop(machine);
-                if (r < 0)
-                        return bus_send_error_reply(connection, message, NULL, r);
+int machine_node_enumerator(sd_bus *bus, const char *path, char ***nodes, void *userdata) {
+        Machine *machine = NULL;
+        Manager *m = userdata;
+        char **l = NULL;
+        Iterator i;
+        int r;
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
+        assert(bus);
+        assert(path);
+        assert(nodes);
 
-        } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
-                char *introspection = NULL;
-                FILE *f;
-                Iterator i;
-                Machine *machine;
-                size_t size;
+        HASHMAP_FOREACH(machine, m->machines, i) {
                 char *p;
 
-                reply = dbus_message_new_method_return(message);
-                if (!reply)
-                        goto oom;
-
-                /* We roll our own introspection code here, instead of
-                 * relying on bus_default_message_handler() because we
-                 * need to generate our introspection string
-                 * dynamically. */
-
-                f = open_memstream(&introspection, &size);
-                if (!f)
-                        goto oom;
-
-                fputs(INTROSPECTION_BEGIN, f);
-
-                HASHMAP_FOREACH(machine, m->machines, i) {
-                        p = bus_path_escape(machine->name);
-
-                        if (p) {
-                                fprintf(f, "<node name=\"machine/%s\"/>", p);
-                                free(p);
-                        }
-                }
-
-                fputs(INTROSPECTION_END, f);
-
-                if (ferror(f)) {
-                        fclose(f);
-                        free(introspection);
-                        goto oom;
-                }
-
-                fclose(f);
-
-                if (!introspection)
-                        goto oom;
+                p = machine_bus_path(machine);
+                if (!p)
+                        return -ENOMEM;
 
-                if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
-                        free(introspection);
-                        goto oom;
+                r = strv_push(&l, p);
+                if (r < 0) {
+                        free(p);
+                        return r;
                 }
-
-                free(introspection);
-        } else
-                return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, NULL);
-
-        if (reply) {
-                if (!bus_maybe_send_reply(connection, message, reply))
-                        goto oom;
         }
 
-        return DBUS_HANDLER_RESULT_HANDLED;
-
-oom:
-        dbus_error_free(&error);
-
-        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+        *nodes = l;
+        return 1;
 }
 
-const DBusObjectPathVTable bus_manager_vtable = {
-        .message_function = manager_message_handler
-};
-
-DBusHandlerResult bus_message_filter(
-                DBusConnection *connection,
-                DBusMessage *message,
-                void *userdata) {
-
+int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        const char *path, *result, *unit;
         Manager *m = userdata;
-        DBusError error;
+        Machine *machine;
+        uint32_t id;
+        int r;
 
-        assert(m);
-        assert(connection);
+        assert(bus);
         assert(message);
+        assert(m);
 
-        dbus_error_init(&error);
-
-        log_debug("Got message: %s %s %s", strna(dbus_message_get_sender(message)), strna(dbus_message_get_interface(message)), strna(dbus_message_get_member(message)));
-
-        if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) {
-                const char *path, *result, *unit;
-                Machine *mm;
-                uint32_t id;
-
-                if (!dbus_message_get_args(message, &error,
-                                           DBUS_TYPE_UINT32, &id,
-                                           DBUS_TYPE_OBJECT_PATH, &path,
-                                           DBUS_TYPE_STRING, &unit,
-                                           DBUS_TYPE_STRING, &result,
-                                           DBUS_TYPE_INVALID)) {
-                        log_error("Failed to parse JobRemoved message: %s", bus_error_message(&error));
-                        goto finish;
-                }
-
-                mm = hashmap_get(m->machine_units, unit);
-                if (mm) {
-                        if (streq_ptr(path, mm->scope_job)) {
-                                free(mm->scope_job);
-                                mm->scope_job = NULL;
-
-                                if (mm->started) {
-                                        if (streq(result, "done"))
-                                                machine_send_create_reply(mm, NULL);
-                                        else {
-                                                dbus_set_error(&error, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
-                                                machine_send_create_reply(mm, &error);
-                                        }
-                                } else
-                                        machine_save(mm);
-                        }
-
-                        machine_add_to_gc_queue(mm);
-                }
-
-        } else if (dbus_message_is_signal(message, "org.freedesktop.DBus.Properties", "PropertiesChanged")) {
-
-                _cleanup_free_ char *unit = NULL;
-                const char *path;
-
-                path = dbus_message_get_path(message);
-                if (!path)
-                        goto finish;
-
-                unit_name_from_dbus_path(path, &unit);
-                if (unit) {
-                        Machine *mm;
-
-                        mm = hashmap_get(m->machine_units, unit);
-                        if (mm)
-                                machine_add_to_gc_queue(mm);
-                }
-
-        } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "UnitRemoved")) {
-                const char *path, *unit;
-                Machine *mm;
-
-                if (!dbus_message_get_args(message, &error,
-                                           DBUS_TYPE_STRING, &unit,
-                                           DBUS_TYPE_OBJECT_PATH, &path,
-                                           DBUS_TYPE_INVALID)) {
-                        log_error("Failed to parse UnitRemoved message: %s", bus_error_message(&error));
-                        goto finish;
-                }
-
-                mm = hashmap_get(m->machine_units, unit);
-                if (mm)
-                        machine_add_to_gc_queue(mm);
+        r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
+        if (r < 0) {
+                log_error("Failed to parse JobRemoved message: %s", strerror(-r));
+                return 0;
+        }
 
-        } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "Reloading")) {
-                dbus_bool_t b;
+        machine = hashmap_get(m->machine_units, unit);
+        if (!machine)
+                return 0;
 
-                if (!dbus_message_get_args(message, &error,
-                                           DBUS_TYPE_BOOLEAN, &b,
-                                           DBUS_TYPE_INVALID)) {
-                        log_error("Failed to parse Reloading message: %s", bus_error_message(&error));
-                        goto finish;
-                }
+        if (streq_ptr(path, machine->scope_job)) {
+                free(machine->scope_job);
+                machine->scope_job = NULL;
 
-                /* systemd finished reloading, let's recheck all our machines */
-                if (!b) {
-                        Machine *mm;
-                        Iterator i;
+                if (machine->started) {
+                        if (streq(result, "done"))
+                                machine_send_create_reply(machine, NULL);
+                        else {
+                                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
 
-                        log_debug("System manager has been reloaded, rechecking machines...");
+                                sd_bus_error_setf(&error, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
 
-                        HASHMAP_FOREACH(mm, m->machines, i)
-                                machine_add_to_gc_queue(mm);
-                }
+                                machine_send_create_reply(machine, &error);
+                        }
+                } else
+                        machine_save(machine);
         }
 
-finish:
-        dbus_error_free(&error);
-
-        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+        machine_add_to_gc_queue(machine);
+        return 0;
 }
 
-static int copy_many_fields(DBusMessageIter *dest, DBusMessageIter *src);
-
-static int copy_one_field(DBusMessageIter *dest, DBusMessageIter *src) {
-        int type, r;
-
-        type = dbus_message_iter_get_arg_type(src);
-
-        switch (type) {
-
-        case DBUS_TYPE_STRUCT: {
-                DBusMessageIter dest_sub, src_sub;
-
-                dbus_message_iter_recurse(src, &src_sub);
-
-                if (!dbus_message_iter_open_container(dest, DBUS_TYPE_STRUCT, NULL, &dest_sub))
-                        return log_oom();
-
-                r = copy_many_fields(&dest_sub, &src_sub);
-                if (r < 0)
-                        return r;
+int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        _cleanup_free_ char *unit = NULL;
+        Manager *m = userdata;
+        Machine *machine;
+        const char *path;
 
-                if (!dbus_message_iter_close_container(dest, &dest_sub))
-                        return log_oom();
+        assert(bus);
+        assert(message);
+        assert(m);
 
+        path = sd_bus_message_get_path(message);
+        if (!path)
                 return 0;
-        }
 
-        case DBUS_TYPE_ARRAY: {
-                DBusMessageIter dest_sub, src_sub;
+        unit_name_from_dbus_path(path, &unit);
+        if (!unit)
+                return 0;
 
-                dbus_message_iter_recurse(src, &src_sub);
+        machine = hashmap_get(m->machine_units, unit);
+        if (machine)
+                machine_add_to_gc_queue(machine);
 
-                if (!dbus_message_iter_open_container(dest, DBUS_TYPE_ARRAY, dbus_message_iter_get_signature(&src_sub), &dest_sub))
-                        return log_oom();
+        return 0;
+}
 
-                r = copy_many_fields(&dest_sub, &src_sub);
-                if (r < 0)
-                        return r;
+int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        const char *path, *unit;
+        Manager *m = userdata;
+        Machine *machine;
+        int r;
 
-                if (!dbus_message_iter_close_container(dest, &dest_sub))
-                        return log_oom();
+        assert(bus);
+        assert(message);
+        assert(m);
 
+        r = sd_bus_message_read(message, "so", &unit, &path);
+        if (r < 0) {
+                log_error("Failed to parse UnitRemoved message: %s", strerror(-r));
                 return 0;
         }
 
-        case DBUS_TYPE_VARIANT: {
-                DBusMessageIter dest_sub, src_sub;
-
-                dbus_message_iter_recurse(src, &src_sub);
+        machine = hashmap_get(m->machine_units, unit);
+        if (machine)
+                machine_add_to_gc_queue(machine);
 
-                if (!dbus_message_iter_open_container(dest, DBUS_TYPE_VARIANT, dbus_message_iter_get_signature(&src_sub), &dest_sub))
-                        return log_oom();
-
-                r = copy_one_field(&dest_sub, &src_sub);
-                if (r < 0)
-                        return r;
+        return 0;
+}
 
-                if (!dbus_message_iter_close_container(dest, &dest_sub))
-                        return log_oom();
+int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata) {
+        Manager *m = userdata;
+        int b, r;
 
-                return 0;
-        }
+        assert(bus);
 
-        case DBUS_TYPE_STRING:
-        case DBUS_TYPE_OBJECT_PATH:
-        case DBUS_TYPE_BYTE:
-        case DBUS_TYPE_BOOLEAN:
-        case DBUS_TYPE_UINT16:
-        case DBUS_TYPE_INT16:
-        case DBUS_TYPE_UINT32:
-        case DBUS_TYPE_INT32:
-        case DBUS_TYPE_UINT64:
-        case DBUS_TYPE_INT64:
-        case DBUS_TYPE_DOUBLE:
-        case DBUS_TYPE_SIGNATURE: {
-                const void *p;
-
-                dbus_message_iter_get_basic(src, &p);
-                dbus_message_iter_append_basic(dest, type, &p);
+        r = sd_bus_message_read(message, "b", &b);
+        if (r < 0) {
+                log_error("Failed to parse Reloading message: %s", strerror(-r));
                 return 0;
         }
 
-        default:
-                return -EINVAL;
-        }
-}
-
-static int copy_many_fields(DBusMessageIter *dest, DBusMessageIter *src) {
-        int r;
-
-        assert(dest);
-        assert(src);
-
-        while (dbus_message_iter_get_arg_type(src) != DBUS_TYPE_INVALID) {
+        /* systemd finished reloading, let's recheck all our machines */
+        if (!b) {
+                Machine *machine;
+                Iterator i;
 
-                r = copy_one_field(dest, src);
-                if (r < 0)
-                        return r;
+                log_debug("System manager has been reloaded, rechecking machines...");
 
-                dbus_message_iter_next(src);
+                HASHMAP_FOREACH(machine, m->machines, i)
+                        machine_add_to_gc_queue(machine);
         }
 
         return 0;
@@ -730,108 +486,80 @@ int manager_start_scope(
                 pid_t pid,
                 const char *slice,
                 const char *description,
-                DBusMessageIter *more_properties,
-                DBusError *error,
+                sd_bus_message *more_properties,
+                sd_bus_error *error,
                 char **job) {
 
-        _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
-        DBusMessageIter iter, sub, sub2, sub3, sub4;
-        const char *timeout_stop_property = "TimeoutStopUSec";
-        const char *pids_property = "PIDs";
-        uint64_t timeout = 500 * USEC_PER_MSEC;
-        const char *fail = "fail";
-        uint32_t u;
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
         int r;
 
         assert(manager);
         assert(scope);
         assert(pid > 1);
 
-        if (!slice)
-                slice = "";
-
-        m = dbus_message_new_method_call(
+        r = sd_bus_message_new_method_call(
+                        manager->bus,
                         "org.freedesktop.systemd1",
                         "/org/freedesktop/systemd1",
                         "org.freedesktop.systemd1.Manager",
-                        "StartTransientUnit");
-        if (!m)
-                return log_oom();
+                        "StartTransientUnit",
+                        &m);
+        if (r < 0)
+                return r;
 
-        dbus_message_iter_init_append(m, &iter);
+        r = sd_bus_message_append(m, "ss", scope, "fail");
+        if (r < 0)
+                return r;
 
-        if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &scope) ||
-            !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &fail) ||
-            !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sv)", &sub))
-                return log_oom();
+        r = sd_bus_message_open_container(m, 'a', "(sv)");
+        if (r < 0)
+                return r;
 
         if (!isempty(slice)) {
-                const char *slice_property = "Slice";
-
-                if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &slice_property) ||
-                    !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, "s", &sub3) ||
-                    !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &slice) ||
-                    !dbus_message_iter_close_container(&sub2, &sub3) ||
-                    !dbus_message_iter_close_container(&sub, &sub2))
-                        return log_oom();
+                r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
+                if (r < 0)
+                        return r;
         }
 
         if (!isempty(description)) {
-                const char *description_property = "Description";
-
-                if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description_property) ||
-                    !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, "s", &sub3) ||
-                    !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, &description) ||
-                    !dbus_message_iter_close_container(&sub2, &sub3) ||
-                    !dbus_message_iter_close_container(&sub, &sub2))
-                        return log_oom();
+                r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
+                if (r < 0)
+                        return r;
         }
 
         /* cgroup empty notification is not available in containers
          * currently. To make this less problematic, let's shorten the
-         * stop timeout for sessions, so that we don't wait
+         * stop timeout for machines, so that we don't wait
          * forever. */
+        r = sd_bus_message_append(m, "(sv)", "TimeoutStopUSec", "t", 500 * USEC_PER_MSEC);
+        if (r < 0)
+                return r;
 
-        if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
-            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &timeout_stop_property) ||
-            !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, "t", &sub3) ||
-            !dbus_message_iter_append_basic(&sub3, DBUS_TYPE_UINT64, &timeout) ||
-            !dbus_message_iter_close_container(&sub2, &sub3) ||
-            !dbus_message_iter_close_container(&sub, &sub2))
-                return log_oom();
-
-        u = pid;
-        if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
-            !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &pids_property) ||
-            !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, "au", &sub3) ||
-            !dbus_message_iter_open_container(&sub3, DBUS_TYPE_ARRAY, "u", &sub4) ||
-            !dbus_message_iter_append_basic(&sub4, DBUS_TYPE_UINT32, &u) ||
-            !dbus_message_iter_close_container(&sub3, &sub4) ||
-            !dbus_message_iter_close_container(&sub2, &sub3) ||
-            !dbus_message_iter_close_container(&sub, &sub2))
-                return log_oom();
+        r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
+        if (r < 0)
+                return r;
 
         if (more_properties) {
-                r = copy_many_fields(&sub, more_properties);
+                r = sd_bus_message_copy(m, more_properties, true);
                 if (r < 0)
                         return r;
         }
 
-        if (!dbus_message_iter_close_container(&iter, &sub))
-                return log_oom();
+        r = sd_bus_message_close_container(m);
+        if (r < 0)
+                return r;
 
-        reply = dbus_connection_send_with_reply_and_block(manager->bus, m, -1, error);
-        if (!reply)
-                return -EIO;
+        r = sd_bus_send_with_reply_and_block(manager->bus, m, 0, error, &reply);
+        if (r < 0)
+                return r;
 
         if (job) {
                 const char *j;
                 char *copy;
 
-                if (!dbus_message_get_args(reply, error, DBUS_TYPE_OBJECT_PATH, &j, DBUS_TYPE_INVALID))
-                        return -EIO;
+                r = sd_bus_message_read(reply, "o", &j);
+                if (r < 0)
+                        return r;
 
                 copy = strdup(j);
                 if (!copy)
@@ -840,40 +568,36 @@ int manager_start_scope(
                 *job = copy;
         }
 
-        return 0;
+        return 1;
 }
 
-int manager_stop_unit(Manager *manager, const char *unit, DBusError *error, char **job) {
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
-        const char *fail = "fail";
+int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
+        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         int r;
 
         assert(manager);
         assert(unit);
 
-        r = bus_method_call_with_reply(
+        r = sd_bus_call_method(
                         manager->bus,
                         "org.freedesktop.systemd1",
                         "/org/freedesktop/systemd1",
                         "org.freedesktop.systemd1.Manager",
                         "StopUnit",
-                        &reply,
                         error,
-                        DBUS_TYPE_STRING, &unit,
-                        DBUS_TYPE_STRING, &fail,
-                        DBUS_TYPE_INVALID);
+                        &reply,
+                        "ss", unit, "fail");
         if (r < 0) {
-                if (dbus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
-                    dbus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
+                if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
+                    sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
 
                         if (job)
                                 *job = NULL;
 
-                        dbus_error_free(error);
+                        sd_bus_error_free(error);
                         return 0;
                 }
 
-                log_error("Failed to stop unit %s: %s", unit, bus_error(error, r));
                 return r;
         }
 
@@ -881,12 +605,9 @@ int manager_stop_unit(Manager *manager, const char *unit, DBusError *error, char
                 const char *j;
                 char *copy;
 
-                if (!dbus_message_get_args(reply, error,
-                                           DBUS_TYPE_OBJECT_PATH, &j,
-                                           DBUS_TYPE_INVALID)) {
-                        log_error("Failed to parse reply.");
-                        return -EIO;
-                }
+                r = sd_bus_message_read(reply, "o", &j);
+                if (r < 0)
+                        return r;
 
                 copy = strdup(j);
                 if (!copy)
@@ -898,139 +619,98 @@ int manager_stop_unit(Manager *manager, const char *unit, DBusError *error, char
         return 1;
 }
 
-int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, DBusError *error) {
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
-        const char *w;
+int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
+        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         int r;
 
         assert(manager);
         assert(unit);
 
-        w = who == KILL_LEADER ? "process" : "cgroup";
-        assert_cc(sizeof(signo) == sizeof(int32_t));
-
-        r = bus_method_call_with_reply(
+        r = sd_bus_call_method(
                         manager->bus,
                         "org.freedesktop.systemd1",
                         "/org/freedesktop/systemd1",
                         "org.freedesktop.systemd1.Manager",
                         "KillUnit",
-                        &reply,
                         error,
-                        DBUS_TYPE_STRING, &unit,
-                        DBUS_TYPE_STRING, &w,
-                        DBUS_TYPE_INT32, &signo,
-                        DBUS_TYPE_INVALID);
-        if (r < 0) {
-                log_error("Failed to stop unit %s: %s", unit, bus_error(error, r));
-                return r;
-        }
+                        &reply,
+                        "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
 
-        return 0;
+        return r;
 }
 
 int manager_unit_is_active(Manager *manager, const char *unit) {
-
-        const char *interface = "org.freedesktop.systemd1.Unit";
-        const char *property = "ActiveState";
-        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         _cleanup_free_ char *path = NULL;
-        DBusMessageIter iter, sub;
         const char *state;
-        DBusError error;
         int r;
 
         assert(manager);
         assert(unit);
 
-        dbus_error_init(&error);
-
         path = unit_dbus_path_from_name(unit);
         if (!path)
                 return -ENOMEM;
 
-        r = bus_method_call_with_reply(
+        r = sd_bus_get_property(
                         manager->bus,
                         "org.freedesktop.systemd1",
                         path,
-                        "org.freedesktop.DBus.Properties",
-                        "Get",
-                        &reply,
+                        "org.freedesktop.systemd1.Unit",
+                        "ActiveState",
                         &error,
-                        DBUS_TYPE_STRING, &interface,
-                        DBUS_TYPE_STRING, &property,
-                        DBUS_TYPE_INVALID);
+                        &reply,
+                        "s");
         if (r < 0) {
-                if (dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY) ||
-                    dbus_error_has_name(&error, DBUS_ERROR_DISCONNECTED)) {
-                        dbus_error_free(&error);
+                if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
+                    sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
                         return true;
-                }
 
-                if (dbus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
-                    dbus_error_has_name(&error, BUS_ERROR_LOAD_FAILED)) {
-                        dbus_error_free(&error);
+                if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
+                    sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
                         return false;
-                }
 
-                log_error("Failed to query ActiveState: %s", bus_error(&error, r));
-                dbus_error_free(&error);
                 return r;
         }
 
-        if (!dbus_message_iter_init(reply, &iter) ||
-            dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
-                log_error("Failed to parse reply.");
+        r = sd_bus_message_read(reply, "s", &state);
+        if (r < 0)
                 return -EINVAL;
-        }
-
-        dbus_message_iter_recurse(&iter, &sub);
-        if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
-                log_error("Failed to parse reply.");
-                return -EINVAL;
-        }
-
-        dbus_message_iter_get_basic(&sub, &state);
 
         return !streq(state, "inactive") && !streq(state, "failed");
 }
 
-int manager_add_machine(Manager *m, const char *name, Machine **_machine) {
-        Machine *machine;
-
-        assert(m);
-        assert(name);
-
-        machine = hashmap_get(m->machines, name);
-        if (!machine) {
-                machine = machine_new(m, name);
-                if (!machine)
-                        return -ENOMEM;
-        }
-
-        if (_machine)
-                *_machine = machine;
+int manager_job_is_active(Manager *manager, const char *path) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        int r;
 
-        return 0;
-}
+        assert(manager);
+        assert(path);
 
-int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
-        _cleanup_free_ char *unit = NULL;
-        Machine *mm;
-        int r;
+        r = sd_bus_get_property(
+                        manager->bus,
+                        "org.freedesktop.systemd1",
+                        path,
+                        "org.freedesktop.systemd1.Job",
+                        "State",
+                        &error,
+                        &reply,
+                        "s");
+        if (r < 0) {
+                if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
+                    sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
+                        return true;
 
-        assert(m);
-        assert(pid >= 1);
-        assert(machine);
+                if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
+                        return false;
 
-        r = cg_pid_get_unit(pid, &unit);
-        if (r < 0)
                 return r;
+        }
 
-        mm = hashmap_get(m->machine_units, unit);
-        if (!mm)
-                return 0;
+        /* We don't actually care about the state really. The fact
+         * that we could read the job state is enough for us */
 
-        *machine = mm;
-        return 1;
+        return true;
 }
index ca84f8a..6391551 100644 (file)
 #include <unistd.h>
 #include <sys/epoll.h>
 
-#include <systemd/sd-daemon.h>
+#include "sd-daemon.h"
 
-#include "machined.h"
-#include "dbus-common.h"
-#include "dbus-loop.h"
 #include "strv.h"
 #include "conf-parser.h"
+#include "cgroup-util.h"
 #include "mkdir.h"
+#include "bus-util.h"
+#include "bus-error.h"
+#include "machined.h"
 
 Manager *manager_new(void) {
         Manager *m;
+        int r;
 
         m = new0(Manager, 1);
         if (!m)
                 return NULL;
 
-        m->bus_fd = -1;
-        m->epoll_fd = -1;
-
         m->machines = hashmap_new(string_hash_func, string_compare_func);
         m->machine_units = hashmap_new(string_hash_func, string_compare_func);
 
+        r = sd_event_new(&m->event);
+        if (r < 0) {
+                manager_free(m);
+                return NULL;
+        }
+
         if (!m->machines || !m->machine_units) {
                 manager_free(m);
                 return NULL;
@@ -67,19 +72,50 @@ void manager_free(Manager *m) {
         hashmap_free(m->machines);
         hashmap_free(m->machine_units);
 
-        if (m->bus) {
-                dbus_connection_flush(m->bus);
-                dbus_connection_close(m->bus);
-                dbus_connection_unref(m->bus);
+        sd_bus_unref(m->bus);
+        sd_event_unref(m->event);
+
+        free(m);
+}
+
+int manager_add_machine(Manager *m, const char *name, Machine **_machine) {
+        Machine *machine;
+
+        assert(m);
+        assert(name);
+
+        machine = hashmap_get(m->machines, name);
+        if (!machine) {
+                machine = machine_new(m, name);
+                if (!machine)
+                        return -ENOMEM;
         }
 
-        if (m->bus_fd >= 0)
-                close_nointr_nofail(m->bus_fd);
+        if (_machine)
+                *_machine = machine;
+
+        return 0;
+}
+
+int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
+        _cleanup_free_ char *unit = NULL;
+        Machine *mm;
+        int r;
 
-        if (m->epoll_fd >= 0)
-                close_nointr_nofail(m->epoll_fd);
+        assert(m);
+        assert(pid >= 1);
+        assert(machine);
 
-        free(m);
+        r = cg_pid_get_unit(pid, &unit);
+        if (r < 0)
+                return r;
+
+        mm = hashmap_get(m->machine_units, unit);
+        if (!mm)
+                return 0;
+
+        *machine = mm;
+        return 1;
 }
 
 int manager_enumerate_machines(Manager *m) {
@@ -125,122 +161,118 @@ int manager_enumerate_machines(Manager *m) {
 }
 
 static int manager_connect_bus(Manager *m) {
-        DBusError error;
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         int r;
-        struct epoll_event ev = {
-                .events = EPOLLIN,
-                .data.u32 = FD_BUS,
-        };
 
         assert(m);
         assert(!m->bus);
-        assert(m->bus_fd < 0);
 
-        dbus_error_init(&error);
+        r = sd_bus_open_system(&m->bus);
+        if (r < 0) {
+                log_error("Failed to connect to system bus: %s", strerror(-r));
+                return r;
+        }
 
-        m->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
-        if (!m->bus) {
-                log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
-                r = -ECONNREFUSED;
-                goto fail;
+        r = sd_bus_add_object_vtable(m->bus, "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", manager_vtable, m);
+        if (r < 0) {
+                log_error("Failed to add manager object vtable: %s", strerror(-r));
+                return r;
         }
 
-        if (!dbus_connection_register_object_path(m->bus, "/org/freedesktop/machine1", &bus_manager_vtable, m) ||
-            !dbus_connection_register_fallback(m->bus, "/org/freedesktop/machine1/machine", &bus_machine_vtable, m) ||
-            !dbus_connection_add_filter(m->bus, bus_message_filter, m, NULL)) {
-                r = log_oom();
-                goto fail;
+        r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/machine1/machine", "org.freedesktop.machine1.Machine", machine_vtable, machine_object_find, m);
+        if (r < 0) {
+                log_error("Failed to add machine object vtable: %s", strerror(-r));
+                return r;
+        }
+
+        r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/machine1/machine", machine_node_enumerator, m);
+        if (r < 0) {
+                log_error("Failed to add machine enumerator: %s", strerror(-r));
+                return r;
         }
 
-        dbus_bus_add_match(m->bus,
-                           "type='signal',"
-                           "sender='org.freedesktop.systemd1',"
-                           "interface='org.freedesktop.systemd1.Manager',"
-                           "member='JobRemoved',"
-                           "path='/org/freedesktop/systemd1'",
-                           &error);
-        if (dbus_error_is_set(&error)) {
-                log_error("Failed to add match for JobRemoved: %s", bus_error_message(&error));
-                dbus_error_free(&error);
+        r = sd_bus_add_match(m->bus,
+                             "type='signal',"
+                             "sender='org.freedesktop.systemd1',"
+                             "interface='org.freedesktop.systemd1.Manager',"
+                             "member='JobRemoved',"
+                             "path='/org/freedesktop/systemd1'",
+                             match_job_removed,
+                             m);
+        if (r < 0) {
+                log_error("Failed to add match for JobRemoved: %s", strerror(-r));
+                return r;
         }
 
-        dbus_bus_add_match(m->bus,
-                           "type='signal',"
-                           "sender='org.freedesktop.systemd1',"
-                           "interface='org.freedesktop.systemd1.Manager',"
-                           "member='UnitRemoved',"
-                           "path='/org/freedesktop/systemd1'",
-                           &error);
-        if (dbus_error_is_set(&error)) {
-                log_error("Failed to add match for UnitRemoved: %s", bus_error_message(&error));
-                dbus_error_free(&error);
+        r = sd_bus_add_match(m->bus,
+                             "type='signal',"
+                             "sender='org.freedesktop.systemd1',"
+                             "interface='org.freedesktop.systemd1.Manager',"
+                             "member='UnitRemoved',"
+                             "path='/org/freedesktop/systemd1'",
+                             match_unit_removed,
+                             m);
+        if (r < 0) {
+                log_error("Failed to add match for UnitRemoved: %s", strerror(-r));
+                return r;
         }
 
-        dbus_bus_add_match(m->bus,
-                           "type='signal',"
-                           "sender='org.freedesktop.systemd1',"
-                           "interface='org.freedesktop.DBus.Properties',"
-                           "member='PropertiesChanged'",
-                           &error);
-        if (dbus_error_is_set(&error)) {
-                log_error("Failed to add match for PropertiesChanged: %s", bus_error_message(&error));
-                dbus_error_free(&error);
+        r = sd_bus_add_match(m->bus,
+                             "type='signal',"
+                             "sender='org.freedesktop.systemd1',"
+                             "interface='org.freedesktop.DBus.Properties',"
+                             "member='PropertiesChanged'",
+                             match_properties_changed,
+                             m);
+        if (r < 0) {
+                log_error("Failed to add match for PropertiesChanged: %s", strerror(-r));
+                return r;
         }
 
-        dbus_bus_add_match(m->bus,
-                           "type='signal',"
-                           "sender='org.freedesktop.systemd1',"
-                           "interface='org.freedesktop.systemd1.Manager',"
-                           "member='Reloading',"
-                           "path='/org/freedesktop/systemd1'",
-                           &error);
-        if (dbus_error_is_set(&error)) {
-                log_error("Failed to add match for Reloading: %s", bus_error_message(&error));
-                dbus_error_free(&error);
+        r = sd_bus_add_match(m->bus,
+                             "type='signal',"
+                             "sender='org.freedesktop.systemd1',"
+                             "interface='org.freedesktop.systemd1.Manager',"
+                             "member='Reloading',"
+                             "path='/org/freedesktop/systemd1'",
+                             match_reloading,
+                             m);
+        if (r < 0) {
+                log_error("Failed to add match for Reloading: %s", strerror(-r));
+                return r;
         }
 
-        r = bus_method_call_with_reply(
+        r = sd_bus_call_method(
                         m->bus,
                         "org.freedesktop.systemd1",
                         "/org/freedesktop/systemd1",
                         "org.freedesktop.systemd1.Manager",
                         "Subscribe",
-                        NULL,
                         &error,
-                        DBUS_TYPE_INVALID);
+                        NULL, NULL);
         if (r < 0) {
-                log_error("Failed to enable subscription: %s", bus_error(&error, r));
-                dbus_error_free(&error);
+                log_error("Failed to enable subscription: %s", bus_error_message(&error, r));
+                return r;
         }
 
-        r = dbus_bus_request_name(m->bus, "org.freedesktop.machine1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
-        if (dbus_error_is_set(&error)) {
-                log_error("Failed to register name on bus: %s", bus_error_message(&error));
-                r = -EIO;
-                goto fail;
+        r = sd_bus_request_name(m->bus, "org.freedesktop.machine1", SD_BUS_NAME_DO_NOT_QUEUE);
+        if (r < 0) {
+                log_error("Failed to register name: %s", strerror(-r));
+                return r;
         }
 
-        if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)  {
+        if (r != SD_BUS_NAME_PRIMARY_OWNER)  {
                 log_error("Failed to acquire name.");
-                r = -EEXIST;
-                goto fail;
+                return -EEXIST;
         }
 
-        m->bus_fd = bus_loop_open(m->bus);
-        if (m->bus_fd < 0) {
-                r = m->bus_fd;
-                goto fail;
+        r = sd_bus_attach_event(m->bus, m->event, 0);
+        if (r < 0) {
+                log_error("Failed to attach bus to event loop: %s", strerror(-r));
+                return r;
         }
 
-        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0)
-                goto fail;
-
         return 0;
-
-fail:
-        dbus_error_free(&error);
-
-        return r;
 }
 
 void manager_gc(Manager *m, bool drop_not_started) {
@@ -260,16 +292,11 @@ void manager_gc(Manager *m, bool drop_not_started) {
 }
 
 int manager_startup(Manager *m) {
-        int r;
         Machine *machine;
         Iterator i;
+        int r;
 
         assert(m);
-        assert(m->epoll_fd <= 0);
-
-        m->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
-        if (m->epoll_fd < 0)
-                return -errno;
 
         /* Connect to the bus */
         r = manager_connect_bus(m);
@@ -284,46 +311,28 @@ int manager_startup(Manager *m) {
 
         /* And start everything */
         HASHMAP_FOREACH(machine, m->machines, i)
-                machine_start(machine, NULL);
+                machine_start(machine, NULL, NULL);
 
         return 0;
 }
 
 int manager_run(Manager *m) {
+        int r;
+
         assert(m);
 
         for (;;) {
-                struct epoll_event event;
-                int n;
-
-                manager_gc(m, true);
-
-                if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
-                        continue;
+                r = sd_event_get_state(m->event);
+                if (r < 0)
+                        return r;
+                if (r == SD_EVENT_FINISHED)
+                        return 0;
 
                 manager_gc(m, true);
 
-                n = epoll_wait(m->epoll_fd, &event, 1, -1);
-                if (n < 0) {
-                        if (errno == EINTR || errno == EAGAIN)
-                                continue;
-
-                        log_error("epoll() failed: %m");
-                        return -errno;
-                }
-
-                if (n == 0)
-                        continue;
-
-                switch (event.data.u32) {
-
-                case FD_BUS:
-                        bus_loop_dispatch(m->bus_fd);
-                        break;
-
-                default:
-                        assert_not_reached("Unknown fd");
-                }
+                r = sd_event_run(m->event, (uint64_t) -1);
+                if (r < 0)
+                        return r;
         }
 
         return 0;
@@ -348,9 +357,9 @@ int main(int argc, char *argv[]) {
 
         /* Always create the directories people can create inotify
          * watches in. Note that some applications might check for the
-         * existence of /run/systemd/seats/ to determine whether
-         * machined is available, so please always make sure this check
-         * stays in. */
+         * existence of /run/systemd/machines/ to determine whether
+         * machined is available, so please always make sure this
+         * check stays in. */
         mkdir_label("/run/systemd/machines", 0755);
 
         m = manager_new();
index 780f516..c47a468 100644 (file)
 
 #include <stdbool.h>
 #include <inttypes.h>
-#include <dbus/dbus.h>
 
 #include "util.h"
 #include "list.h"
 #include "hashmap.h"
+#include "sd-event.h"
+#include "sd-bus.h"
 
 typedef struct Manager Manager;
 
 #include "machine.h"
 
 struct Manager {
-        DBusConnection *bus;
-
-        int bus_fd;
-        int epoll_fd;
+        sd_event *event;
+        sd_bus *bus;
 
         Hashmap *machines;
         Hashmap *machine_units;
@@ -45,10 +44,6 @@ struct Manager {
         LIST_HEAD(Machine, machine_gc_queue);
 };
 
-enum {
-        FD_BUS
-};
-
 Manager *manager_new(void);
 void manager_free(Manager *m);
 
@@ -63,11 +58,17 @@ void manager_gc(Manager *m, bool drop_not_started);
 
 int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine);
 
-extern const DBusObjectPathVTable bus_manager_vtable;
+extern const sd_bus_vtable manager_vtable[];
+
+int machine_node_enumerator(sd_bus *bus, const char *path, char ***nodes, void *userdata);
 
-DBusHandlerResult bus_message_filter(DBusConnection *c, DBusMessage *message, void *userdata);
+int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata);
+int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata);
+int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata);
+int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata);
 
-int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, DBusMessageIter *more_properties, DBusError *error, char **job);
-int manager_stop_unit(Manager *manager, const char *unit, DBusError *error, char **job);
-int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, DBusError *error);
+int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, sd_bus_message *more_properties, sd_bus_error *error, char **job);
+int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
+int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error);
 int manager_unit_is_active(Manager *manager, const char *unit);
+int manager_job_is_active(Manager *manager, const char *path);
index 6ce21ac..daf9ad0 100644 (file)
@@ -82,7 +82,6 @@ bool strv_overlap(char **a, char **b) _pure_;
 #define STRV_FOREACH_PAIR(x, y, l)               \
         for ((x) = (l), (y) = (x+1); (x) && *(x) && *(y); (x) += 2, (y) = (x + 1))
 
-
 char **strv_sort(char **l);
 void strv_print(char **l);