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/>.
28 #include "path-util.h"
29 #include "unit-name.h"
31 #include "bus-common-errors.h"
32 #include "cgroup-util.h"
33 #include "btrfs-util.h"
34 #include "formats-util.h"
35 #include "process-util.h"
36 #include "hostname-util.h"
37 #include "machine-image.h"
38 #include "machine-pool.h"
39 #include "image-dbus.h"
41 #include "machine-dbus.h"
43 static int property_get_pool_path(
46 const char *interface
,
48 sd_bus_message
*reply
,
50 sd_bus_error
*error
) {
55 return sd_bus_message_append(reply
, "s", "/var/lib/machines");
58 static int property_get_pool_usage(
61 const char *interface
,
63 sd_bus_message
*reply
,
65 sd_bus_error
*error
) {
67 _cleanup_close_
int fd
= -1;
68 uint64_t usage
= (uint64_t) -1;
74 /* We try to read the quota info from /var/lib/machines, as
75 * well as the usage of the loopback file
76 * /var/lib/machines.raw, and pick the larger value. */
78 fd
= open("/var/lib/machines", O_RDONLY
|O_CLOEXEC
|O_DIRECTORY
);
82 if (btrfs_subvol_get_quota_fd(fd
, &q
) >= 0)
86 if (stat("/var/lib/machines.raw", &st
) >= 0) {
87 if (usage
== (uint64_t) -1 || st
.st_blocks
* 512ULL > usage
)
88 usage
= st
.st_blocks
* 512ULL;
91 return sd_bus_message_append(reply
, "t", usage
);
94 static int property_get_pool_limit(
97 const char *interface
,
99 sd_bus_message
*reply
,
101 sd_bus_error
*error
) {
103 _cleanup_close_
int fd
= -1;
104 uint64_t size
= (uint64_t) -1;
110 /* We try to read the quota limit from /var/lib/machines, as
111 * well as the size of the loopback file
112 * /var/lib/machines.raw, and pick the smaller value. */
114 fd
= open("/var/lib/machines", O_RDONLY
|O_CLOEXEC
|O_DIRECTORY
);
118 if (btrfs_subvol_get_quota_fd(fd
, &q
) >= 0)
119 size
= q
.referenced_max
;
122 if (stat("/var/lib/machines.raw", &st
) >= 0) {
123 if (size
== (uint64_t) -1 || (uint64_t) st
.st_size
< size
)
127 return sd_bus_message_append(reply
, "t", size
);
130 static int method_get_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
131 _cleanup_free_
char *p
= NULL
;
132 Manager
*m
= userdata
;
140 r
= sd_bus_message_read(message
, "s", &name
);
144 machine
= hashmap_get(m
->machines
, name
);
146 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
148 p
= machine_bus_path(machine
);
152 return sd_bus_reply_method_return(message
, "o", p
);
155 static int method_get_image(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
156 _cleanup_free_
char *p
= NULL
;
157 Manager
*m
= userdata
;
164 r
= sd_bus_message_read(message
, "s", &name
);
168 r
= image_find(name
, NULL
);
170 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
174 p
= image_bus_path(name
);
178 return sd_bus_reply_method_return(message
, "o", p
);
181 static int method_get_machine_by_pid(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
182 _cleanup_free_
char *p
= NULL
;
183 Manager
*m
= userdata
;
184 Machine
*machine
= NULL
;
191 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
193 r
= sd_bus_message_read(message
, "u", &pid
);
198 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
200 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
204 r
= sd_bus_creds_get_pid(creds
, &pid
);
209 r
= manager_get_machine_by_pid(m
, pid
, &machine
);
213 return sd_bus_error_setf(error
, BUS_ERROR_NO_MACHINE_FOR_PID
, "PID "PID_FMT
" does not belong to any known machine", pid
);
215 p
= machine_bus_path(machine
);
219 return sd_bus_reply_method_return(message
, "o", p
);
222 static int method_list_machines(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
223 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
224 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(NULL
, 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_message
*message
, bool read_network
, void *userdata
, sd_bus_error
*error
) {
389 Manager
*manager
= userdata
;
396 r
= method_create_or_register_machine(manager
, message
, read_network
, &m
, error
);
400 r
= sd_bus_message_enter_container(message
, 'a', "(sv)");
404 r
= machine_start(m
, message
, error
);
408 m
->create_message
= sd_bus_message_ref(message
);
412 machine_add_to_gc_queue(m
);
416 static int method_create_machine_with_network(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
417 return method_create_machine_internal(message
, true, userdata
, error
);
420 static int method_create_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
421 return method_create_machine_internal(message
, false, userdata
, error
);
424 static int method_register_machine_internal(sd_bus_message
*message
, bool read_network
, void *userdata
, sd_bus_error
*error
) {
425 Manager
*manager
= userdata
;
426 _cleanup_free_
char *p
= NULL
;
433 r
= method_create_or_register_machine(manager
, message
, read_network
, &m
, error
);
437 r
= cg_pid_get_unit(m
->leader
, &m
->unit
);
439 r
= sd_bus_error_set_errnof(error
, r
, "Failed to determine unit of process "PID_FMT
" : %s", m
->leader
, strerror(-r
));
443 r
= machine_start(m
, NULL
, error
);
447 p
= machine_bus_path(m
);
453 return sd_bus_reply_method_return(message
, "o", p
);
456 machine_add_to_gc_queue(m
);
460 static int method_register_machine_with_network(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
461 return method_register_machine_internal(message
, true, userdata
, error
);
464 static int method_register_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
465 return method_register_machine_internal(message
, false, userdata
, error
);
468 static int method_terminate_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
469 Manager
*m
= userdata
;
477 r
= sd_bus_message_read(message
, "s", &name
);
479 return sd_bus_error_set_errno(error
, r
);
481 machine
= hashmap_get(m
->machines
, name
);
483 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
485 return bus_machine_method_terminate(message
, machine
, error
);
488 static int method_kill_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
489 Manager
*m
= userdata
;
497 r
= sd_bus_message_read(message
, "s", &name
);
499 return sd_bus_error_set_errno(error
, r
);
501 machine
= hashmap_get(m
->machines
, name
);
503 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
505 return bus_machine_method_kill(message
, machine
, error
);
508 static int method_get_machine_addresses(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
509 Manager
*m
= userdata
;
517 r
= sd_bus_message_read(message
, "s", &name
);
519 return sd_bus_error_set_errno(error
, r
);
521 machine
= hashmap_get(m
->machines
, name
);
523 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
525 return bus_machine_method_get_addresses(message
, machine
, error
);
528 static int method_get_machine_os_release(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
529 Manager
*m
= userdata
;
537 r
= sd_bus_message_read(message
, "s", &name
);
539 return sd_bus_error_set_errno(error
, r
);
541 machine
= hashmap_get(m
->machines
, name
);
543 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
545 return bus_machine_method_get_os_release(message
, machine
, error
);
548 static int method_list_images(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
549 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
550 _cleanup_(image_hashmap_freep
) Hashmap
*images
= NULL
;
551 Manager
*m
= userdata
;
559 images
= hashmap_new(&string_hash_ops
);
563 r
= image_discover(images
);
567 r
= sd_bus_message_new_method_return(message
, &reply
);
571 r
= sd_bus_message_open_container(reply
, 'a', "(ssbttto)");
575 HASHMAP_FOREACH(image
, images
, i
) {
576 _cleanup_free_
char *p
= NULL
;
578 p
= image_bus_path(image
->name
);
582 r
= sd_bus_message_append(reply
, "(ssbttto)",
584 image_type_to_string(image
->type
),
594 r
= sd_bus_message_close_container(reply
);
598 return sd_bus_send(NULL
, reply
, NULL
);
601 static int method_open_machine_pty(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
602 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(message
, machine
, error
);
621 static int method_open_machine_login(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
622 Manager
*m
= userdata
;
630 r
= sd_bus_message_read(message
, "s", &name
);
634 machine
= hashmap_get(m
->machines
, name
);
636 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
638 return bus_machine_method_open_login(message
, machine
, error
);
641 static int method_open_machine_shell(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
642 Manager
*m
= userdata
;
651 r
= sd_bus_message_read(message
, "s", &name
);
655 machine
= hashmap_get(m
->machines
, name
);
657 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
659 return bus_machine_method_open_shell(message
, machine
, error
);
662 static int method_bind_mount_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
663 Manager
*m
= userdata
;
671 r
= sd_bus_message_read(message
, "s", &name
);
675 machine
= hashmap_get(m
->machines
, name
);
677 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
679 return bus_machine_method_bind_mount(message
, machine
, error
);
682 static int method_copy_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
683 Manager
*m
= userdata
;
691 r
= sd_bus_message_read(message
, "s", &name
);
695 machine
= hashmap_get(m
->machines
, name
);
697 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
699 return bus_machine_method_copy(message
, machine
, error
);
702 static int method_remove_image(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
703 _cleanup_(image_unrefp
) Image
* i
= NULL
;
709 r
= sd_bus_message_read(message
, "s", &name
);
713 if (!image_name_is_valid(name
))
714 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", name
);
716 r
= image_find(name
, &i
);
720 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
722 i
->userdata
= userdata
;
723 return bus_image_method_remove(message
, i
, error
);
726 static int method_rename_image(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
727 _cleanup_(image_unrefp
) Image
* i
= NULL
;
728 const char *old_name
;
733 r
= sd_bus_message_read(message
, "s", &old_name
);
737 if (!image_name_is_valid(old_name
))
738 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", old_name
);
740 r
= image_find(old_name
, &i
);
744 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", old_name
);
746 i
->userdata
= userdata
;
747 return bus_image_method_rename(message
, i
, error
);
750 static int method_clone_image(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
751 _cleanup_(image_unrefp
) Image
*i
= NULL
;
752 const char *old_name
;
757 r
= sd_bus_message_read(message
, "s", &old_name
);
761 if (!image_name_is_valid(old_name
))
762 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", old_name
);
764 r
= image_find(old_name
, &i
);
768 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", old_name
);
770 i
->userdata
= userdata
;
771 return bus_image_method_clone(message
, i
, error
);
774 static int method_mark_image_read_only(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
775 _cleanup_(image_unrefp
) Image
*i
= NULL
;
781 r
= sd_bus_message_read(message
, "s", &name
);
785 if (!image_name_is_valid(name
))
786 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", name
);
788 r
= image_find(name
, &i
);
792 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
794 i
->userdata
= userdata
;
795 return bus_image_method_mark_read_only(message
, i
, error
);
798 static int method_set_pool_limit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
799 Manager
*m
= userdata
;
805 r
= sd_bus_message_read(message
, "t", &limit
);
809 r
= bus_verify_polkit_async(
812 "org.freedesktop.machine1.manage-machines",
820 return 1; /* Will call us back */
822 /* Set up the machine directory if necessary */
823 r
= setup_machine_directory(limit
, error
);
827 r
= btrfs_resize_loopback("/var/lib/machines", limit
, false);
829 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Quota is only supported on btrfs.");
830 if (r
< 0 && r
!= -ENODEV
) /* ignore ENODEV, as that's what is returned if the file system is not on loopback */
831 return sd_bus_error_set_errnof(error
, r
, "Failed to adjust loopback limit: %m");
833 r
= btrfs_quota_limit("/var/lib/machines", limit
);
835 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Quota is only supported on btrfs.");
837 return sd_bus_error_set_errnof(error
, r
, "Failed to adjust quota limit: %m");
839 return sd_bus_reply_method_return(message
, NULL
);
842 static int method_set_image_limit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
843 _cleanup_(image_unrefp
) Image
*i
= NULL
;
849 r
= sd_bus_message_read(message
, "s", &name
);
853 if (!image_name_is_valid(name
))
854 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", name
);
856 r
= image_find(name
, &i
);
860 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
862 i
->userdata
= userdata
;
863 return bus_image_method_set_limit(message
, i
, error
);
866 static int method_map_from_machine_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
867 _cleanup_fclose_
FILE *f
= NULL
;
868 Manager
*m
= userdata
;
869 const char *name
, *p
;
874 r
= sd_bus_message_read(message
, "su", &name
, &uid
);
878 if (UID_IS_INVALID(uid
))
879 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
881 machine
= hashmap_get(m
->machines
, name
);
883 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
885 p
= procfs_file_alloca(machine
->leader
, "uid_map");
891 uid_t uid_base
, uid_shift
, uid_range
, converted
;
895 k
= fscanf(f
, UID_FMT
" " UID_FMT
" " UID_FMT
, &uid_base
, &uid_shift
, &uid_range
);
896 if (k
< 0 && feof(f
))
899 if (ferror(f
) && errno
!= 0)
905 if (uid
< uid_base
|| uid
>= uid_base
+ uid_range
)
908 converted
= uid
- uid_base
+ uid_shift
;
909 if (UID_IS_INVALID(converted
))
910 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
912 return sd_bus_reply_method_return(message
, "u", (uint32_t) converted
);
915 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "Machine '%s' has no matching user mappings.", name
);
918 static int method_map_to_machine_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
919 Manager
*m
= userdata
;
925 r
= sd_bus_message_read(message
, "u", &uid
);
928 if (UID_IS_INVALID(uid
))
929 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
931 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "User " UID_FMT
" belongs to host UID range", uid
);
933 HASHMAP_FOREACH(machine
, m
->machines
, i
) {
934 _cleanup_fclose_
FILE *f
= NULL
;
935 char p
[strlen("/proc//uid_map") + DECIMAL_STR_MAX(pid_t
) + 1];
937 xsprintf(p
, "/proc/" UID_FMT
"/uid_map", machine
->leader
);
940 log_warning_errno(errno
, "Failed top open %s, ignoring,", p
);
945 _cleanup_free_
char *o
= NULL
;
946 uid_t uid_base
, uid_shift
, uid_range
, converted
;
950 k
= fscanf(f
, UID_FMT
" " UID_FMT
" " UID_FMT
, &uid_base
, &uid_shift
, &uid_range
);
951 if (k
< 0 && feof(f
))
954 if (ferror(f
) && errno
!= 0)
960 if (uid
< uid_shift
|| uid
>= uid_shift
+ uid_range
)
963 converted
= (uid
- uid_shift
+ uid_base
);
964 if (UID_IS_INVALID(converted
))
965 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
967 o
= machine_bus_path(machine
);
971 return sd_bus_reply_method_return(message
, "sou", machine
->name
, o
, (uint32_t) converted
);
975 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "No matching user mapping for " UID_FMT
".", uid
);
978 static int method_map_from_machine_group(sd_bus_message
*message
, void *groupdata
, sd_bus_error
*error
) {
979 _cleanup_fclose_
FILE *f
= NULL
;
980 Manager
*m
= groupdata
;
981 const char *name
, *p
;
986 r
= sd_bus_message_read(message
, "su", &name
, &gid
);
990 if (GID_IS_INVALID(gid
))
991 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
993 machine
= hashmap_get(m
->machines
, name
);
995 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
997 p
= procfs_file_alloca(machine
->leader
, "gid_map");
1003 gid_t gid_base
, gid_shift
, gid_range
, converted
;
1007 k
= fscanf(f
, GID_FMT
" " GID_FMT
" " GID_FMT
, &gid_base
, &gid_shift
, &gid_range
);
1008 if (k
< 0 && feof(f
))
1011 if (ferror(f
) && errno
!= 0)
1017 if (gid
< gid_base
|| gid
>= gid_base
+ gid_range
)
1020 converted
= gid
- gid_base
+ gid_shift
;
1021 if (GID_IS_INVALID(converted
))
1022 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1024 return sd_bus_reply_method_return(message
, "u", (uint32_t) converted
);
1027 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
, "Machine '%s' has no matching group mappings.", name
);
1030 static int method_map_to_machine_group(sd_bus_message
*message
, void *groupdata
, sd_bus_error
*error
) {
1031 Manager
*m
= groupdata
;
1037 r
= sd_bus_message_read(message
, "u", &gid
);
1040 if (GID_IS_INVALID(gid
))
1041 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1043 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
, "Group " GID_FMT
" belongs to host GID range", gid
);
1045 HASHMAP_FOREACH(machine
, m
->machines
, i
) {
1046 _cleanup_fclose_
FILE *f
= NULL
;
1047 char p
[strlen("/proc//gid_map") + DECIMAL_STR_MAX(pid_t
) + 1];
1049 xsprintf(p
, "/proc/" GID_FMT
"/gid_map", machine
->leader
);
1052 log_warning_errno(errno
, "Failed top open %s, ignoring,", p
);
1057 _cleanup_free_
char *o
= NULL
;
1058 gid_t gid_base
, gid_shift
, gid_range
, converted
;
1062 k
= fscanf(f
, GID_FMT
" " GID_FMT
" " GID_FMT
, &gid_base
, &gid_shift
, &gid_range
);
1063 if (k
< 0 && feof(f
))
1066 if (ferror(f
) && errno
!= 0)
1072 if (gid
< gid_shift
|| gid
>= gid_shift
+ gid_range
)
1075 converted
= (gid
- gid_shift
+ gid_base
);
1076 if (GID_IS_INVALID(converted
))
1077 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1079 o
= machine_bus_path(machine
);
1083 return sd_bus_reply_method_return(message
, "sou", machine
->name
, o
, (uint32_t) converted
);
1087 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
, "No matching group mapping for " GID_FMT
".", gid
);
1090 const sd_bus_vtable manager_vtable
[] = {
1091 SD_BUS_VTABLE_START(0),
1092 SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path
, 0, 0),
1093 SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage
, 0, 0),
1094 SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit
, 0, 0),
1095 SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1096 SD_BUS_METHOD("GetImage", "s", "o", method_get_image
, SD_BUS_VTABLE_UNPRIVILEGED
),
1097 SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid
, SD_BUS_VTABLE_UNPRIVILEGED
),
1098 SD_BUS_METHOD("ListMachines", NULL
, "a(ssso)", method_list_machines
, SD_BUS_VTABLE_UNPRIVILEGED
),
1099 SD_BUS_METHOD("ListImages", NULL
, "a(ssbttto)", method_list_images
, SD_BUS_VTABLE_UNPRIVILEGED
),
1100 SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine
, 0),
1101 SD_BUS_METHOD("CreateMachineWithNetwork", "sayssusaia(sv)", "o", method_create_machine_with_network
, 0),
1102 SD_BUS_METHOD("RegisterMachine", "sayssus", "o", method_register_machine
, 0),
1103 SD_BUS_METHOD("RegisterMachineWithNetwork", "sayssusai", "o", method_register_machine_with_network
, 0),
1104 SD_BUS_METHOD("TerminateMachine", "s", NULL
, method_terminate_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1105 SD_BUS_METHOD("KillMachine", "ssi", NULL
, method_kill_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1106 SD_BUS_METHOD("GetMachineAddresses", "s", "a(iay)", method_get_machine_addresses
, SD_BUS_VTABLE_UNPRIVILEGED
),
1107 SD_BUS_METHOD("GetMachineOSRelease", "s", "a{ss}", method_get_machine_os_release
, SD_BUS_VTABLE_UNPRIVILEGED
),
1108 SD_BUS_METHOD("OpenMachinePTY", "s", "hs", method_open_machine_pty
, 0),
1109 SD_BUS_METHOD("OpenMachineLogin", "s", "hs", method_open_machine_login
, SD_BUS_VTABLE_UNPRIVILEGED
),
1110 SD_BUS_METHOD("OpenMachineShell", "sssasas", "hs", method_open_machine_shell
, SD_BUS_VTABLE_UNPRIVILEGED
),
1111 SD_BUS_METHOD("BindMountMachine", "sssbb", NULL
, method_bind_mount_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1112 SD_BUS_METHOD("CopyFromMachine", "sss", NULL
, method_copy_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1113 SD_BUS_METHOD("CopyToMachine", "sss", NULL
, method_copy_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1114 SD_BUS_METHOD("RemoveImage", "s", NULL
, method_remove_image
, SD_BUS_VTABLE_UNPRIVILEGED
),
1115 SD_BUS_METHOD("RenameImage", "ss", NULL
, method_rename_image
, SD_BUS_VTABLE_UNPRIVILEGED
),
1116 SD_BUS_METHOD("CloneImage", "ssb", NULL
, method_clone_image
, SD_BUS_VTABLE_UNPRIVILEGED
),
1117 SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL
, method_mark_image_read_only
, SD_BUS_VTABLE_UNPRIVILEGED
),
1118 SD_BUS_METHOD("SetPoolLimit", "t", NULL
, method_set_pool_limit
, SD_BUS_VTABLE_UNPRIVILEGED
),
1119 SD_BUS_METHOD("SetImageLimit", "st", NULL
, method_set_image_limit
, SD_BUS_VTABLE_UNPRIVILEGED
),
1120 SD_BUS_METHOD("MapFromMachineUser", "su", "u", method_map_from_machine_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
1121 SD_BUS_METHOD("MapToMachineUser", "u", "sou", method_map_to_machine_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
1122 SD_BUS_METHOD("MapFromMachineGroup", "su", "u", method_map_from_machine_group
, SD_BUS_VTABLE_UNPRIVILEGED
),
1123 SD_BUS_METHOD("MapToMachineGroup", "u", "sou", method_map_to_machine_group
, SD_BUS_VTABLE_UNPRIVILEGED
),
1124 SD_BUS_SIGNAL("MachineNew", "so", 0),
1125 SD_BUS_SIGNAL("MachineRemoved", "so", 0),
1129 int match_job_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1130 const char *path
, *result
, *unit
;
1131 Manager
*m
= userdata
;
1139 r
= sd_bus_message_read(message
, "uoss", &id
, &path
, &unit
, &result
);
1141 bus_log_parse_error(r
);
1145 machine
= hashmap_get(m
->machine_units
, unit
);
1149 if (streq_ptr(path
, machine
->scope_job
)) {
1150 machine
->scope_job
= mfree(machine
->scope_job
);
1152 if (machine
->started
) {
1153 if (streq(result
, "done"))
1154 machine_send_create_reply(machine
, NULL
);
1156 _cleanup_bus_error_free_ sd_bus_error e
= SD_BUS_ERROR_NULL
;
1158 sd_bus_error_setf(&e
, BUS_ERROR_JOB_FAILED
, "Start job for unit %s failed with '%s'", unit
, result
);
1160 machine_send_create_reply(machine
, &e
);
1164 machine_save(machine
);
1167 machine_add_to_gc_queue(machine
);
1171 int match_properties_changed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1172 _cleanup_free_
char *unit
= NULL
;
1174 Manager
*m
= userdata
;
1181 path
= sd_bus_message_get_path(message
);
1185 r
= unit_name_from_dbus_path(path
, &unit
);
1186 if (r
== -EINVAL
) /* not for a unit */
1193 machine
= hashmap_get(m
->machine_units
, unit
);
1197 machine_add_to_gc_queue(machine
);
1201 int match_unit_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1202 const char *path
, *unit
;
1203 Manager
*m
= userdata
;
1210 r
= sd_bus_message_read(message
, "so", &unit
, &path
);
1212 bus_log_parse_error(r
);
1216 machine
= hashmap_get(m
->machine_units
, unit
);
1220 machine_add_to_gc_queue(machine
);
1224 int match_reloading(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1225 Manager
*m
= userdata
;
1233 r
= sd_bus_message_read(message
, "b", &b
);
1235 bus_log_parse_error(r
);
1241 /* systemd finished reloading, let's recheck all our machines */
1242 log_debug("System manager has been reloaded, rechecking machines...");
1244 HASHMAP_FOREACH(machine
, m
->machines
, i
)
1245 machine_add_to_gc_queue(machine
);
1250 int manager_start_scope(
1255 const char *description
,
1256 sd_bus_message
*more_properties
,
1257 sd_bus_error
*error
,
1260 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
, *reply
= NULL
;
1267 r
= sd_bus_message_new_method_call(
1270 "org.freedesktop.systemd1",
1271 "/org/freedesktop/systemd1",
1272 "org.freedesktop.systemd1.Manager",
1273 "StartTransientUnit");
1277 r
= sd_bus_message_append(m
, "ss", strempty(scope
), "fail");
1281 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
1285 if (!isempty(slice
)) {
1286 r
= sd_bus_message_append(m
, "(sv)", "Slice", "s", slice
);
1291 if (!isempty(description
)) {
1292 r
= sd_bus_message_append(m
, "(sv)", "Description", "s", description
);
1297 r
= sd_bus_message_append(m
, "(sv)", "PIDs", "au", 1, pid
);
1301 r
= sd_bus_message_append(m
, "(sv)", "Delegate", "b", 1);
1305 if (more_properties
) {
1306 r
= sd_bus_message_copy(m
, more_properties
, true);
1311 r
= sd_bus_message_close_container(m
);
1315 r
= sd_bus_message_append(m
, "a(sa(sv))", 0);
1319 r
= sd_bus_call(manager
->bus
, m
, 0, error
, &reply
);
1327 r
= sd_bus_message_read(reply
, "o", &j
);
1341 int manager_stop_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
1342 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1348 r
= sd_bus_call_method(
1350 "org.freedesktop.systemd1",
1351 "/org/freedesktop/systemd1",
1352 "org.freedesktop.systemd1.Manager",
1356 "ss", unit
, "fail");
1358 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) ||
1359 sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
)) {
1364 sd_bus_error_free(error
);
1375 r
= sd_bus_message_read(reply
, "o", &j
);
1389 int manager_kill_unit(Manager
*manager
, const char *unit
, int signo
, sd_bus_error
*error
) {
1393 return sd_bus_call_method(
1395 "org.freedesktop.systemd1",
1396 "/org/freedesktop/systemd1",
1397 "org.freedesktop.systemd1.Manager",
1401 "ssi", unit
, "all", signo
);
1404 int manager_unit_is_active(Manager
*manager
, const char *unit
) {
1405 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1406 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1407 _cleanup_free_
char *path
= NULL
;
1414 path
= unit_dbus_path_from_name(unit
);
1418 r
= sd_bus_get_property(
1420 "org.freedesktop.systemd1",
1422 "org.freedesktop.systemd1.Unit",
1428 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
1429 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
1432 if (sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
) ||
1433 sd_bus_error_has_name(&error
, BUS_ERROR_LOAD_FAILED
))
1439 r
= sd_bus_message_read(reply
, "s", &state
);
1443 return !STR_IN_SET(state
, "inactive", "failed");
1446 int manager_job_is_active(Manager
*manager
, const char *path
) {
1447 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1448 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1454 r
= sd_bus_get_property(
1456 "org.freedesktop.systemd1",
1458 "org.freedesktop.systemd1.Job",
1464 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
1465 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
1468 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_OBJECT
))
1474 /* We don't actually care about the state really. The fact
1475 * that we could read the job state is enough for us */
1480 int manager_get_machine_by_pid(Manager
*m
, pid_t pid
, Machine
**machine
) {
1488 mm
= hashmap_get(m
->machine_leaders
, UINT_TO_PTR(pid
));
1490 _cleanup_free_
char *unit
= NULL
;
1492 r
= cg_pid_get_unit(pid
, &unit
);
1494 mm
= hashmap_get(m
->machine_units
, unit
);
1503 int manager_add_machine(Manager
*m
, const char *name
, Machine
**_machine
) {
1509 machine
= hashmap_get(m
->machines
, name
);
1511 machine
= machine_new(m
, _MACHINE_CLASS_INVALID
, name
);
1517 *_machine
= machine
;