chiark / gitweb /
remove unused includes
[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 "machine-image.h"
33 #include "image-dbus.h"
34 #include "machined.h"
35 #include "machine-dbus.h"
36
37 static int method_get_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
38         _cleanup_free_ char *p = NULL;
39         Manager *m = userdata;
40         Machine *machine;
41         const char *name;
42         int r;
43
44         assert(bus);
45         assert(message);
46         assert(m);
47
48         r = sd_bus_message_read(message, "s", &name);
49         if (r < 0)
50                 return r;
51
52         machine = hashmap_get(m->machines, name);
53         if (!machine)
54                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
55
56         p = machine_bus_path(machine);
57         if (!p)
58                 return -ENOMEM;
59
60         return sd_bus_reply_method_return(message, "o", p);
61 }
62
63 static int method_get_image(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
64         _cleanup_free_ char *p = NULL;
65         Manager *m = userdata;
66         const char *name;
67         int r;
68
69         assert(bus);
70         assert(message);
71         assert(m);
72
73         r = sd_bus_message_read(message, "s", &name);
74         if (r < 0)
75                 return r;
76
77         r = image_find(name, NULL);
78         if (r == 0)
79                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
80         if (r < 0)
81                 return r;
82
83         p = image_bus_path(name);
84         if (!p)
85                 return -ENOMEM;
86
87         return sd_bus_reply_method_return(message, "o", p);
88 }
89
90 static int method_get_machine_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
91         _cleanup_free_ char *p = NULL;
92         Manager *m = userdata;
93         Machine *machine = NULL;
94         pid_t pid;
95         int r;
96
97         assert(bus);
98         assert(message);
99         assert(m);
100
101         assert_cc(sizeof(pid_t) == sizeof(uint32_t));
102
103         r = sd_bus_message_read(message, "u", &pid);
104         if (r < 0)
105                 return r;
106
107         if (pid == 0) {
108                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
109
110                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
111                 if (r < 0)
112                         return r;
113
114                 r = sd_bus_creds_get_pid(creds, &pid);
115                 if (r < 0)
116                         return r;
117         }
118
119         r = manager_get_machine_by_pid(m, pid, &machine);
120         if (r < 0)
121                 return r;
122         if (!machine)
123                 return sd_bus_error_setf(error, BUS_ERROR_NO_MACHINE_FOR_PID, "PID "PID_FMT" does not belong to any known machine", pid);
124
125         p = machine_bus_path(machine);
126         if (!p)
127                 return -ENOMEM;
128
129         return sd_bus_reply_method_return(message, "o", p);
130 }
131
132 static int method_list_machines(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
133         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
134         Manager *m = userdata;
135         Machine *machine;
136         Iterator i;
137         int r;
138
139         assert(bus);
140         assert(message);
141         assert(m);
142
143         r = sd_bus_message_new_method_return(message, &reply);
144         if (r < 0)
145                 return sd_bus_error_set_errno(error, r);
146
147         r = sd_bus_message_open_container(reply, 'a', "(ssso)");
148         if (r < 0)
149                 return sd_bus_error_set_errno(error, r);
150
151         HASHMAP_FOREACH(machine, m->machines, i) {
152                 _cleanup_free_ char *p = NULL;
153
154                 p = machine_bus_path(machine);
155                 if (!p)
156                         return -ENOMEM;
157
158                 r = sd_bus_message_append(reply, "(ssso)",
159                                           machine->name,
160                                           strempty(machine_class_to_string(machine->class)),
161                                           machine->service,
162                                           p);
163                 if (r < 0)
164                         return sd_bus_error_set_errno(error, r);
165         }
166
167         r = sd_bus_message_close_container(reply);
168         if (r < 0)
169                 return sd_bus_error_set_errno(error, r);
170
171         return sd_bus_send(bus, reply, NULL);
172 }
173
174 static int method_create_or_register_machine(Manager *manager, sd_bus_message *message, bool read_network, Machine **_m, sd_bus_error *error) {
175         const char *name, *service, *class, *root_directory;
176         const int32_t *netif = NULL;
177         MachineClass c;
178         uint32_t leader;
179         sd_id128_t id;
180         const void *v;
181         Machine *m;
182         size_t n, n_netif = 0;
183         int r;
184
185         assert(manager);
186         assert(message);
187         assert(_m);
188
189         r = sd_bus_message_read(message, "s", &name);
190         if (r < 0)
191                 return r;
192         if (!machine_name_is_valid(name))
193                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine name");
194
195         r = sd_bus_message_read_array(message, 'y', &v, &n);
196         if (r < 0)
197                 return r;
198         if (n == 0)
199                 id = SD_ID128_NULL;
200         else if (n == 16)
201                 memcpy(&id, v, n);
202         else
203                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine ID parameter");
204
205         r = sd_bus_message_read(message, "ssus", &service, &class, &leader, &root_directory);
206         if (r < 0)
207                 return r;
208
209         if (read_network) {
210                 size_t i;
211
212                 r = sd_bus_message_read_array(message, 'i', (const void**) &netif, &n_netif);
213                 if (r < 0)
214                         return r;
215
216                 n_netif /= sizeof(int32_t);
217
218                 for (i = 0; i < n_netif; i++) {
219                         if (netif[i] <= 0)
220                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid network interface index %i", netif[i]);
221                 }
222         }
223
224         if (isempty(class))
225                 c = _MACHINE_CLASS_INVALID;
226         else {
227                 c = machine_class_from_string(class);
228                 if (c < 0)
229                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine class parameter");
230         }
231
232         if (leader == 1)
233                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
234
235         if (!isempty(root_directory) && !path_is_absolute(root_directory))
236                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root directory must be empty or an absolute path");
237
238         if (leader == 0) {
239                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
240
241                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
242                 if (r < 0)
243                         return r;
244
245                 assert_cc(sizeof(uint32_t) == sizeof(pid_t));
246
247                 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
248                 if (r < 0)
249                         return r;
250         }
251
252         if (hashmap_get(manager->machines, name))
253                 return sd_bus_error_setf(error, BUS_ERROR_MACHINE_EXISTS, "Machine '%s' already exists", name);
254
255         r = manager_add_machine(manager, name, &m);
256         if (r < 0)
257                 return r;
258
259         m->leader = leader;
260         m->class = c;
261         m->id = id;
262
263         if (!isempty(service)) {
264                 m->service = strdup(service);
265                 if (!m->service) {
266                         r = -ENOMEM;
267                         goto fail;
268                 }
269         }
270
271         if (!isempty(root_directory)) {
272                 m->root_directory = strdup(root_directory);
273                 if (!m->root_directory) {
274                         r = -ENOMEM;
275                         goto fail;
276                 }
277         }
278
279         if (n_netif > 0) {
280                 assert_cc(sizeof(int32_t) == sizeof(int));
281                 m->netif = memdup(netif, sizeof(int32_t) * n_netif);
282                 if (!m->netif) {
283                         r = -ENOMEM;
284                         goto fail;
285                 }
286
287                 m->n_netif = n_netif;
288         }
289
290         *_m = m;
291
292         return 1;
293
294 fail:
295         machine_add_to_gc_queue(m);
296         return r;
297 }
298
299 static int method_create_machine_internal(sd_bus *bus, sd_bus_message *message, bool read_network, void *userdata, sd_bus_error *error) {
300         Manager *manager = userdata;
301         Machine *m = NULL;
302         int r;
303
304         r = method_create_or_register_machine(manager, message, read_network, &m, error);
305         if (r < 0)
306                 return r;
307
308         r = sd_bus_message_enter_container(message, 'a', "(sv)");
309         if (r < 0)
310                 goto fail;
311
312         r = machine_start(m, message, error);
313         if (r < 0)
314                 goto fail;
315
316         m->create_message = sd_bus_message_ref(message);
317         return 1;
318
319 fail:
320         machine_add_to_gc_queue(m);
321         return r;
322 }
323
324 static int method_create_machine_with_network(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
325         return method_create_machine_internal(bus, message, true, userdata, error);
326 }
327
328 static int method_create_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
329         return method_create_machine_internal(bus, message, false, userdata, error);
330 }
331
332 static int method_register_machine_internal(sd_bus *bus, sd_bus_message *message, bool read_network, void *userdata, sd_bus_error *error) {
333         Manager *manager = userdata;
334         _cleanup_free_ char *p = NULL;
335         Machine *m = NULL;
336         int r;
337
338         r = method_create_or_register_machine(manager, message, read_network, &m, error);
339         if (r < 0)
340                 return r;
341
342         r = cg_pid_get_unit(m->leader, &m->unit);
343         if (r < 0) {
344                 r = sd_bus_error_set_errnof(error, r, "Failed to determine unit of process "PID_FMT" : %s", m->leader, strerror(-r));
345                 goto fail;
346         }
347
348         r = machine_start(m, NULL, error);
349         if (r < 0)
350                 goto fail;
351
352         p = machine_bus_path(m);
353         if (!p) {
354                 r = -ENOMEM;
355                 goto fail;
356         }
357
358         return sd_bus_reply_method_return(message, "o", p);
359
360 fail:
361         machine_add_to_gc_queue(m);
362         return r;
363 }
364
365 static int method_register_machine_with_network(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
366         return method_register_machine_internal(bus, message, true, userdata, error);
367 }
368
369 static int method_register_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
370         return method_register_machine_internal(bus, message, false, userdata, error);
371 }
372
373 static int method_terminate_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
374         Manager *m = userdata;
375         Machine *machine;
376         const char *name;
377         int r;
378
379         assert(bus);
380         assert(message);
381         assert(m);
382
383         r = sd_bus_message_read(message, "s", &name);
384         if (r < 0)
385                 return sd_bus_error_set_errno(error, r);
386
387         machine = hashmap_get(m->machines, name);
388         if (!machine)
389                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
390
391         return bus_machine_method_terminate(bus, message, machine, error);
392 }
393
394 static int method_kill_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
395         Manager *m = userdata;
396         Machine *machine;
397         const char *name;
398         int r;
399
400         assert(bus);
401         assert(message);
402         assert(m);
403
404         r = sd_bus_message_read(message, "s", &name);
405         if (r < 0)
406                 return sd_bus_error_set_errno(error, r);
407
408         machine = hashmap_get(m->machines, name);
409         if (!machine)
410                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
411
412         return bus_machine_method_kill(bus, message, machine, error);
413 }
414
415 static int method_get_machine_addresses(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
416         Manager *m = userdata;
417         Machine *machine;
418         const char *name;
419         int r;
420
421         assert(bus);
422         assert(message);
423         assert(m);
424
425         r = sd_bus_message_read(message, "s", &name);
426         if (r < 0)
427                 return sd_bus_error_set_errno(error, r);
428
429         machine = hashmap_get(m->machines, name);
430         if (!machine)
431                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
432
433         return bus_machine_method_get_addresses(bus, message, machine, error);
434 }
435
436 static int method_get_machine_os_release(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
437         Manager *m = userdata;
438         Machine *machine;
439         const char *name;
440         int r;
441
442         assert(bus);
443         assert(message);
444         assert(m);
445
446         r = sd_bus_message_read(message, "s", &name);
447         if (r < 0)
448                 return sd_bus_error_set_errno(error, r);
449
450         machine = hashmap_get(m->machines, name);
451         if (!machine)
452                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
453
454         return bus_machine_method_get_os_release(bus, message, machine, error);
455 }
456
457 static int method_list_images(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
458         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
459         _cleanup_(image_hashmap_freep) Hashmap *images = NULL;
460         Manager *m = userdata;
461         Image *image;
462         Iterator i;
463         int r;
464
465         assert(bus);
466         assert(message);
467         assert(m);
468
469         images = hashmap_new(&string_hash_ops);
470         if (!images)
471                 return -ENOMEM;
472
473         r = image_discover(images);
474         if (r < 0)
475                 return r;
476
477         r = sd_bus_message_new_method_return(message, &reply);
478         if (r < 0)
479                 return r;
480
481         r = sd_bus_message_open_container(reply, 'a', "(ssbttto)");
482         if (r < 0)
483                 return r;
484
485         HASHMAP_FOREACH(image, images, i) {
486                 _cleanup_free_ char *p = NULL;
487
488                 p = image_bus_path(image->name);
489                 if (!p)
490                         return -ENOMEM;
491
492                 r = sd_bus_message_append(reply, "(ssbttto)",
493                                           image->name,
494                                           image_type_to_string(image->type),
495                                           image->read_only,
496                                           image->crtime,
497                                           image->mtime,
498                                           image->usage,
499                                           p);
500                 if (r < 0)
501                         return r;
502         }
503
504         r = sd_bus_message_close_container(reply);
505         if (r < 0)
506                 return r;
507
508         return sd_bus_send(bus, reply, NULL);
509 }
510
511 static int method_open_machine_pty(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
512         Manager *m = userdata;
513         Machine *machine;
514         const char *name;
515         int r;
516
517         assert(bus);
518         assert(message);
519         assert(m);
520
521         r = sd_bus_message_read(message, "s", &name);
522         if (r < 0)
523                 return sd_bus_error_set_errno(error, r);
524
525         machine = hashmap_get(m->machines, name);
526         if (!machine)
527                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
528
529         return bus_machine_method_open_pty(bus, message, machine, error);
530 }
531
532 static int method_open_machine_login(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
533         Manager *m = userdata;
534         Machine *machine;
535         const char *name;
536         int r;
537
538         assert(bus);
539         assert(message);
540         assert(m);
541
542         r = sd_bus_message_read(message, "s", &name);
543         if (r < 0)
544                 return r;
545
546         machine = hashmap_get(m->machines, name);
547         if (!machine)
548                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
549
550         return bus_machine_method_open_login(bus, message, machine, error);
551 }
552
553 static int method_bind_mount_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
554         Manager *m = userdata;
555         Machine *machine;
556         const char *name;
557         int r;
558
559         assert(bus);
560         assert(message);
561         assert(m);
562
563         r = sd_bus_message_read(message, "s", &name);
564         if (r < 0)
565                 return r;
566
567         machine = hashmap_get(m->machines, name);
568         if (!machine)
569                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
570
571         return bus_machine_method_bind_mount(bus, message, machine, error);
572 }
573
574 static int method_copy_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
575         Manager *m = userdata;
576         Machine *machine;
577         const char *name;
578         int r;
579
580         assert(bus);
581         assert(message);
582         assert(m);
583
584         r = sd_bus_message_read(message, "s", &name);
585         if (r < 0)
586                 return r;
587
588         machine = hashmap_get(m->machines, name);
589         if (!machine)
590                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
591
592         return bus_machine_method_copy(bus, message, machine, error);
593 }
594
595 static int method_remove_image(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
596         _cleanup_(image_unrefp) Image* i = NULL;
597         const char *name;
598         int r;
599
600         assert(bus);
601         assert(message);
602
603         r = sd_bus_message_read(message, "s", &name);
604         if (r < 0)
605                 return r;
606
607         if (!image_name_is_valid(name))
608                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
609
610         r = image_find(name, &i);
611         if (r < 0)
612                 return r;
613         if (r == 0)
614                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
615
616         i->userdata = userdata;
617         return bus_image_method_remove(bus, message, i, error);
618 }
619
620 static int method_rename_image(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
621         _cleanup_(image_unrefp) Image* i = NULL;
622         const char *old_name;
623         int r;
624
625         assert(bus);
626         assert(message);
627
628         r = sd_bus_message_read(message, "s", &old_name);
629         if (r < 0)
630                 return r;
631
632         if (!image_name_is_valid(old_name))
633                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", old_name);
634
635         r = image_find(old_name, &i);
636         if (r < 0)
637                 return r;
638         if (r == 0)
639                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", old_name);
640
641         i->userdata = userdata;
642         return bus_image_method_rename(bus, message, i, error);
643 }
644
645 static int method_clone_image(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
646         _cleanup_(image_unrefp) Image *i = NULL;
647         const char *old_name;
648         int r;
649
650         assert(bus);
651         r = sd_bus_message_read(message, "s", &old_name);
652         if (r < 0)
653                 return r;
654
655         if (!image_name_is_valid(old_name))
656                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", old_name);
657
658         r = image_find(old_name, &i);
659         if (r < 0)
660                 return r;
661         if (r == 0)
662                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", old_name);
663
664         i->userdata = userdata;
665         return bus_image_method_clone(bus, message, i, error);
666 }
667
668 static int method_mark_image_read_only(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
669         _cleanup_(image_unrefp) Image *i = NULL;
670         const char *name;
671         int r;
672
673         assert(bus);
674         r = sd_bus_message_read(message, "s", &name);
675         if (r < 0)
676                 return r;
677
678         if (!image_name_is_valid(name))
679                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image name '%s' is invalid.", name);
680
681         r = image_find(name, &i);
682         if (r < 0)
683                 return r;
684         if (r == 0)
685                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_IMAGE, "No image '%s' known", name);
686
687         i->userdata = userdata;
688         return bus_image_method_mark_read_only(bus, message, i, error);
689 }
690
691 const sd_bus_vtable manager_vtable[] = {
692         SD_BUS_VTABLE_START(0),
693         SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, SD_BUS_VTABLE_UNPRIVILEGED),
694         SD_BUS_METHOD("GetImage", "s", "o", method_get_image, SD_BUS_VTABLE_UNPRIVILEGED),
695         SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
696         SD_BUS_METHOD("ListMachines", NULL, "a(ssso)", method_list_machines, SD_BUS_VTABLE_UNPRIVILEGED),
697         SD_BUS_METHOD("ListImages", NULL, "a(ssbttto)", method_list_images, SD_BUS_VTABLE_UNPRIVILEGED),
698         SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine, 0),
699         SD_BUS_METHOD("CreateMachineWithNetwork", "sayssusaia(sv)", "o", method_create_machine_with_network, 0),
700         SD_BUS_METHOD("RegisterMachine", "sayssus", "o", method_register_machine, 0),
701         SD_BUS_METHOD("RegisterMachineWithNetwork", "sayssusai", "o", method_register_machine_with_network, 0),
702         SD_BUS_METHOD("TerminateMachine", "s", NULL, method_terminate_machine, SD_BUS_VTABLE_UNPRIVILEGED),
703         SD_BUS_METHOD("KillMachine", "ssi", NULL, method_kill_machine, SD_BUS_VTABLE_UNPRIVILEGED),
704         SD_BUS_METHOD("GetMachineAddresses", "s", "a(iay)", method_get_machine_addresses, SD_BUS_VTABLE_UNPRIVILEGED),
705         SD_BUS_METHOD("GetMachineOSRelease", "s", "a{ss}", method_get_machine_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
706         SD_BUS_METHOD("OpenMachinePTY", "s", "hs", method_open_machine_pty, 0),
707         SD_BUS_METHOD("OpenMachineLogin", "s", "hs", method_open_machine_login, SD_BUS_VTABLE_UNPRIVILEGED),
708         SD_BUS_METHOD("BindMountMachine", "sssbb", NULL, method_bind_mount_machine, SD_BUS_VTABLE_UNPRIVILEGED),
709         SD_BUS_METHOD("CopyFromMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED),
710         SD_BUS_METHOD("CopyToMachine", "sss", NULL, method_copy_machine, SD_BUS_VTABLE_UNPRIVILEGED),
711         SD_BUS_METHOD("RemoveImage", "s", NULL, method_remove_image, SD_BUS_VTABLE_UNPRIVILEGED),
712         SD_BUS_METHOD("RenameImage", "ss", NULL, method_rename_image, SD_BUS_VTABLE_UNPRIVILEGED),
713         SD_BUS_METHOD("CloneImage", "ssb", NULL, method_clone_image, SD_BUS_VTABLE_UNPRIVILEGED),
714         SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL, method_mark_image_read_only, SD_BUS_VTABLE_UNPRIVILEGED),
715         SD_BUS_SIGNAL("MachineNew", "so", 0),
716         SD_BUS_SIGNAL("MachineRemoved", "so", 0),
717         SD_BUS_VTABLE_END
718 };
719
720 int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
721         const char *path, *result, *unit;
722         Manager *m = userdata;
723         Machine *machine;
724         uint32_t id;
725         int r;
726
727         assert(bus);
728         assert(message);
729         assert(m);
730
731         r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
732         if (r < 0) {
733                 bus_log_parse_error(r);
734                 return r;
735         }
736
737         machine = hashmap_get(m->machine_units, unit);
738         if (!machine)
739                 return 0;
740
741         if (streq_ptr(path, machine->scope_job)) {
742                 free(machine->scope_job);
743                 machine->scope_job = NULL;
744
745                 if (machine->started) {
746                         if (streq(result, "done"))
747                                 machine_send_create_reply(machine, NULL);
748                         else {
749                                 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
750
751                                 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
752
753                                 machine_send_create_reply(machine, &e);
754                         }
755                 } else
756                         machine_save(machine);
757         }
758
759         machine_add_to_gc_queue(machine);
760         return 0;
761 }
762
763 int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
764         _cleanup_free_ char *unit = NULL;
765         Manager *m = userdata;
766         Machine *machine;
767         const char *path;
768         int r;
769
770         assert(bus);
771         assert(message);
772         assert(m);
773
774         path = sd_bus_message_get_path(message);
775         if (!path)
776                 return 0;
777
778         r = unit_name_from_dbus_path(path, &unit);
779         if (r == -EINVAL) /* not for a unit */
780                 return 0;
781         if (r < 0)
782                 return r;
783
784         machine = hashmap_get(m->machine_units, unit);
785         if (machine)
786                 machine_add_to_gc_queue(machine);
787
788         return 0;
789 }
790
791 int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
792         const char *path, *unit;
793         Manager *m = userdata;
794         Machine *machine;
795         int r;
796
797         assert(bus);
798         assert(message);
799         assert(m);
800
801         r = sd_bus_message_read(message, "so", &unit, &path);
802         if (r < 0) {
803                 bus_log_parse_error(r);
804                 return r;
805         }
806
807         machine = hashmap_get(m->machine_units, unit);
808         if (machine)
809                 machine_add_to_gc_queue(machine);
810
811         return 0;
812 }
813
814 int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
815         Manager *m = userdata;
816         Machine *machine;
817         Iterator i;
818         int b, r;
819
820         assert(bus);
821
822         r = sd_bus_message_read(message, "b", &b);
823         if (r < 0) {
824                 bus_log_parse_error(r);
825                 return r;
826         }
827         if (b)
828                 return 0;
829
830         /* systemd finished reloading, let's recheck all our machines */
831         log_debug("System manager has been reloaded, rechecking machines...");
832
833         HASHMAP_FOREACH(machine, m->machines, i)
834                 machine_add_to_gc_queue(machine);
835
836         return 0;
837 }
838
839 int manager_start_scope(
840                 Manager *manager,
841                 const char *scope,
842                 pid_t pid,
843                 const char *slice,
844                 const char *description,
845                 sd_bus_message *more_properties,
846                 sd_bus_error *error,
847                 char **job) {
848
849         _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
850         int r;
851
852         assert(manager);
853         assert(scope);
854         assert(pid > 1);
855
856         r = sd_bus_message_new_method_call(
857                         manager->bus,
858                         &m,
859                         "org.freedesktop.systemd1",
860                         "/org/freedesktop/systemd1",
861                         "org.freedesktop.systemd1.Manager",
862                         "StartTransientUnit");
863         if (r < 0)
864                 return r;
865
866         r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
867         if (r < 0)
868                 return r;
869
870         r = sd_bus_message_open_container(m, 'a', "(sv)");
871         if (r < 0)
872                 return r;
873
874         if (!isempty(slice)) {
875                 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
876                 if (r < 0)
877                         return r;
878         }
879
880         if (!isempty(description)) {
881                 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
882                 if (r < 0)
883                         return r;
884         }
885
886         r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
887         if (r < 0)
888                 return r;
889
890         r = sd_bus_message_append(m, "(sv)", "Delegate", "b", 1);
891         if (r < 0)
892                 return r;
893
894         if (more_properties) {
895                 r = sd_bus_message_copy(m, more_properties, true);
896                 if (r < 0)
897                         return r;
898         }
899
900         r = sd_bus_message_close_container(m);
901         if (r < 0)
902                 return r;
903
904         r = sd_bus_message_append(m, "a(sa(sv))", 0);
905         if (r < 0)
906                 return r;
907
908         r = sd_bus_call(manager->bus, m, 0, error, &reply);
909         if (r < 0)
910                 return r;
911
912         if (job) {
913                 const char *j;
914                 char *copy;
915
916                 r = sd_bus_message_read(reply, "o", &j);
917                 if (r < 0)
918                         return r;
919
920                 copy = strdup(j);
921                 if (!copy)
922                         return -ENOMEM;
923
924                 *job = copy;
925         }
926
927         return 1;
928 }
929
930 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
931         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
932         int r;
933
934         assert(manager);
935         assert(unit);
936
937         r = sd_bus_call_method(
938                         manager->bus,
939                         "org.freedesktop.systemd1",
940                         "/org/freedesktop/systemd1",
941                         "org.freedesktop.systemd1.Manager",
942                         "StopUnit",
943                         error,
944                         &reply,
945                         "ss", unit, "fail");
946         if (r < 0) {
947                 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
948                     sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
949
950                         if (job)
951                                 *job = NULL;
952
953                         sd_bus_error_free(error);
954                         return 0;
955                 }
956
957                 return r;
958         }
959
960         if (job) {
961                 const char *j;
962                 char *copy;
963
964                 r = sd_bus_message_read(reply, "o", &j);
965                 if (r < 0)
966                         return r;
967
968                 copy = strdup(j);
969                 if (!copy)
970                         return -ENOMEM;
971
972                 *job = copy;
973         }
974
975         return 1;
976 }
977
978 int manager_kill_unit(Manager *manager, const char *unit, int signo, sd_bus_error *error) {
979         assert(manager);
980         assert(unit);
981
982         return sd_bus_call_method(
983                         manager->bus,
984                         "org.freedesktop.systemd1",
985                         "/org/freedesktop/systemd1",
986                         "org.freedesktop.systemd1.Manager",
987                         "KillUnit",
988                         error,
989                         NULL,
990                         "ssi", unit, "all", signo);
991 }
992
993 int manager_unit_is_active(Manager *manager, const char *unit) {
994         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
995         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
996         _cleanup_free_ char *path = NULL;
997         const char *state;
998         int r;
999
1000         assert(manager);
1001         assert(unit);
1002
1003         path = unit_dbus_path_from_name(unit);
1004         if (!path)
1005                 return -ENOMEM;
1006
1007         r = sd_bus_get_property(
1008                         manager->bus,
1009                         "org.freedesktop.systemd1",
1010                         path,
1011                         "org.freedesktop.systemd1.Unit",
1012                         "ActiveState",
1013                         &error,
1014                         &reply,
1015                         "s");
1016         if (r < 0) {
1017                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
1018                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
1019                         return true;
1020
1021                 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
1022                     sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
1023                         return false;
1024
1025                 return r;
1026         }
1027
1028         r = sd_bus_message_read(reply, "s", &state);
1029         if (r < 0)
1030                 return -EINVAL;
1031
1032         return !streq(state, "inactive") && !streq(state, "failed");
1033 }
1034
1035 int manager_job_is_active(Manager *manager, const char *path) {
1036         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1037         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1038         int r;
1039
1040         assert(manager);
1041         assert(path);
1042
1043         r = sd_bus_get_property(
1044                         manager->bus,
1045                         "org.freedesktop.systemd1",
1046                         path,
1047                         "org.freedesktop.systemd1.Job",
1048                         "State",
1049                         &error,
1050                         &reply,
1051                         "s");
1052         if (r < 0) {
1053                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
1054                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
1055                         return true;
1056
1057                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
1058                         return false;
1059
1060                 return r;
1061         }
1062
1063         /* We don't actually care about the state really. The fact
1064          * that we could read the job state is enough for us */
1065
1066         return true;
1067 }
1068
1069 int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
1070         _cleanup_free_ char *unit = NULL;
1071         Machine *mm;
1072         int r;
1073
1074         assert(m);
1075         assert(pid >= 1);
1076         assert(machine);
1077
1078         r = cg_pid_get_unit(pid, &unit);
1079         if (r < 0)
1080                 mm = hashmap_get(m->machine_leaders, UINT_TO_PTR(pid));
1081         else
1082                 mm = hashmap_get(m->machine_units, unit);
1083
1084         if (!mm)
1085                 return 0;
1086
1087         *machine = mm;
1088         return 1;
1089 }
1090
1091 int manager_add_machine(Manager *m, const char *name, Machine **_machine) {
1092         Machine *machine;
1093
1094         assert(m);
1095         assert(name);
1096
1097         machine = hashmap_get(m->machines, name);
1098         if (!machine) {
1099                 machine = machine_new(m, name);
1100                 if (!machine)
1101                         return -ENOMEM;
1102         }
1103
1104         if (_machine)
1105                 *_machine = machine;
1106
1107         return 0;
1108 }