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.
This commit is contained in:
Lennart Poettering 2017-11-14 23:27:14 +01:00
parent c7664c071e
commit cf30a8c1ed
4 changed files with 157 additions and 126 deletions

View File

@ -290,124 +290,68 @@ int bus_image_method_set_limit(
return sd_bus_reply_method_return(message, NULL);
}
#define EXIT_NOT_FOUND 2
int bus_image_method_get_hostname(
sd_bus_message *message,
void *userdata,
sd_bus_error *error) {
static int directory_image_get_os_release(Image *image, char ***ret, 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);
return 0;
}
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 (!image->metadata_valid) {
r = image_read_metadata(image);
if (r < 0)
_exit(EXIT_FAILURE);
r = mount_move_root(t);
if (r < 0)
_exit(EXIT_FAILURE);
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);
r = copy_bytes(fd, pair[1], (uint64_t) -1, 0);
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]);
return sd_bus_reply_method_return(message, "s", image->hostname);
}
f = fdopen(pair[0], "re");
if (!f)
return -errno;
int bus_image_method_get_machine_id(
sd_bus_message *message,
void *userdata,
sd_bus_error *error) {
pair[0] = -1;
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
Image *image = userdata;
int r;
r = load_env_file_pairs(f, "os-release", NULL, &v);
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");
}
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.");
return r;
*ret = v;
v = NULL;
return sd_bus_send(NULL, reply, NULL);
}
return 0;
int bus_image_method_get_machine_info(
sd_bus_message *message,
void *userdata,
sd_bus_error *error) {
Image *image = userdata;
int r;
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 bus_reply_pair_array(message, image->machine_info);
}
int bus_image_method_get_os_release(
@ -415,34 +359,16 @@ int bus_image_method_get_os_release(
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");
switch (image->type) {
case IMAGE_DIRECTORY:
case IMAGE_SUBVOLUME:
r = directory_image_get_os_release(image, &v, error);
break;
case IMAGE_RAW:
case IMAGE_BLOCK:
r = raw_image_get_os_release(image, &v, error);
break;
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
};

View File

@ -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);

View File

@ -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),

View File

@ -120,6 +120,18 @@
send_interface="org.freedesktop.machine1.Manager"
send_member="SetImageLimit"/>
<allow send_destination="org.freedesktop.machine1"
send_interface="org.freedesktop.machine1.Manager"
send_member="GetImageHostname"/>
<allow send_destination="org.freedesktop.machine1"
send_interface="org.freedesktop.machine1.Manager"
send_member="GetImageMachineID"/>
<allow send_destination="org.freedesktop.machine1"
send_interface="org.freedesktop.machine1.Manager"
send_member="GetImageMachineInfo"/>
<allow send_destination="org.freedesktop.machine1"
send_interface="org.freedesktop.machine1.Manager"
send_member="GetImageOSRelease"/>
@ -204,6 +216,18 @@
send_interface="org.freedesktop.machine1.Image"
send_member="MarkReadOnly"/>
<allow send_destination="org.freedesktop.machine1"
send_interface="org.freedesktop.machine1.Image"
send_member="GetHostname"/>
<allow send_destination="org.freedesktop.machine1"
send_interface="org.freedesktop.machine1.Image"
send_member="GetMachineID"/>
<allow send_destination="org.freedesktop.machine1"
send_interface="org.freedesktop.machine1.Image"
send_member="GetMachineInfo"/>
<allow send_destination="org.freedesktop.machine1"
send_interface="org.freedesktop.machine1.Image"
send_member="GetOSRelease"/>