From cf30a8c1ed2de720dee935d552011aa9ba596d31 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 14 Nov 2017 23:27:14 +0100 Subject: [PATCH] machined: port machined's bus APIs to use new image metadata API Let's rework the D-Bus APIs GetImageOSRelease() to use the new internal metadata API, to query what it needs to know. Augment it with GetImageHostname(), GetImageMachineID(), GetImageMachineInfo(), that expose the other new APIS. --- src/machine/image-dbus.c | 173 +++++++++--------------------- src/machine/image-dbus.h | 3 + src/machine/machined-dbus.c | 75 +++++++++++++ src/machine/org.freedesktop.machine1.conf | 24 +++++ 4 files changed, 153 insertions(+), 122 deletions(-) diff --git a/src/machine/image-dbus.c b/src/machine/image-dbus.c index c868d62..3d2fdd4 100644 --- a/src/machine/image-dbus.c +++ b/src/machine/image-dbus.c @@ -290,159 +290,85 @@ int bus_image_method_set_limit( return sd_bus_reply_method_return(message, NULL); } -#define EXIT_NOT_FOUND 2 - -static int directory_image_get_os_release(Image *image, char ***ret, sd_bus_error *error) { +int bus_image_method_get_hostname( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { - _cleanup_free_ char *path = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + Image *image = userdata; int r; - assert(image); - assert(ret); - - r = chase_symlinks("/etc/os-release", image->path, CHASE_PREFIX_ROOT, &path); - if (r == -ENOENT) - r = chase_symlinks("/usr/lib/os-release", image->path, CHASE_PREFIX_ROOT, &path); - if (r == -ENOENT) - return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Image does not contain OS release information"); - if (r < 0) - return sd_bus_error_set_errnof(error, r, "Failed to resolve %s: %m", image->path); - - r = load_env_file_pairs(NULL, path, NULL, ret); - if (r < 0) - return sd_bus_error_set_errnof(error, r, "Failed to open %s: %m", path); + if (!image->metadata_valid) { + r = image_read_metadata(image); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m"); + } - return 0; + return sd_bus_reply_method_return(message, "s", image->hostname); } -static int raw_image_get_os_release(Image *image, char ***ret, sd_bus_error *error) { - _cleanup_(rmdir_and_freep) char *t = NULL; - _cleanup_(loop_device_unrefp) LoopDevice *d = NULL; - _cleanup_(dissected_image_unrefp) DissectedImage *m = NULL; - _cleanup_(sigkill_waitp) pid_t child = 0; - _cleanup_close_pair_ int pair[2] = { -1, -1 }; - _cleanup_fclose_ FILE *f = NULL; - _cleanup_strv_free_ char **v = NULL; - siginfo_t si; - int r; - - assert(image); - assert(ret); - - r = mkdtemp_malloc("/tmp/machined-root-XXXXXX", &t); - if (r < 0) - return sd_bus_error_set_errnof(error, r, "Failed to create temporary directory: %m"); - - r = loop_device_make_by_path(image->path, O_RDONLY, &d); - if (r < 0) - return sd_bus_error_set_errnof(error, r, "Failed to set up loop block device for %s: %m", image->path); - - r = dissect_image(d->fd, NULL, 0, DISSECT_IMAGE_REQUIRE_ROOT, &m); - if (r == -ENOPKG) - return sd_bus_error_set_errnof(error, r, "Disk image %s not understood: %m", image->path); - if (r < 0) - return sd_bus_error_set_errnof(error, r, "Failed to dissect image %s: %m", image->path); - - if (pipe2(pair, O_CLOEXEC) < 0) - return sd_bus_error_set_errnof(error, errno, "Failed to create communication pipe: %m"); - - child = raw_clone(SIGCHLD|CLONE_NEWNS); - if (child < 0) - return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m"); - - if (child == 0) { - int fd; - - pair[0] = safe_close(pair[0]); - - /* Make sure we never propagate to the host */ - if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) - _exit(EXIT_FAILURE); - - r = dissected_image_mount(m, t, DISSECT_IMAGE_READ_ONLY); - if (r < 0) - _exit(EXIT_FAILURE); - - r = mount_move_root(t); - if (r < 0) - _exit(EXIT_FAILURE); +int bus_image_method_get_machine_id( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { - fd = open("/etc/os-release", O_RDONLY|O_CLOEXEC|O_NOCTTY); - if (fd < 0 && errno == ENOENT) { - fd = open("/usr/lib/os-release", O_RDONLY|O_CLOEXEC|O_NOCTTY); - if (fd < 0 && errno == ENOENT) - _exit(EXIT_NOT_FOUND); - } - if (fd < 0) - _exit(EXIT_FAILURE); + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + Image *image = userdata; + int r; - r = copy_bytes(fd, pair[1], (uint64_t) -1, 0); + if (!image->metadata_valid) { + r = image_read_metadata(image); if (r < 0) - _exit(EXIT_FAILURE); - - _exit(EXIT_SUCCESS); + return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m"); } - pair[1] = safe_close(pair[1]); - - f = fdopen(pair[0], "re"); - if (!f) - return -errno; - - pair[0] = -1; - - r = load_env_file_pairs(f, "os-release", NULL, &v); + r = sd_bus_message_new_method_return(message, &reply); if (r < 0) return r; - r = wait_for_terminate(child, &si); + if (sd_id128_is_null(image->machine_id)) /* Add an empty array if the ID is zero */ + r = sd_bus_message_append(reply, "ay", 0); + else + r = sd_bus_message_append_array(reply, 'y', image->machine_id.bytes, 16); if (r < 0) - return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m"); - child = 0; - if (si.si_code == CLD_EXITED && si.si_status == EXIT_NOT_FOUND) - return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Image does not contain OS release information"); - if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS) - return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Child died abnormally."); - - *ret = v; - v = NULL; + return r; - return 0; + return sd_bus_send(NULL, reply, NULL); } -int bus_image_method_get_os_release( +int bus_image_method_get_machine_info( sd_bus_message *message, void *userdata, sd_bus_error *error) { - _cleanup_release_lock_file_ LockFile tree_global_lock = LOCK_FILE_INIT, tree_local_lock = LOCK_FILE_INIT; - _cleanup_strv_free_ char **v = NULL; Image *image = userdata; int r; - r = image_path_lock(image->path, LOCK_SH|LOCK_NB, &tree_global_lock, &tree_local_lock); - if (r < 0) - return sd_bus_error_set_errnof(error, r, "Failed to lock image: %m"); + if (!image->metadata_valid) { + r = image_read_metadata(image); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m"); + } - switch (image->type) { + return bus_reply_pair_array(message, image->machine_info); +} - case IMAGE_DIRECTORY: - case IMAGE_SUBVOLUME: - r = directory_image_get_os_release(image, &v, error); - break; +int bus_image_method_get_os_release( + sd_bus_message *message, + void *userdata, + sd_bus_error *error) { - case IMAGE_RAW: - case IMAGE_BLOCK: - r = raw_image_get_os_release(image, &v, error); - break; + Image *image = userdata; + int r; - default: - assert_not_reached("Unknown image type"); + if (!image->metadata_valid) { + r = image_read_metadata(image); + if (r < 0) + return sd_bus_error_set_errnof(error, r, "Failed to read image metadata: %m"); } - if (r < 0) - return r; - return bus_reply_pair_array(message, v); + return bus_reply_pair_array(message, image->os_release); } const sd_bus_vtable image_vtable[] = { @@ -462,6 +388,9 @@ const sd_bus_vtable image_vtable[] = { SD_BUS_METHOD("Clone", "sb", NULL, bus_image_method_clone, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("MarkReadOnly", "b", NULL, bus_image_method_mark_read_only, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetLimit", "t", NULL, bus_image_method_set_limit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetHostname", NULL, "s", bus_image_method_get_hostname, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetMachineID", NULL, "ay", bus_image_method_get_machine_id, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetMachineInfo", NULL, "a{ss}", bus_image_method_get_machine_info, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetOSRelease", NULL, "a{ss}", bus_image_method_get_os_release, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_END }; diff --git a/src/machine/image-dbus.h b/src/machine/image-dbus.h index f270e57..119c69c 100644 --- a/src/machine/image-dbus.h +++ b/src/machine/image-dbus.h @@ -34,4 +34,7 @@ int bus_image_method_rename(sd_bus_message *message, void *userdata, sd_bus_erro int bus_image_method_clone(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_image_method_mark_read_only(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_image_method_set_limit(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_image_method_get_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_image_method_get_machine_id(sd_bus_message *message, void *userdata, sd_bus_error *error); +int bus_image_method_get_machine_info(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_image_method_get_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error); diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c index f537f3a..8f460d0 100644 --- a/src/machine/machined-dbus.c +++ b/src/machine/machined-dbus.c @@ -846,6 +846,78 @@ static int method_mark_image_read_only(sd_bus_message *message, void *userdata, return bus_image_method_mark_read_only(message, i, error); } +static int method_get_image_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(image_unrefp) Image *i = NULL; + const char *name; + int r; + + assert(message); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + if (!image_name_is_valid(name)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name); + + r = image_find(name, &i); + if (r < 0) + return r; + if (r == 0) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name); + + i->userdata = userdata; + return bus_image_method_get_hostname(message, i, error); +} + +static int method_get_image_machine_id(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(image_unrefp) Image *i = NULL; + const char *name; + int r; + + assert(message); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + if (!image_name_is_valid(name)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name); + + r = image_find(name, &i); + if (r < 0) + return r; + if (r == 0) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name); + + i->userdata = userdata; + return bus_image_method_get_machine_id(message, i, error); +} + +static int method_get_image_machine_info(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(image_unrefp) Image *i = NULL; + const char *name; + int r; + + assert(message); + + r = sd_bus_message_read(message, "s", &name); + if (r < 0) + return r; + + if (!image_name_is_valid(name)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name); + + r = image_find(name, &i); + if (r < 0) + return r; + if (r == 0) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name); + + i->userdata = userdata; + return bus_image_method_get_machine_info(message, i, error); +} + static int method_get_image_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_(image_unrefp) Image *i = NULL; const char *name; @@ -1442,6 +1514,9 @@ const sd_bus_vtable manager_vtable[] = { SD_BUS_METHOD("RenameImage", "ss", NULL, method_rename_image, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CloneImage", "ssb", NULL, method_clone_image, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL, method_mark_image_read_only, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetImageHostname", "s", "s", method_get_image_hostname, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetImageMachineID", "s", "ay", method_get_image_machine_id, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetImageMachineInfo", "s", "a{ss}", method_get_image_machine_info, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetImageOSRelease", "s", "a{ss}", method_get_image_os_release, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetPoolLimit", "t", NULL, method_set_pool_limit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SetImageLimit", "st", NULL, method_set_image_limit, SD_BUS_VTABLE_UNPRIVILEGED), diff --git a/src/machine/org.freedesktop.machine1.conf b/src/machine/org.freedesktop.machine1.conf index daa365a..73b7e07 100644 --- a/src/machine/org.freedesktop.machine1.conf +++ b/src/machine/org.freedesktop.machine1.conf @@ -122,6 +122,18 @@ + + + + + + + + + + + + -- 2.7.4