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_subtree_quota_fd(fd
, 0, &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_subtree_quota_fd(fd
, 0, &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",
821 return 1; /* Will call us back */
823 /* Set up the machine directory if necessary */
824 r
= setup_machine_directory(limit
, error
);
828 r
= btrfs_resize_loopback("/var/lib/machines", limit
, false);
830 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Quota is only supported on btrfs.");
831 if (r
< 0 && r
!= -ENODEV
) /* ignore ENODEV, as that's what is returned if the file system is not on loopback */
832 return sd_bus_error_set_errnof(error
, r
, "Failed to adjust loopback limit: %m");
834 (void) btrfs_qgroup_set_limit("/var/lib/machines", 0, limit
);
836 r
= btrfs_subvol_set_subtree_quota_limit("/var/lib/machines", 0, limit
);
838 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Quota is only supported on btrfs.");
840 return sd_bus_error_set_errnof(error
, r
, "Failed to adjust quota limit: %m");
842 return sd_bus_reply_method_return(message
, NULL
);
845 static int method_set_image_limit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
846 _cleanup_(image_unrefp
) Image
*i
= NULL
;
852 r
= sd_bus_message_read(message
, "s", &name
);
856 if (!image_name_is_valid(name
))
857 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", name
);
859 r
= image_find(name
, &i
);
863 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
865 i
->userdata
= userdata
;
866 return bus_image_method_set_limit(message
, i
, error
);
869 static int method_map_from_machine_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
870 _cleanup_fclose_
FILE *f
= NULL
;
871 Manager
*m
= userdata
;
872 const char *name
, *p
;
877 r
= sd_bus_message_read(message
, "su", &name
, &uid
);
881 if (!uid_is_valid(uid
))
882 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
884 machine
= hashmap_get(m
->machines
, name
);
886 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
888 if (machine
->class != MACHINE_CONTAINER
)
889 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Not supported for non-container machines.");
891 p
= procfs_file_alloca(machine
->leader
, "uid_map");
897 uid_t uid_base
, uid_shift
, uid_range
, converted
;
901 k
= fscanf(f
, UID_FMT
" " UID_FMT
" " UID_FMT
, &uid_base
, &uid_shift
, &uid_range
);
902 if (k
< 0 && feof(f
))
905 if (ferror(f
) && errno
!= 0)
911 if (uid
< uid_base
|| uid
>= uid_base
+ uid_range
)
914 converted
= uid
- uid_base
+ uid_shift
;
915 if (!uid_is_valid(converted
))
916 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
918 return sd_bus_reply_method_return(message
, "u", (uint32_t) converted
);
921 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "Machine '%s' has no matching user mappings.", name
);
924 static int method_map_to_machine_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
925 Manager
*m
= userdata
;
931 r
= sd_bus_message_read(message
, "u", &uid
);
934 if (!uid_is_valid(uid
))
935 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
937 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "User " UID_FMT
" belongs to host UID range", uid
);
939 HASHMAP_FOREACH(machine
, m
->machines
, i
) {
940 _cleanup_fclose_
FILE *f
= NULL
;
941 char p
[strlen("/proc//uid_map") + DECIMAL_STR_MAX(pid_t
) + 1];
943 if (machine
->class != MACHINE_CONTAINER
)
946 xsprintf(p
, "/proc/" UID_FMT
"/uid_map", machine
->leader
);
949 log_warning_errno(errno
, "Failed top open %s, ignoring,", p
);
954 _cleanup_free_
char *o
= NULL
;
955 uid_t uid_base
, uid_shift
, uid_range
, converted
;
959 k
= fscanf(f
, UID_FMT
" " UID_FMT
" " UID_FMT
, &uid_base
, &uid_shift
, &uid_range
);
960 if (k
< 0 && feof(f
))
963 if (ferror(f
) && errno
!= 0)
969 if (uid
< uid_shift
|| uid
>= uid_shift
+ uid_range
)
972 converted
= (uid
- uid_shift
+ uid_base
);
973 if (!uid_is_valid(converted
))
974 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
976 o
= machine_bus_path(machine
);
980 return sd_bus_reply_method_return(message
, "sou", machine
->name
, o
, (uint32_t) converted
);
984 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "No matching user mapping for " UID_FMT
".", uid
);
987 static int method_map_from_machine_group(sd_bus_message
*message
, void *groupdata
, sd_bus_error
*error
) {
988 _cleanup_fclose_
FILE *f
= NULL
;
989 Manager
*m
= groupdata
;
990 const char *name
, *p
;
995 r
= sd_bus_message_read(message
, "su", &name
, &gid
);
999 if (!gid_is_valid(gid
))
1000 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1002 machine
= hashmap_get(m
->machines
, name
);
1004 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
1006 if (machine
->class != MACHINE_CONTAINER
)
1007 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Not supported for non-container machines.");
1009 p
= procfs_file_alloca(machine
->leader
, "gid_map");
1015 gid_t gid_base
, gid_shift
, gid_range
, converted
;
1019 k
= fscanf(f
, GID_FMT
" " GID_FMT
" " GID_FMT
, &gid_base
, &gid_shift
, &gid_range
);
1020 if (k
< 0 && feof(f
))
1023 if (ferror(f
) && errno
!= 0)
1029 if (gid
< gid_base
|| gid
>= gid_base
+ gid_range
)
1032 converted
= gid
- gid_base
+ gid_shift
;
1033 if (!gid_is_valid(converted
))
1034 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1036 return sd_bus_reply_method_return(message
, "u", (uint32_t) converted
);
1039 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
, "Machine '%s' has no matching group mappings.", name
);
1042 static int method_map_to_machine_group(sd_bus_message
*message
, void *groupdata
, sd_bus_error
*error
) {
1043 Manager
*m
= groupdata
;
1049 r
= sd_bus_message_read(message
, "u", &gid
);
1052 if (!gid_is_valid(gid
))
1053 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1055 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
, "Group " GID_FMT
" belongs to host GID range", gid
);
1057 HASHMAP_FOREACH(machine
, m
->machines
, i
) {
1058 _cleanup_fclose_
FILE *f
= NULL
;
1059 char p
[strlen("/proc//gid_map") + DECIMAL_STR_MAX(pid_t
) + 1];
1061 if (machine
->class != MACHINE_CONTAINER
)
1064 xsprintf(p
, "/proc/" GID_FMT
"/gid_map", machine
->leader
);
1067 log_warning_errno(errno
, "Failed top open %s, ignoring,", p
);
1072 _cleanup_free_
char *o
= NULL
;
1073 gid_t gid_base
, gid_shift
, gid_range
, converted
;
1077 k
= fscanf(f
, GID_FMT
" " GID_FMT
" " GID_FMT
, &gid_base
, &gid_shift
, &gid_range
);
1078 if (k
< 0 && feof(f
))
1081 if (ferror(f
) && errno
!= 0)
1087 if (gid
< gid_shift
|| gid
>= gid_shift
+ gid_range
)
1090 converted
= (gid
- gid_shift
+ gid_base
);
1091 if (!gid_is_valid(converted
))
1092 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1094 o
= machine_bus_path(machine
);
1098 return sd_bus_reply_method_return(message
, "sou", machine
->name
, o
, (uint32_t) converted
);
1102 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
, "No matching group mapping for " GID_FMT
".", gid
);
1105 const sd_bus_vtable manager_vtable
[] = {
1106 SD_BUS_VTABLE_START(0),
1107 SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path
, 0, 0),
1108 SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage
, 0, 0),
1109 SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit
, 0, 0),
1110 SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1111 SD_BUS_METHOD("GetImage", "s", "o", method_get_image
, SD_BUS_VTABLE_UNPRIVILEGED
),
1112 SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid
, SD_BUS_VTABLE_UNPRIVILEGED
),
1113 SD_BUS_METHOD("ListMachines", NULL
, "a(ssso)", method_list_machines
, SD_BUS_VTABLE_UNPRIVILEGED
),
1114 SD_BUS_METHOD("ListImages", NULL
, "a(ssbttto)", method_list_images
, SD_BUS_VTABLE_UNPRIVILEGED
),
1115 SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine
, 0),
1116 SD_BUS_METHOD("CreateMachineWithNetwork", "sayssusaia(sv)", "o", method_create_machine_with_network
, 0),
1117 SD_BUS_METHOD("RegisterMachine", "sayssus", "o", method_register_machine
, 0),
1118 SD_BUS_METHOD("RegisterMachineWithNetwork", "sayssusai", "o", method_register_machine_with_network
, 0),
1119 SD_BUS_METHOD("TerminateMachine", "s", NULL
, method_terminate_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1120 SD_BUS_METHOD("KillMachine", "ssi", NULL
, method_kill_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1121 SD_BUS_METHOD("GetMachineAddresses", "s", "a(iay)", method_get_machine_addresses
, SD_BUS_VTABLE_UNPRIVILEGED
),
1122 SD_BUS_METHOD("GetMachineOSRelease", "s", "a{ss}", method_get_machine_os_release
, SD_BUS_VTABLE_UNPRIVILEGED
),
1123 SD_BUS_METHOD("OpenMachinePTY", "s", "hs", method_open_machine_pty
, 0),
1124 SD_BUS_METHOD("OpenMachineLogin", "s", "hs", method_open_machine_login
, SD_BUS_VTABLE_UNPRIVILEGED
),
1125 SD_BUS_METHOD("OpenMachineShell", "sssasas", "hs", method_open_machine_shell
, SD_BUS_VTABLE_UNPRIVILEGED
),
1126 SD_BUS_METHOD("BindMountMachine", "sssbb", NULL
, method_bind_mount_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1127 SD_BUS_METHOD("CopyFromMachine", "sss", NULL
, method_copy_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1128 SD_BUS_METHOD("CopyToMachine", "sss", NULL
, method_copy_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1129 SD_BUS_METHOD("RemoveImage", "s", NULL
, method_remove_image
, SD_BUS_VTABLE_UNPRIVILEGED
),
1130 SD_BUS_METHOD("RenameImage", "ss", NULL
, method_rename_image
, SD_BUS_VTABLE_UNPRIVILEGED
),
1131 SD_BUS_METHOD("CloneImage", "ssb", NULL
, method_clone_image
, SD_BUS_VTABLE_UNPRIVILEGED
),
1132 SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL
, method_mark_image_read_only
, SD_BUS_VTABLE_UNPRIVILEGED
),
1133 SD_BUS_METHOD("SetPoolLimit", "t", NULL
, method_set_pool_limit
, SD_BUS_VTABLE_UNPRIVILEGED
),
1134 SD_BUS_METHOD("SetImageLimit", "st", NULL
, method_set_image_limit
, SD_BUS_VTABLE_UNPRIVILEGED
),
1135 SD_BUS_METHOD("MapFromMachineUser", "su", "u", method_map_from_machine_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
1136 SD_BUS_METHOD("MapToMachineUser", "u", "sou", method_map_to_machine_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
1137 SD_BUS_METHOD("MapFromMachineGroup", "su", "u", method_map_from_machine_group
, SD_BUS_VTABLE_UNPRIVILEGED
),
1138 SD_BUS_METHOD("MapToMachineGroup", "u", "sou", method_map_to_machine_group
, SD_BUS_VTABLE_UNPRIVILEGED
),
1139 SD_BUS_SIGNAL("MachineNew", "so", 0),
1140 SD_BUS_SIGNAL("MachineRemoved", "so", 0),
1144 int match_job_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1145 const char *path
, *result
, *unit
;
1146 Manager
*m
= userdata
;
1154 r
= sd_bus_message_read(message
, "uoss", &id
, &path
, &unit
, &result
);
1156 bus_log_parse_error(r
);
1160 machine
= hashmap_get(m
->machine_units
, unit
);
1164 if (streq_ptr(path
, machine
->scope_job
)) {
1165 machine
->scope_job
= mfree(machine
->scope_job
);
1167 if (machine
->started
) {
1168 if (streq(result
, "done"))
1169 machine_send_create_reply(machine
, NULL
);
1171 _cleanup_bus_error_free_ sd_bus_error e
= SD_BUS_ERROR_NULL
;
1173 sd_bus_error_setf(&e
, BUS_ERROR_JOB_FAILED
, "Start job for unit %s failed with '%s'", unit
, result
);
1175 machine_send_create_reply(machine
, &e
);
1179 machine_save(machine
);
1182 machine_add_to_gc_queue(machine
);
1186 int match_properties_changed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1187 _cleanup_free_
char *unit
= NULL
;
1189 Manager
*m
= userdata
;
1196 path
= sd_bus_message_get_path(message
);
1200 r
= unit_name_from_dbus_path(path
, &unit
);
1201 if (r
== -EINVAL
) /* not for a unit */
1208 machine
= hashmap_get(m
->machine_units
, unit
);
1212 machine_add_to_gc_queue(machine
);
1216 int match_unit_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1217 const char *path
, *unit
;
1218 Manager
*m
= userdata
;
1225 r
= sd_bus_message_read(message
, "so", &unit
, &path
);
1227 bus_log_parse_error(r
);
1231 machine
= hashmap_get(m
->machine_units
, unit
);
1235 machine_add_to_gc_queue(machine
);
1239 int match_reloading(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1240 Manager
*m
= userdata
;
1248 r
= sd_bus_message_read(message
, "b", &b
);
1250 bus_log_parse_error(r
);
1256 /* systemd finished reloading, let's recheck all our machines */
1257 log_debug("System manager has been reloaded, rechecking machines...");
1259 HASHMAP_FOREACH(machine
, m
->machines
, i
)
1260 machine_add_to_gc_queue(machine
);
1265 int manager_start_scope(
1270 const char *description
,
1271 sd_bus_message
*more_properties
,
1272 sd_bus_error
*error
,
1275 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
, *reply
= NULL
;
1282 r
= sd_bus_message_new_method_call(
1285 "org.freedesktop.systemd1",
1286 "/org/freedesktop/systemd1",
1287 "org.freedesktop.systemd1.Manager",
1288 "StartTransientUnit");
1292 r
= sd_bus_message_append(m
, "ss", strempty(scope
), "fail");
1296 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
1300 if (!isempty(slice
)) {
1301 r
= sd_bus_message_append(m
, "(sv)", "Slice", "s", slice
);
1306 if (!isempty(description
)) {
1307 r
= sd_bus_message_append(m
, "(sv)", "Description", "s", description
);
1312 r
= sd_bus_message_append(m
, "(sv)", "PIDs", "au", 1, pid
);
1316 r
= sd_bus_message_append(m
, "(sv)", "Delegate", "b", 1);
1320 if (more_properties
) {
1321 r
= sd_bus_message_copy(m
, more_properties
, true);
1326 r
= sd_bus_message_close_container(m
);
1330 r
= sd_bus_message_append(m
, "a(sa(sv))", 0);
1334 r
= sd_bus_call(manager
->bus
, m
, 0, error
, &reply
);
1342 r
= sd_bus_message_read(reply
, "o", &j
);
1356 int manager_stop_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
1357 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1363 r
= sd_bus_call_method(
1365 "org.freedesktop.systemd1",
1366 "/org/freedesktop/systemd1",
1367 "org.freedesktop.systemd1.Manager",
1371 "ss", unit
, "fail");
1373 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) ||
1374 sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
)) {
1379 sd_bus_error_free(error
);
1390 r
= sd_bus_message_read(reply
, "o", &j
);
1404 int manager_kill_unit(Manager
*manager
, const char *unit
, int signo
, sd_bus_error
*error
) {
1408 return sd_bus_call_method(
1410 "org.freedesktop.systemd1",
1411 "/org/freedesktop/systemd1",
1412 "org.freedesktop.systemd1.Manager",
1416 "ssi", unit
, "all", signo
);
1419 int manager_unit_is_active(Manager
*manager
, const char *unit
) {
1420 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1421 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1422 _cleanup_free_
char *path
= NULL
;
1429 path
= unit_dbus_path_from_name(unit
);
1433 r
= sd_bus_get_property(
1435 "org.freedesktop.systemd1",
1437 "org.freedesktop.systemd1.Unit",
1443 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
1444 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
1447 if (sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
) ||
1448 sd_bus_error_has_name(&error
, BUS_ERROR_LOAD_FAILED
))
1454 r
= sd_bus_message_read(reply
, "s", &state
);
1458 return !STR_IN_SET(state
, "inactive", "failed");
1461 int manager_job_is_active(Manager
*manager
, const char *path
) {
1462 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1463 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1469 r
= sd_bus_get_property(
1471 "org.freedesktop.systemd1",
1473 "org.freedesktop.systemd1.Job",
1479 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
1480 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
1483 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_OBJECT
))
1489 /* We don't actually care about the state really. The fact
1490 * that we could read the job state is enough for us */
1495 int manager_get_machine_by_pid(Manager
*m
, pid_t pid
, Machine
**machine
) {
1503 mm
= hashmap_get(m
->machine_leaders
, UINT_TO_PTR(pid
));
1505 _cleanup_free_
char *unit
= NULL
;
1507 r
= cg_pid_get_unit(pid
, &unit
);
1509 mm
= hashmap_get(m
->machine_units
, unit
);
1518 int manager_add_machine(Manager
*m
, const char *name
, Machine
**_machine
) {
1524 machine
= hashmap_get(m
->machines
, name
);
1526 machine
= machine_new(m
, _MACHINE_CLASS_INVALID
, name
);
1532 *_machine
= machine
;