chiark / gitweb /
shared: the btrfs quota field is called "referenced" not "referred"
[elogind.git] / src / machine / machined-dbus.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2011 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <errno.h>
23 #include <string.h>
24 #include <unistd.h>
25
26 #include "sd-id128.h"
27 #include "path-util.h"
28 #include "unit-name.h"
29 #include "bus-util.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"
36 #include "machined.h"
37 #include "machine-dbus.h"
38
39 static int property_get_pool_path(
40                 sd_bus *bus,
41                 const char *path,
42                 const char *interface,
43                 const char *property,
44                 sd_bus_message *reply,
45                 void *userdata,
46                 sd_bus_error *error) {
47
48         assert(bus);
49         assert(reply);
50
51         return sd_bus_message_append(reply, "s", "/var/lib/machines");
52 }
53
54 static int property_get_pool_usage(
55                 sd_bus *bus,
56                 const char *path,
57                 const char *interface,
58                 const char *property,
59                 sd_bus_message *reply,
60                 void *userdata,
61                 sd_bus_error *error) {
62
63         _cleanup_close_ int fd = -1;
64         uint64_t usage = (uint64_t) -1;
65         struct stat st;
66
67         assert(bus);
68         assert(reply);
69
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. */
73
74         fd = open("/var/lib/machines", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
75         if (fd >= 0) {
76                 BtrfsQuotaInfo q;
77
78                 if (btrfs_subvol_get_quota_fd(fd, &q) >= 0)
79                         usage = q.referenced;
80         }
81
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;
85         }
86
87         return sd_bus_message_append(reply, "t", usage);
88 }
89
90 static int property_get_pool_limit(
91                 sd_bus *bus,
92                 const char *path,
93                 const char *interface,
94                 const char *property,
95                 sd_bus_message *reply,
96                 void *userdata,
97                 sd_bus_error *error) {
98
99         _cleanup_close_ int fd = -1;
100         uint64_t size = (uint64_t) -1;
101         struct stat st;
102
103         assert(bus);
104         assert(reply);
105
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. */
109
110         fd = open("/var/lib/machines", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
111         if (fd >= 0) {
112                 BtrfsQuotaInfo q;
113
114                 if (btrfs_subvol_get_quota_fd(fd, &q) >= 0)
115                         size = q.referenced_max;
116         }
117
118         if (stat("/var/lib/machines.raw", &st) >= 0) {
119                 if (size == (uint64_t) -1 || (uint64_t) st.st_size < size)
120                         size = st.st_size;
121         }
122
123         return sd_bus_message_append(reply, "t", size);
124 }
125
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;
129         Machine *machine;
130         const char *name;
131         int r;
132
133         assert(bus);
134         assert(message);
135         assert(m);
136
137         r = sd_bus_message_read(message, "s", &name);
138         if (r < 0)
139                 return r;
140
141         machine = hashmap_get(m->machines, name);
142         if (!machine)
143                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
144
145         p = machine_bus_path(machine);
146         if (!p)
147                 return -ENOMEM;
148
149         return sd_bus_reply_method_return(message, "o", p);
150 }
151
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;
155         const char *name;
156         int r;
157
158         assert(bus);
159         assert(message);
160         assert(m);
161
162         r = sd_bus_message_read(message, "s", &name);
163         if (r < 0)
164                 return r;
165
166         r = image_find(name, NULL);
167         if (r == 0)
168                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
169         if (r < 0)
170                 return r;
171
172         p = image_bus_path(name);
173         if (!p)
174                 return -ENOMEM;
175
176         return sd_bus_reply_method_return(message, "o", p);
177 }
178
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;
183         pid_t pid;
184         int r;
185
186         assert(bus);
187         assert(message);
188         assert(m);
189
190         assert_cc(sizeof(pid_t) == sizeof(uint32_t));
191
192         r = sd_bus_message_read(message, "u", &pid);
193         if (r < 0)
194                 return r;
195
196         if (pid == 0) {
197                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
198
199                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
200                 if (r < 0)
201                         return r;
202
203                 r = sd_bus_creds_get_pid(creds, &pid);
204                 if (r < 0)
205                         return r;
206         }
207
208         r = manager_get_machine_by_pid(m, pid, &machine);
209         if (r < 0)
210                 return r;
211         if (!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);
213
214         p = machine_bus_path(machine);
215         if (!p)
216                 return -ENOMEM;
217
218         return sd_bus_reply_method_return(message, "o", p);
219 }
220
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;
224         Machine *machine;
225         Iterator i;
226         int r;
227
228         assert(bus);
229         assert(message);
230         assert(m);
231
232         r = sd_bus_message_new_method_return(message, &reply);
233         if (r < 0)
234                 return sd_bus_error_set_errno(error, r);
235
236         r = sd_bus_message_open_container(reply, 'a', "(ssso)");
237         if (r < 0)
238                 return sd_bus_error_set_errno(error, r);
239
240         HASHMAP_FOREACH(machine, m->machines, i) {
241                 _cleanup_free_ char *p = NULL;
242
243                 p = machine_bus_path(machine);
244                 if (!p)
245                         return -ENOMEM;
246
247                 r = sd_bus_message_append(reply, "(ssso)",
248                                           machine->name,
249                                           strempty(machine_class_to_string(machine->class)),
250                                           machine->service,
251                                           p);
252                 if (r < 0)
253                         return sd_bus_error_set_errno(error, r);
254         }
255
256         r = sd_bus_message_close_container(reply);
257         if (r < 0)
258                 return sd_bus_error_set_errno(error, r);
259
260         return sd_bus_send(bus, reply, NULL);
261 }
262
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;
266         MachineClass c;
267         uint32_t leader;
268         sd_id128_t id;
269         const void *v;
270         Machine *m;
271         size_t n, n_netif = 0;
272         int r;
273
274         assert(manager);
275         assert(message);
276         assert(_m);
277
278         r = sd_bus_message_read(message, "s", &name);
279         if (r < 0)
280                 return r;
281         if (!machine_name_is_valid(name))
282                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine name");
283
284         r = sd_bus_message_read_array(message, 'y', &v, &n);
285         if (r < 0)
286                 return r;
287         if (n == 0)
288                 id = SD_ID128_NULL;
289         else if (n == 16)
290                 memcpy(&id, v, n);
291         else
292                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine ID parameter");
293
294         r = sd_bus_message_read(message, "ssus", &service, &class, &leader, &root_directory);
295         if (r < 0)
296                 return r;
297
298         if (read_network) {
299                 size_t i;
300
301                 r = sd_bus_message_read_array(message, 'i', (const void**) &netif, &n_netif);
302                 if (r < 0)
303                         return r;
304
305                 n_netif /= sizeof(int32_t);
306
307                 for (i = 0; i < n_netif; i++) {
308                         if (netif[i] <= 0)
309                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid network interface index %i", netif[i]);
310                 }
311         }
312
313         if (isempty(class))
314                 c = _MACHINE_CLASS_INVALID;
315         else {
316                 c = machine_class_from_string(class);
317                 if (c < 0)
318                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine class parameter");
319         }
320
321         if (leader == 1)
322                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
323
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");
326
327         if (leader == 0) {
328                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
329
330                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
331                 if (r < 0)
332                         return r;
333
334                 assert_cc(sizeof(uint32_t) == sizeof(pid_t));
335
336                 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
337                 if (r < 0)
338                         return r;
339         }
340
341         if (hashmap_get(manager->machines, name))
342                 return sd_bus_error_setf(error, BUS_ERROR_MACHINE_EXISTS, "Machine '%s' already exists", name);
343
344         r = manager_add_machine(manager, name, &m);
345         if (r < 0)
346                 return r;
347
348         m->leader = leader;
349         m->class = c;
350         m->id = id;
351
352         if (!isempty(service)) {
353                 m->service = strdup(service);
354                 if (!m->service) {
355                         r = -ENOMEM;
356                         goto fail;
357                 }
358         }
359
360         if (!isempty(root_directory)) {
361                 m->root_directory = strdup(root_directory);
362                 if (!m->root_directory) {
363                         r = -ENOMEM;
364                         goto fail;
365                 }
366         }
367
368         if (n_netif > 0) {
369                 assert_cc(sizeof(int32_t) == sizeof(int));
370                 m->netif = memdup(netif, sizeof(int32_t) * n_netif);
371                 if (!m->netif) {
372                         r = -ENOMEM;
373                         goto fail;
374                 }
375
376                 m->n_netif = n_netif;
377         }
378
379         *_m = m;
380
381         return 1;
382
383 fail:
384         machine_add_to_gc_queue(m);
385         return r;
386 }
387
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;
390         Machine *m = NULL;
391         int r;
392
393         r = method_create_or_register_machine(manager, message, read_network, &m, error);
394         if (r < 0)
395                 return r;
396
397         r = sd_bus_message_enter_container(message, 'a', "(sv)");
398         if (r < 0)
399                 goto fail;
400
401         r = machine_start(m, message, error);
402         if (r < 0)
403                 goto fail;
404
405         m->create_message = sd_bus_message_ref(message);
406         return 1;
407
408 fail:
409         machine_add_to_gc_queue(m);
410         return r;
411 }
412
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);
415 }
416
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);
419 }
420
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;
424         Machine *m = NULL;
425         int r;
426
427         r = method_create_or_register_machine(manager, message, read_network, &m, error);
428         if (r < 0)
429                 return r;
430
431         r = cg_pid_get_unit(m->leader, &m->unit);
432         if (r < 0) {
433                 r = sd_bus_error_set_errnof(error, r, "Failed to determine unit of process "PID_FMT" : %s", m->leader, strerror(-r));
434                 goto fail;
435         }
436
437         r = machine_start(m, NULL, error);
438         if (r < 0)
439                 goto fail;
440
441         p = machine_bus_path(m);
442         if (!p) {
443                 r = -ENOMEM;
444                 goto fail;
445         }
446
447         return sd_bus_reply_method_return(message, "o", p);
448
449 fail:
450         machine_add_to_gc_queue(m);
451         return r;
452 }
453
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);
456 }
457
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);
460 }
461
462 static int method_terminate_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
463         Manager *m = userdata;
464         Machine *machine;
465         const char *name;
466         int r;
467
468         assert(bus);
469         assert(message);
470         assert(m);
471
472         r = sd_bus_message_read(message, "s", &name);
473         if (r < 0)
474                 return sd_bus_error_set_errno(error, r);
475
476         machine = hashmap_get(m->machines, name);
477         if (!machine)
478                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
479
480         return bus_machine_method_terminate(bus, message, machine, error);
481 }
482
483 static int method_kill_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
484         Manager *m = userdata;
485         Machine *machine;
486         const char *name;
487         int r;
488
489         assert(bus);
490         assert(message);
491         assert(m);
492
493         r = sd_bus_message_read(message, "s", &name);
494         if (r < 0)
495                 return sd_bus_error_set_errno(error, r);
496
497         machine = hashmap_get(m->machines, name);
498         if (!machine)
499                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
500
501         return bus_machine_method_kill(bus, message, machine, error);
502 }
503
504 static int method_get_machine_addresses(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
505         Manager *m = userdata;
506         Machine *machine;
507         const char *name;
508         int r;
509
510         assert(bus);
511         assert(message);
512         assert(m);
513
514         r = sd_bus_message_read(message, "s", &name);
515         if (r < 0)
516                 return sd_bus_error_set_errno(error, r);
517
518         machine = hashmap_get(m->machines, name);
519         if (!machine)
520                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
521
522         return bus_machine_method_get_addresses(bus, message, machine, error);
523 }
524
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;
527         Machine *machine;
528         const char *name;
529         int r;
530
531         assert(bus);
532         assert(message);
533         assert(m);
534
535         r = sd_bus_message_read(message, "s", &name);
536         if (r < 0)
537                 return sd_bus_error_set_errno(error, r);
538
539         machine = hashmap_get(m->machines, name);
540         if (!machine)
541                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
542
543         return bus_machine_method_get_os_release(bus, message, machine, error);
544 }
545
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;
550         Image *image;
551         Iterator i;
552         int r;
553
554         assert(bus);
555         assert(message);
556         assert(m);
557
558         images = hashmap_new(&string_hash_ops);
559         if (!images)
560                 return -ENOMEM;
561
562         r = image_discover(images);
563         if (r < 0)
564                 return r;
565
566         r = sd_bus_message_new_method_return(message, &reply);
567         if (r < 0)
568                 return r;
569
570         r = sd_bus_message_open_container(reply, 'a', "(ssbttto)");
571         if (r < 0)
572                 return r;
573
574         HASHMAP_FOREACH(image, images, i) {
575                 _cleanup_free_ char *p = NULL;
576
577                 p = image_bus_path(image->name);
578                 if (!p)
579                         return -ENOMEM;
580
581                 r = sd_bus_message_append(reply, "(ssbttto)",
582                                           image->name,
583                                           image_type_to_string(image->type),
584                                           image->read_only,
585                                           image->crtime,
586                                           image->mtime,
587                                           image->usage,
588                                           p);
589                 if (r < 0)
590                         return r;
591         }
592
593         r = sd_bus_message_close_container(reply);
594         if (r < 0)
595                 return r;
596
597         return sd_bus_send(bus, reply, NULL);
598 }
599
600 static int method_open_machine_pty(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
601         Manager *m = userdata;
602         Machine *machine;
603         const char *name;
604         int r;
605
606         assert(bus);
607         assert(message);
608         assert(m);
609
610         r = sd_bus_message_read(message, "s", &name);
611         if (r < 0)
612                 return sd_bus_error_set_errno(error, r);
613
614         machine = hashmap_get(m->machines, name);
615         if (!machine)
616                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
617
618         return bus_machine_method_open_pty(bus, message, machine, error);
619 }
620
621 static int method_open_machine_login(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
622         Manager *m = userdata;
623         Machine *machine;
624         const char *name;
625         int r;
626
627         assert(bus);
628         assert(message);
629         assert(m);
630
631         r = sd_bus_message_read(message, "s", &name);
632         if (r < 0)
633                 return r;
634
635         machine = hashmap_get(m->machines, name);
636         if (!machine)
637                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
638
639         return bus_machine_method_open_login(bus, message, machine, error);
640 }
641
642 static int method_bind_mount_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
643         Manager *m = userdata;
644         Machine *machine;
645         const char *name;
646         int r;
647
648         assert(bus);
649         assert(message);
650         assert(m);
651
652         r = sd_bus_message_read(message, "s", &name);
653         if (r < 0)
654                 return r;
655
656         machine = hashmap_get(m->machines, name);
657         if (!machine)
658                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
659
660         return bus_machine_method_bind_mount(bus, message, machine, error);
661 }
662
663 static int method_copy_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
664         Manager *m = userdata;
665         Machine *machine;
666         const char *name;
667         int r;
668
669         assert(bus);
670         assert(message);
671         assert(m);
672
673         r = sd_bus_message_read(message, "s", &name);
674         if (r < 0)
675                 return r;
676
677         machine = hashmap_get(m->machines, name);
678         if (!machine)
679                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
680
681         return bus_machine_method_copy(bus, message, machine, error);
682 }
683
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;
686         const char *name;
687         int r;
688
689         assert(bus);
690         assert(message);
691
692         r = sd_bus_message_read(message, "s", &name);
693         if (r < 0)
694                 return r;
695
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);
698
699         r = image_find(name, &i);
700         if (r < 0)
701                 return r;
702         if (r == 0)
703                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
704
705         i->userdata = userdata;
706         return bus_image_method_remove(bus, message, i, error);
707 }
708
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;
712         int r;
713
714         assert(bus);
715         assert(message);
716
717         r = sd_bus_message_read(message, "s", &old_name);
718         if (r < 0)
719                 return r;
720
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);
723
724         r = image_find(old_name, &i);
725         if (r < 0)
726                 return r;
727         if (r == 0)
728                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", old_name);
729
730         i->userdata = userdata;
731         return bus_image_method_rename(bus, message, i, error);
732 }
733
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;
737         int r;
738
739         assert(bus);
740         r = sd_bus_message_read(message, "s", &old_name);
741         if (r < 0)
742                 return r;
743
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);
746
747         r = image_find(old_name, &i);
748         if (r < 0)
749                 return r;
750         if (r == 0)
751                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", old_name);
752
753         i->userdata = userdata;
754         return bus_image_method_clone(bus, message, i, error);
755 }
756
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;
759         const char *name;
760         int r;
761
762         assert(bus);
763         r = sd_bus_message_read(message, "s", &name);
764         if (r < 0)
765                 return r;
766
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);
769
770         r = image_find(name, &i);
771         if (r < 0)
772                 return r;
773         if (r == 0)
774                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
775
776         i->userdata = userdata;
777         return bus_image_method_mark_read_only(bus, message, i, error);
778 }
779
780 static int method_set_pool_limit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
781         Manager *m = userdata;
782         uint64_t limit;
783         int r;
784
785         assert(bus);
786         r = sd_bus_message_read(message, "t", &limit);
787         if (r < 0)
788                 return r;
789
790         r = bus_verify_polkit_async(
791                         message,
792                         CAP_SYS_ADMIN,
793                         "org.freedesktop.machine1.manage-machines",
794                         false,
795                         UID_INVALID,
796                         &m->polkit_registry,
797                         error);
798         if (r < 0)
799                 return r;
800         if (r == 0)
801                 return 1; /* Will call us back */
802
803         /* Set up the machine directory if necessary */
804         r = setup_machine_directory(limit, error);
805         if (r < 0)
806                 return r;
807
808         r = btrfs_resize_loopback("/var/lib/machines", limit, false);
809         if (r == -ENOTTY)
810                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs.");
811         if (r < 0 && r != -ENODEV) /* ignore ENODEV, as that's what is returned if the file system is not on loopback */
812                 return sd_bus_error_set_errnof(error, r, "Failed to adjust loopback limit: %m");
813
814         r = btrfs_quota_limit("/var/lib/machines", limit);
815         if (r == -ENOTTY)
816                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Quota is only supported on btrfs.");
817         if (r < 0)
818                 return sd_bus_error_set_errnof(error, r, "Failed to adjust quota limit: %m");
819
820         return sd_bus_reply_method_return(message, NULL);
821 }
822
823 static int method_set_image_limit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
824         _cleanup_(image_unrefp) Image *i = NULL;
825         const char *name;
826         int r;
827
828         assert(bus);
829         r = sd_bus_message_read(message, "s", &name);
830         if (r < 0)
831                 return r;
832
833         if (!image_name_is_valid(name))
834                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
835
836         r = image_find(name, &i);
837         if (r < 0)
838                 return r;
839         if (r == 0)
840                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
841
842         i->userdata = userdata;
843         return bus_image_method_set_limit(bus, message, i, error);
844 }
845
846 const sd_bus_vtable manager_vtable[] = {
847         SD_BUS_VTABLE_START(0),
848         SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path, 0, 0),
849         SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage, 0, 0),
850         SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit, 0, 0),
851         SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, SD_BUS_VTABLE_UNPRIVILEGED),
852         SD_BUS_METHOD("GetImage", "s", "o", method_get_image, SD_BUS_VTABLE_UNPRIVILEGED),
853         SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
854         SD_BUS_METHOD("ListMachines", NULL, "a(ssso)", method_list_machines, SD_BUS_VTABLE_UNPRIVILEGED),
855         SD_BUS_METHOD("ListImages", NULL, "a(ssbttto)", method_list_images, SD_BUS_VTABLE_UNPRIVILEGED),
856         SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine, 0),
857         SD_BUS_METHOD("CreateMachineWithNetwork", "sayssusaia(sv)", "o", method_create_machine_with_network, 0),
858         SD_BUS_METHOD("RegisterMachine", "sayssus", "o", method_register_machine, 0),
859         SD_BUS_METHOD("RegisterMachineWithNetwork", "sayssusai", "o", method_register_machine_with_network, 0),
860         SD_BUS_METHOD("TerminateMachine", "s", NULL, method_terminate_machine, SD_BUS_VTABLE_UNPRIVILEGED),
861         SD_BUS_METHOD("KillMachine", "ssi", NULL, method_kill_machine, SD_BUS_VTABLE_UNPRIVILEGED),
862         SD_BUS_METHOD("GetMachineAddresses", "s", "a(iay)", method_get_machine_addresses, SD_BUS_VTABLE_UNPRIVILEGED),
863         SD_BUS_METHOD("GetMachineOSRelease", "s", "a{ss}", method_get_machine_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
864         SD_BUS_METHOD("OpenMachinePTY", "s", "hs", method_open_machine_pty, 0),
865         SD_BUS_METHOD("OpenMachineLogin", "s", "hs", method_open_machine_login, SD_BUS_VTABLE_UNPRIVILEGED),
866         SD_BUS_METHOD("BindMountMachine", "sssbb", NULL, method_bind_mount_machine, SD_BUS_VTABLE_UNPRIVILEGED),
867         SD_BUS_METHOD("CopyFromMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED),
868         SD_BUS_METHOD("CopyToMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED),
869         SD_BUS_METHOD("RemoveImage", "s", NULL, method_remove_image, SD_BUS_VTABLE_UNPRIVILEGED),
870         SD_BUS_METHOD("RenameImage", "ss", NULL, method_rename_image, SD_BUS_VTABLE_UNPRIVILEGED),
871         SD_BUS_METHOD("CloneImage", "ssb", NULL, method_clone_image, SD_BUS_VTABLE_UNPRIVILEGED),
872         SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL, method_mark_image_read_only, SD_BUS_VTABLE_UNPRIVILEGED),
873         SD_BUS_METHOD("SetPoolLimit", "t", NULL, method_set_pool_limit, SD_BUS_VTABLE_UNPRIVILEGED),
874         SD_BUS_METHOD("SetImageLimit", "st", NULL, method_set_image_limit, SD_BUS_VTABLE_UNPRIVILEGED),
875         SD_BUS_SIGNAL("MachineNew", "so", 0),
876         SD_BUS_SIGNAL("MachineRemoved", "so", 0),
877         SD_BUS_VTABLE_END
878 };
879
880 int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
881         const char *path, *result, *unit;
882         Manager *m = userdata;
883         Machine *machine;
884         uint32_t id;
885         int r;
886
887         assert(bus);
888         assert(message);
889         assert(m);
890
891         r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
892         if (r < 0) {
893                 bus_log_parse_error(r);
894                 return r;
895         }
896
897         machine = hashmap_get(m->machine_units, unit);
898         if (!machine)
899                 return 0;
900
901         if (streq_ptr(path, machine->scope_job)) {
902                 free(machine->scope_job);
903                 machine->scope_job = NULL;
904
905                 if (machine->started) {
906                         if (streq(result, "done"))
907                                 machine_send_create_reply(machine, NULL);
908                         else {
909                                 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
910
911                                 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
912
913                                 machine_send_create_reply(machine, &e);
914                         }
915                 } else
916                         machine_save(machine);
917         }
918
919         machine_add_to_gc_queue(machine);
920         return 0;
921 }
922
923 int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
924         _cleanup_free_ char *unit = NULL;
925         Manager *m = userdata;
926         Machine *machine;
927         const char *path;
928         int r;
929
930         assert(bus);
931         assert(message);
932         assert(m);
933
934         path = sd_bus_message_get_path(message);
935         if (!path)
936                 return 0;
937
938         r = unit_name_from_dbus_path(path, &unit);
939         if (r == -EINVAL) /* not for a unit */
940                 return 0;
941         if (r < 0)
942                 return r;
943
944         machine = hashmap_get(m->machine_units, unit);
945         if (machine)
946                 machine_add_to_gc_queue(machine);
947
948         return 0;
949 }
950
951 int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
952         const char *path, *unit;
953         Manager *m = userdata;
954         Machine *machine;
955         int r;
956
957         assert(bus);
958         assert(message);
959         assert(m);
960
961         r = sd_bus_message_read(message, "so", &unit, &path);
962         if (r < 0) {
963                 bus_log_parse_error(r);
964                 return r;
965         }
966
967         machine = hashmap_get(m->machine_units, unit);
968         if (machine)
969                 machine_add_to_gc_queue(machine);
970
971         return 0;
972 }
973
974 int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
975         Manager *m = userdata;
976         Machine *machine;
977         Iterator i;
978         int b, r;
979
980         assert(bus);
981
982         r = sd_bus_message_read(message, "b", &b);
983         if (r < 0) {
984                 bus_log_parse_error(r);
985                 return r;
986         }
987         if (b)
988                 return 0;
989
990         /* systemd finished reloading, let's recheck all our machines */
991         log_debug("System manager has been reloaded, rechecking machines...");
992
993         HASHMAP_FOREACH(machine, m->machines, i)
994                 machine_add_to_gc_queue(machine);
995
996         return 0;
997 }
998
999 int manager_start_scope(
1000                 Manager *manager,
1001                 const char *scope,
1002                 pid_t pid,
1003                 const char *slice,
1004                 const char *description,
1005                 sd_bus_message *more_properties,
1006                 sd_bus_error *error,
1007                 char **job) {
1008
1009         _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
1010         int r;
1011
1012         assert(manager);
1013         assert(scope);
1014         assert(pid > 1);
1015
1016         r = sd_bus_message_new_method_call(
1017                         manager->bus,
1018                         &m,
1019                         "org.freedesktop.systemd1",
1020                         "/org/freedesktop/systemd1",
1021                         "org.freedesktop.systemd1.Manager",
1022                         "StartTransientUnit");
1023         if (r < 0)
1024                 return r;
1025
1026         r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
1027         if (r < 0)
1028                 return r;
1029
1030         r = sd_bus_message_open_container(m, 'a', "(sv)");
1031         if (r < 0)
1032                 return r;
1033
1034         if (!isempty(slice)) {
1035                 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
1036                 if (r < 0)
1037                         return r;
1038         }
1039
1040         if (!isempty(description)) {
1041                 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
1042                 if (r < 0)
1043                         return r;
1044         }
1045
1046         r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
1047         if (r < 0)
1048                 return r;
1049
1050         r = sd_bus_message_append(m, "(sv)", "Delegate", "b", 1);
1051         if (r < 0)
1052                 return r;
1053
1054         if (more_properties) {
1055                 r = sd_bus_message_copy(m, more_properties, true);
1056                 if (r < 0)
1057                         return r;
1058         }
1059
1060         r = sd_bus_message_close_container(m);
1061         if (r < 0)
1062                 return r;
1063
1064         r = sd_bus_message_append(m, "a(sa(sv))", 0);
1065         if (r < 0)
1066                 return r;
1067
1068         r = sd_bus_call(manager->bus, m, 0, error, &reply);
1069         if (r < 0)
1070                 return r;
1071
1072         if (job) {
1073                 const char *j;
1074                 char *copy;
1075
1076                 r = sd_bus_message_read(reply, "o", &j);
1077                 if (r < 0)
1078                         return r;
1079
1080                 copy = strdup(j);
1081                 if (!copy)
1082                         return -ENOMEM;
1083
1084                 *job = copy;
1085         }
1086
1087         return 1;
1088 }
1089
1090 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
1091         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1092         int r;
1093
1094         assert(manager);
1095         assert(unit);
1096
1097         r = sd_bus_call_method(
1098                         manager->bus,
1099                         "org.freedesktop.systemd1",
1100                         "/org/freedesktop/systemd1",
1101                         "org.freedesktop.systemd1.Manager",
1102                         "StopUnit",
1103                         error,
1104                         &reply,
1105                         "ss", unit, "fail");
1106         if (r < 0) {
1107                 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
1108                     sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
1109
1110                         if (job)
1111                                 *job = NULL;
1112
1113                         sd_bus_error_free(error);
1114                         return 0;
1115                 }
1116
1117                 return r;
1118         }
1119
1120         if (job) {
1121                 const char *j;
1122                 char *copy;
1123
1124                 r = sd_bus_message_read(reply, "o", &j);
1125                 if (r < 0)
1126                         return r;
1127
1128                 copy = strdup(j);
1129                 if (!copy)
1130                         return -ENOMEM;
1131
1132                 *job = copy;
1133         }
1134
1135         return 1;
1136 }
1137
1138 int manager_kill_unit(Manager *manager, const char *unit, int signo, sd_bus_error *error) {
1139         assert(manager);
1140         assert(unit);
1141
1142         return sd_bus_call_method(
1143                         manager->bus,
1144                         "org.freedesktop.systemd1",
1145                         "/org/freedesktop/systemd1",
1146                         "org.freedesktop.systemd1.Manager",
1147                         "KillUnit",
1148                         error,
1149                         NULL,
1150                         "ssi", unit, "all", signo);
1151 }
1152
1153 int manager_unit_is_active(Manager *manager, const char *unit) {
1154         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1155         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1156         _cleanup_free_ char *path = NULL;
1157         const char *state;
1158         int r;
1159
1160         assert(manager);
1161         assert(unit);
1162
1163         path = unit_dbus_path_from_name(unit);
1164         if (!path)
1165                 return -ENOMEM;
1166
1167         r = sd_bus_get_property(
1168                         manager->bus,
1169                         "org.freedesktop.systemd1",
1170                         path,
1171                         "org.freedesktop.systemd1.Unit",
1172                         "ActiveState",
1173                         &error,
1174                         &reply,
1175                         "s");
1176         if (r < 0) {
1177                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
1178                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
1179                         return true;
1180
1181                 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
1182                     sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
1183                         return false;
1184
1185                 return r;
1186         }
1187
1188         r = sd_bus_message_read(reply, "s", &state);
1189         if (r < 0)
1190                 return -EINVAL;
1191
1192         return !streq(state, "inactive") && !streq(state, "failed");
1193 }
1194
1195 int manager_job_is_active(Manager *manager, const char *path) {
1196         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1197         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1198         int r;
1199
1200         assert(manager);
1201         assert(path);
1202
1203         r = sd_bus_get_property(
1204                         manager->bus,
1205                         "org.freedesktop.systemd1",
1206                         path,
1207                         "org.freedesktop.systemd1.Job",
1208                         "State",
1209                         &error,
1210                         &reply,
1211                         "s");
1212         if (r < 0) {
1213                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
1214                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
1215                         return true;
1216
1217                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
1218                         return false;
1219
1220                 return r;
1221         }
1222
1223         /* We don't actually care about the state really. The fact
1224          * that we could read the job state is enough for us */
1225
1226         return true;
1227 }
1228
1229 int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
1230         _cleanup_free_ char *unit = NULL;
1231         Machine *mm;
1232         int r;
1233
1234         assert(m);
1235         assert(pid >= 1);
1236         assert(machine);
1237
1238         r = cg_pid_get_unit(pid, &unit);
1239         if (r < 0)
1240                 mm = hashmap_get(m->machine_leaders, UINT_TO_PTR(pid));
1241         else
1242                 mm = hashmap_get(m->machine_units, unit);
1243
1244         if (!mm)
1245                 return 0;
1246
1247         *machine = mm;
1248         return 1;
1249 }
1250
1251 int manager_add_machine(Manager *m, const char *name, Machine **_machine) {
1252         Machine *machine;
1253
1254         assert(m);
1255         assert(name);
1256
1257         machine = hashmap_get(m->machines, name);
1258         if (!machine) {
1259                 machine = machine_new(m, name);
1260                 if (!machine)
1261                         return -ENOMEM;
1262         }
1263
1264         if (_machine)
1265                 *_machine = machine;
1266
1267         return 0;
1268 }