1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 #include "path-util.h"
28 #include "unit-name.h"
30 #include "bus-common-errors.h"
31 #include "cgroup-util.h"
32 #include "btrfs-util.h"
33 #include "machine-image.h"
34 #include "machine-pool.h"
35 #include "image-dbus.h"
37 #include "machine-dbus.h"
39 static int property_get_pool_path(
42 const char *interface,
44 sd_bus_message *reply,
46 sd_bus_error *error) {
51 return sd_bus_message_append(reply, "s", "/var/lib/machines");
54 static int property_get_pool_usage(
57 const char *interface,
59 sd_bus_message *reply,
61 sd_bus_error *error) {
63 _cleanup_close_ int fd = -1;
64 uint64_t usage = (uint64_t) -1;
70 /* We try to read the quota info from /var/lib/machines, as
71 * well as the usage of the loopback file
72 * /var/lib/machines.raw, and pick the larger value. */
74 fd = open("/var/lib/machines", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
78 if (btrfs_subvol_get_quota_fd(fd, &q) >= 0)
82 if (stat("/var/lib/machines.raw", &st) >= 0) {
83 if (usage == (uint64_t) -1 || st.st_blocks * 512ULL > usage)
84 usage = st.st_blocks * 512ULL;
87 return sd_bus_message_append(reply, "t", usage);
90 static int property_get_pool_limit(
93 const char *interface,
95 sd_bus_message *reply,
97 sd_bus_error *error) {
99 _cleanup_close_ int fd = -1;
100 uint64_t size = (uint64_t) -1;
106 /* We try to read the quota limit from /var/lib/machines, as
107 * well as the size of the loopback file
108 * /var/lib/machines.raw, and pick the smaller value. */
110 fd = open("/var/lib/machines", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
114 if (btrfs_subvol_get_quota_fd(fd, &q) >= 0)
115 size = q.referred_max;
118 if (stat("/var/lib/machines.raw", &st) >= 0) {
119 if (size == (uint64_t) -1 || (uint64_t) st.st_size < size)
123 return sd_bus_message_append(reply, "t", size);
126 static int method_get_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
127 _cleanup_free_ char *p = NULL;
128 Manager *m = userdata;
137 r = sd_bus_message_read(message, "s", &name);
141 machine = hashmap_get(m->machines, name);
143 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
145 p = machine_bus_path(machine);
149 return sd_bus_reply_method_return(message, "o", p);
152 static int method_get_image(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
153 _cleanup_free_ char *p = NULL;
154 Manager *m = userdata;
162 r = sd_bus_message_read(message, "s", &name);
166 r = image_find(name, NULL);
168 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
172 p = image_bus_path(name);
176 return sd_bus_reply_method_return(message, "o", p);
179 static int method_get_machine_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
180 _cleanup_free_ char *p = NULL;
181 Manager *m = userdata;
182 Machine *machine = NULL;
190 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
192 r = sd_bus_message_read(message, "u", &pid);
197 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
199 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
203 r = sd_bus_creds_get_pid(creds, &pid);
208 r = manager_get_machine_by_pid(m, pid, &machine);
212 return sd_bus_error_setf(error, BUS_ERROR_NO_MACHINE_FOR_PID, "PID "PID_FMT" does not belong to any known machine", pid);
214 p = machine_bus_path(machine);
218 return sd_bus_reply_method_return(message, "o", p);
221 static int method_list_machines(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
222 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
223 Manager *m = userdata;
232 r = sd_bus_message_new_method_return(message, &reply);
234 return sd_bus_error_set_errno(error, r);
236 r = sd_bus_message_open_container(reply, 'a', "(ssso)");
238 return sd_bus_error_set_errno(error, r);
240 HASHMAP_FOREACH(machine, m->machines, i) {
241 _cleanup_free_ char *p = NULL;
243 p = machine_bus_path(machine);
247 r = sd_bus_message_append(reply, "(ssso)",
249 strempty(machine_class_to_string(machine->class)),
253 return sd_bus_error_set_errno(error, r);
256 r = sd_bus_message_close_container(reply);
258 return sd_bus_error_set_errno(error, r);
260 return sd_bus_send(bus, reply, NULL);
263 static int method_create_or_register_machine(Manager *manager, sd_bus_message *message, bool read_network, Machine **_m, sd_bus_error *error) {
264 const char *name, *service, *class, *root_directory;
265 const int32_t *netif = NULL;
271 size_t n, n_netif = 0;
278 r = sd_bus_message_read(message, "s", &name);
281 if (!machine_name_is_valid(name))
282 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine name");
284 r = sd_bus_message_read_array(message, 'y', &v, &n);
292 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine ID parameter");
294 r = sd_bus_message_read(message, "ssus", &service, &class, &leader, &root_directory);
301 r = sd_bus_message_read_array(message, 'i', (const void**) &netif, &n_netif);
305 n_netif /= sizeof(int32_t);
307 for (i = 0; i < n_netif; i++) {
309 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid network interface index %i", netif[i]);
314 c = _MACHINE_CLASS_INVALID;
316 c = machine_class_from_string(class);
318 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine class parameter");
322 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
324 if (!isempty(root_directory) && !path_is_absolute(root_directory))
325 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root directory must be empty or an absolute path");
328 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
330 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
334 assert_cc(sizeof(uint32_t) == sizeof(pid_t));
336 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
341 if (hashmap_get(manager->machines, name))
342 return sd_bus_error_setf(error, BUS_ERROR_MACHINE_EXISTS, "Machine '%s' already exists", name);
344 r = manager_add_machine(manager, name, &m);
352 if (!isempty(service)) {
353 m->service = strdup(service);
360 if (!isempty(root_directory)) {
361 m->root_directory = strdup(root_directory);
362 if (!m->root_directory) {
369 assert_cc(sizeof(int32_t) == sizeof(int));
370 m->netif = memdup(netif, sizeof(int32_t) * n_netif);
376 m->n_netif = n_netif;
384 machine_add_to_gc_queue(m);
388 static int method_create_machine_internal(sd_bus *bus, sd_bus_message *message, bool read_network, void *userdata, sd_bus_error *error) {
389 Manager *manager = userdata;
393 r = method_create_or_register_machine(manager, message, read_network, &m, error);
397 r = sd_bus_message_enter_container(message, 'a', "(sv)");
401 r = machine_start(m, message, error);
405 m->create_message = sd_bus_message_ref(message);
409 machine_add_to_gc_queue(m);
413 static int method_create_machine_with_network(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
414 return method_create_machine_internal(bus, message, true, userdata, error);
417 static int method_create_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
418 return method_create_machine_internal(bus, message, false, userdata, error);
421 static int method_register_machine_internal(sd_bus *bus, sd_bus_message *message, bool read_network, void *userdata, sd_bus_error *error) {
422 Manager *manager = userdata;
423 _cleanup_free_ char *p = NULL;
427 r = method_create_or_register_machine(manager, message, read_network, &m, error);
431 r = cg_pid_get_unit(m->leader, &m->unit);
433 r = sd_bus_error_set_errnof(error, r, "Failed to determine unit of process "PID_FMT" : %s", m->leader, strerror(-r));
437 r = machine_start(m, NULL, error);
441 p = machine_bus_path(m);
447 return sd_bus_reply_method_return(message, "o", p);
450 machine_add_to_gc_queue(m);
454 static int method_register_machine_with_network(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
455 return method_register_machine_internal(bus, message, true, userdata, error);
458 static int method_register_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
459 return method_register_machine_internal(bus, message, false, userdata, error);
462 static int method_terminate_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
463 Manager *m = userdata;
472 r = sd_bus_message_read(message, "s", &name);
474 return sd_bus_error_set_errno(error, r);
476 machine = hashmap_get(m->machines, name);
478 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
480 return bus_machine_method_terminate(bus, message, machine, error);
483 static int method_kill_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
484 Manager *m = userdata;
493 r = sd_bus_message_read(message, "s", &name);
495 return sd_bus_error_set_errno(error, r);
497 machine = hashmap_get(m->machines, name);
499 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
501 return bus_machine_method_kill(bus, message, machine, error);
504 static int method_get_machine_addresses(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
505 Manager *m = userdata;
514 r = sd_bus_message_read(message, "s", &name);
516 return sd_bus_error_set_errno(error, r);
518 machine = hashmap_get(m->machines, name);
520 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
522 return bus_machine_method_get_addresses(bus, message, machine, error);
525 static int method_get_machine_os_release(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
526 Manager *m = userdata;
535 r = sd_bus_message_read(message, "s", &name);
537 return sd_bus_error_set_errno(error, r);
539 machine = hashmap_get(m->machines, name);
541 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
543 return bus_machine_method_get_os_release(bus, message, machine, error);
546 static int method_list_images(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
547 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
548 _cleanup_(image_hashmap_freep) Hashmap *images = NULL;
549 Manager *m = userdata;
558 images = hashmap_new(&string_hash_ops);
562 r = image_discover(images);
566 r = sd_bus_message_new_method_return(message, &reply);
570 r = sd_bus_message_open_container(reply, 'a', "(ssbttto)");
574 HASHMAP_FOREACH(image, images, i) {
575 _cleanup_free_ char *p = NULL;
577 p = image_bus_path(image->name);
581 r = sd_bus_message_append(reply, "(ssbttto)",
583 image_type_to_string(image->type),
593 r = sd_bus_message_close_container(reply);
597 return sd_bus_send(bus, reply, NULL);
600 static int method_open_machine_pty(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
601 Manager *m = userdata;
610 r = sd_bus_message_read(message, "s", &name);
612 return sd_bus_error_set_errno(error, r);
614 machine = hashmap_get(m->machines, name);
616 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
618 return bus_machine_method_open_pty(bus, message, machine, error);
621 static int method_open_machine_login(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
622 Manager *m = userdata;
631 r = sd_bus_message_read(message, "s", &name);
635 machine = hashmap_get(m->machines, name);
637 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
639 return bus_machine_method_open_login(bus, message, machine, error);
642 static int method_bind_mount_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
643 Manager *m = userdata;
652 r = sd_bus_message_read(message, "s", &name);
656 machine = hashmap_get(m->machines, name);
658 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
660 return bus_machine_method_bind_mount(bus, message, machine, error);
663 static int method_copy_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
664 Manager *m = userdata;
673 r = sd_bus_message_read(message, "s", &name);
677 machine = hashmap_get(m->machines, name);
679 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
681 return bus_machine_method_copy(bus, message, machine, error);
684 static int method_remove_image(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
685 _cleanup_(image_unrefp) Image* i = NULL;
692 r = sd_bus_message_read(message, "s", &name);
696 if (!image_name_is_valid(name))
697 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
699 r = image_find(name, &i);
703 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
705 i->userdata = userdata;
706 return bus_image_method_remove(bus, message, i, error);
709 static int method_rename_image(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
710 _cleanup_(image_unrefp) Image* i = NULL;
711 const char *old_name;
717 r = sd_bus_message_read(message, "s", &old_name);
721 if (!image_name_is_valid(old_name))
722 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", old_name);
724 r = image_find(old_name, &i);
728 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", old_name);
730 i->userdata = userdata;
731 return bus_image_method_rename(bus, message, i, error);
734 static int method_clone_image(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
735 _cleanup_(image_unrefp) Image *i = NULL;
736 const char *old_name;
740 r = sd_bus_message_read(message, "s", &old_name);
744 if (!image_name_is_valid(old_name))
745 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", old_name);
747 r = image_find(old_name, &i);
751 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", old_name);
753 i->userdata = userdata;
754 return bus_image_method_clone(bus, message, i, error);
757 static int method_mark_image_read_only(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
758 _cleanup_(image_unrefp) Image *i = NULL;
763 r = sd_bus_message_read(message, "s", &name);
767 if (!image_name_is_valid(name))
768 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
770 r = image_find(name, &i);
774 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
776 i->userdata = userdata;
777 return bus_image_method_mark_read_only(bus, message, i, error);
780 static int method_set_pool_limit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
781 Manager *m = userdata;
786 r = sd_bus_message_read(message, "t", &limit);
790 r = bus_verify_polkit_async(
793 "org.freedesktop.machine1.manage-machines",
801 return 1; /* Will call us back */
803 /* Set up the machine directory if necessary */
804 r = setup_machine_directory(limit, error);
808 r = btrfs_resize_loopback("/var/lib/machines", limit);
809 if (r < 0 && r != -ENODEV)
810 return sd_bus_error_set_errnof(error, r, "Failed to adjust loopback limit: %m");
812 r = btrfs_quota_limit("/var/lib/machines", limit);
814 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs.");
816 return sd_bus_error_set_errnof(error, r, "Failed to adjust quota limit: %m");
818 return sd_bus_reply_method_return(message, NULL);
821 static int method_set_image_limit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
822 _cleanup_(image_unrefp) Image *i = NULL;
827 r = sd_bus_message_read(message, "s", &name);
831 if (!image_name_is_valid(name))
832 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
834 r = image_find(name, &i);
838 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
840 i->userdata = userdata;
841 return bus_image_method_set_limit(bus, message, i, error);
844 const sd_bus_vtable manager_vtable[] = {
845 SD_BUS_VTABLE_START(0),
846 SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path, 0, 0),
847 SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage, 0, 0),
848 SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit, 0, 0),
849 SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, SD_BUS_VTABLE_UNPRIVILEGED),
850 SD_BUS_METHOD("GetImage", "s", "o", method_get_image, SD_BUS_VTABLE_UNPRIVILEGED),
851 SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
852 SD_BUS_METHOD("ListMachines", NULL, "a(ssso)", method_list_machines, SD_BUS_VTABLE_UNPRIVILEGED),
853 SD_BUS_METHOD("ListImages", NULL, "a(ssbttto)", method_list_images, SD_BUS_VTABLE_UNPRIVILEGED),
854 SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine, 0),
855 SD_BUS_METHOD("CreateMachineWithNetwork", "sayssusaia(sv)", "o", method_create_machine_with_network, 0),
856 SD_BUS_METHOD("RegisterMachine", "sayssus", "o", method_register_machine, 0),
857 SD_BUS_METHOD("RegisterMachineWithNetwork", "sayssusai", "o", method_register_machine_with_network, 0),
858 SD_BUS_METHOD("TerminateMachine", "s", NULL, method_terminate_machine, SD_BUS_VTABLE_UNPRIVILEGED),
859 SD_BUS_METHOD("KillMachine", "ssi", NULL, method_kill_machine, SD_BUS_VTABLE_UNPRIVILEGED),
860 SD_BUS_METHOD("GetMachineAddresses", "s", "a(iay)", method_get_machine_addresses, SD_BUS_VTABLE_UNPRIVILEGED),
861 SD_BUS_METHOD("GetMachineOSRelease", "s", "a{ss}", method_get_machine_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
862 SD_BUS_METHOD("OpenMachinePTY", "s", "hs", method_open_machine_pty, 0),
863 SD_BUS_METHOD("OpenMachineLogin", "s", "hs", method_open_machine_login, SD_BUS_VTABLE_UNPRIVILEGED),
864 SD_BUS_METHOD("BindMountMachine", "sssbb", NULL, method_bind_mount_machine, SD_BUS_VTABLE_UNPRIVILEGED),
865 SD_BUS_METHOD("CopyFromMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED),
866 SD_BUS_METHOD("CopyToMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED),
867 SD_BUS_METHOD("RemoveImage", "s", NULL, method_remove_image, SD_BUS_VTABLE_UNPRIVILEGED),
868 SD_BUS_METHOD("RenameImage", "ss", NULL, method_rename_image, SD_BUS_VTABLE_UNPRIVILEGED),
869 SD_BUS_METHOD("CloneImage", "ssb", NULL, method_clone_image, SD_BUS_VTABLE_UNPRIVILEGED),
870 SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL, method_mark_image_read_only, SD_BUS_VTABLE_UNPRIVILEGED),
871 SD_BUS_METHOD("SetPoolLimit", "t", NULL, method_set_pool_limit, SD_BUS_VTABLE_UNPRIVILEGED),
872 SD_BUS_METHOD("SetImageLimit", "st", NULL, method_set_image_limit, SD_BUS_VTABLE_UNPRIVILEGED),
873 SD_BUS_SIGNAL("MachineNew", "so", 0),
874 SD_BUS_SIGNAL("MachineRemoved", "so", 0),
878 int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
879 const char *path, *result, *unit;
880 Manager *m = userdata;
889 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
891 bus_log_parse_error(r);
895 machine = hashmap_get(m->machine_units, unit);
899 if (streq_ptr(path, machine->scope_job)) {
900 free(machine->scope_job);
901 machine->scope_job = NULL;
903 if (machine->started) {
904 if (streq(result, "done"))
905 machine_send_create_reply(machine, NULL);
907 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
909 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
911 machine_send_create_reply(machine, &e);
914 machine_save(machine);
917 machine_add_to_gc_queue(machine);
921 int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
922 _cleanup_free_ char *unit = NULL;
923 Manager *m = userdata;
932 path = sd_bus_message_get_path(message);
936 r = unit_name_from_dbus_path(path, &unit);
937 if (r == -EINVAL) /* not for a unit */
942 machine = hashmap_get(m->machine_units, unit);
944 machine_add_to_gc_queue(machine);
949 int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
950 const char *path, *unit;
951 Manager *m = userdata;
959 r = sd_bus_message_read(message, "so", &unit, &path);
961 bus_log_parse_error(r);
965 machine = hashmap_get(m->machine_units, unit);
967 machine_add_to_gc_queue(machine);
972 int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
973 Manager *m = userdata;
980 r = sd_bus_message_read(message, "b", &b);
982 bus_log_parse_error(r);
988 /* systemd finished reloading, let's recheck all our machines */
989 log_debug("System manager has been reloaded, rechecking machines...");
991 HASHMAP_FOREACH(machine, m->machines, i)
992 machine_add_to_gc_queue(machine);
997 int manager_start_scope(
1002 const char *description,
1003 sd_bus_message *more_properties,
1004 sd_bus_error *error,
1007 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
1014 r = sd_bus_message_new_method_call(
1017 "org.freedesktop.systemd1",
1018 "/org/freedesktop/systemd1",
1019 "org.freedesktop.systemd1.Manager",
1020 "StartTransientUnit");
1024 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
1028 r = sd_bus_message_open_container(m, 'a', "(sv)");
1032 if (!isempty(slice)) {
1033 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
1038 if (!isempty(description)) {
1039 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
1044 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
1048 r = sd_bus_message_append(m, "(sv)", "Delegate", "b", 1);
1052 if (more_properties) {
1053 r = sd_bus_message_copy(m, more_properties, true);
1058 r = sd_bus_message_close_container(m);
1062 r = sd_bus_message_append(m, "a(sa(sv))", 0);
1066 r = sd_bus_call(manager->bus, m, 0, error, &reply);
1074 r = sd_bus_message_read(reply, "o", &j);
1088 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
1089 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1095 r = sd_bus_call_method(
1097 "org.freedesktop.systemd1",
1098 "/org/freedesktop/systemd1",
1099 "org.freedesktop.systemd1.Manager",
1103 "ss", unit, "fail");
1105 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
1106 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
1111 sd_bus_error_free(error);
1122 r = sd_bus_message_read(reply, "o", &j);
1136 int manager_kill_unit(Manager *manager, const char *unit, int signo, sd_bus_error *error) {
1140 return sd_bus_call_method(
1142 "org.freedesktop.systemd1",
1143 "/org/freedesktop/systemd1",
1144 "org.freedesktop.systemd1.Manager",
1148 "ssi", unit, "all", signo);
1151 int manager_unit_is_active(Manager *manager, const char *unit) {
1152 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1153 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1154 _cleanup_free_ char *path = NULL;
1161 path = unit_dbus_path_from_name(unit);
1165 r = sd_bus_get_property(
1167 "org.freedesktop.systemd1",
1169 "org.freedesktop.systemd1.Unit",
1175 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
1176 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
1179 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
1180 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
1186 r = sd_bus_message_read(reply, "s", &state);
1190 return !streq(state, "inactive") && !streq(state, "failed");
1193 int manager_job_is_active(Manager *manager, const char *path) {
1194 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1195 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1201 r = sd_bus_get_property(
1203 "org.freedesktop.systemd1",
1205 "org.freedesktop.systemd1.Job",
1211 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
1212 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
1215 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
1221 /* We don't actually care about the state really. The fact
1222 * that we could read the job state is enough for us */
1227 int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
1228 _cleanup_free_ char *unit = NULL;
1236 r = cg_pid_get_unit(pid, &unit);
1238 mm = hashmap_get(m->machine_leaders, UINT_TO_PTR(pid));
1240 mm = hashmap_get(m->machine_units, unit);
1249 int manager_add_machine(Manager *m, const char *name, Machine **_machine) {
1255 machine = hashmap_get(m->machines, name);
1257 machine = machine_new(m, name);
1263 *_machine = machine;