chiark / gitweb /
3c7d4be8d28d2905c5e5b021598a4d758ace99c0
[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 #include <pwd.h>
26 #include <sys/capability.h>
27
28 #include "sd-id128.h"
29 #include "sd-messages.h"
30 #include "strv.h"
31 #include "mkdir.h"
32 #include "path-util.h"
33 #include "special.h"
34 #include "fileio-label.h"
35 #include "label.h"
36 #include "utf8.h"
37 #include "unit-name.h"
38 #include "bus-util.h"
39 #include "bus-errors.h"
40 #include "time-util.h"
41 #include "cgroup-util.h"
42 #include "machined.h"
43
44 static int method_get_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
45         _cleanup_free_ char *p = NULL;
46         Manager *m = userdata;
47         Machine *machine;
48         const char *name;
49         int r;
50
51         assert(bus);
52         assert(message);
53         assert(m);
54
55         r = sd_bus_message_read(message, "s", &name);
56         if (r < 0)
57                 return r;
58
59         machine = hashmap_get(m->machines, name);
60         if (!machine)
61                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
62
63         p = machine_bus_path(machine);
64         if (!p)
65                 return -ENOMEM;
66
67         return sd_bus_reply_method_return(message, "o", p);
68 }
69
70 static int method_get_machine_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
71         _cleanup_free_ char *p = NULL;
72         Manager *m = userdata;
73         Machine *machine = NULL;
74         pid_t pid;
75         int r;
76
77         assert(bus);
78         assert(message);
79         assert(m);
80
81         assert_cc(sizeof(pid_t) == sizeof(uint32_t));
82
83         r = sd_bus_message_read(message, "u", &pid);
84         if (r < 0)
85                 return r;
86
87         if (pid == 0) {
88                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
89
90                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
91                 if (r < 0)
92                         return r;
93
94                 r = sd_bus_creds_get_pid(creds, &pid);
95                 if (r < 0)
96                         return r;
97         }
98
99         r = manager_get_machine_by_pid(m, pid, &machine);
100         if (r < 0)
101                 return r;
102         if (!machine)
103                 return sd_bus_error_setf(error, BUS_ERROR_NO_MACHINE_FOR_PID, "PID "PID_FMT" does not belong to any known machine", pid);
104
105         p = machine_bus_path(machine);
106         if (!p)
107                 return -ENOMEM;
108
109         return sd_bus_reply_method_return(message, "o", p);
110 }
111
112 static int method_list_machines(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
113         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
114         Manager *m = userdata;
115         Machine *machine;
116         Iterator i;
117         int r;
118
119         assert(bus);
120         assert(message);
121         assert(m);
122
123         r = sd_bus_message_new_method_return(message, &reply);
124         if (r < 0)
125                 return sd_bus_error_set_errno(error, r);
126
127         r = sd_bus_message_open_container(reply, 'a', "(ssso)");
128         if (r < 0)
129                 return sd_bus_error_set_errno(error, r);
130
131         HASHMAP_FOREACH(machine, m->machines, i) {
132                 _cleanup_free_ char *p = NULL;
133
134                 p = machine_bus_path(machine);
135                 if (!p)
136                         return -ENOMEM;
137
138                 r = sd_bus_message_append(reply, "(ssso)",
139                                           machine->name,
140                                           strempty(machine_class_to_string(machine->class)),
141                                           machine->service,
142                                           p);
143                 if (r < 0)
144                         return sd_bus_error_set_errno(error, r);
145         }
146
147         r = sd_bus_message_close_container(reply);
148         if (r < 0)
149                 return sd_bus_error_set_errno(error, r);
150
151         return sd_bus_send(bus, reply, NULL);
152 }
153
154 static int method_create_or_register_machine(Manager *manager, sd_bus_message *message, bool read_network, Machine **_m, sd_bus_error *error) {
155         const char *name, *service, *class, *root_directory;
156         const int32_t *netif = NULL;
157         MachineClass c;
158         uint32_t leader;
159         sd_id128_t id;
160         const void *v;
161         Machine *m;
162         size_t n, n_netif = 0;
163         int r;
164
165         assert(manager);
166         assert(message);
167         assert(_m);
168
169         r = sd_bus_message_read(message, "s", &name);
170         if (r < 0)
171                 return r;
172         if (!machine_name_is_valid(name))
173                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine name");
174
175         r = sd_bus_message_read_array(message, 'y', &v, &n);
176         if (r < 0)
177                 return r;
178         if (n == 0)
179                 id = SD_ID128_NULL;
180         else if (n == 16)
181                 memcpy(&id, v, n);
182         else
183                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine ID parameter");
184
185         r = sd_bus_message_read(message, "ssus", &service, &class, &leader, &root_directory);
186         if (r < 0)
187                 return r;
188
189         if (read_network) {
190                 size_t i;
191
192                 r = sd_bus_message_read_array(message, 'i', (const void**) &netif, &n_netif);
193                 if (r < 0)
194                         return r;
195
196                 n_netif /= sizeof(int32_t);
197
198                 for (i = 0; i < n_netif; i++) {
199                         if (netif[i] <= 0)
200                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid network interface index %i", netif[i]);
201                 }
202         }
203
204         if (isempty(class))
205                 c = _MACHINE_CLASS_INVALID;
206         else {
207                 c = machine_class_from_string(class);
208                 if (c < 0)
209                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid machine class parameter");
210         }
211
212         if (leader == 1)
213                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
214
215         if (!isempty(root_directory) && !path_is_absolute(root_directory))
216                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root directory must be empty or an absolute path");
217
218         if (leader == 0) {
219                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
220
221                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
222                 if (r < 0)
223                         return r;
224
225                 assert_cc(sizeof(uint32_t) == sizeof(pid_t));
226
227                 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
228                 if (r < 0)
229                         return r;
230         }
231
232         if (hashmap_get(manager->machines, name))
233                 return sd_bus_error_setf(error, BUS_ERROR_MACHINE_EXISTS, "Machine '%s' already exists", name);
234
235         r = manager_add_machine(manager, name, &m);
236         if (r < 0)
237                 return r;
238
239         m->leader = leader;
240         m->class = c;
241         m->id = id;
242
243         if (!isempty(service)) {
244                 m->service = strdup(service);
245                 if (!m->service) {
246                         r = -ENOMEM;
247                         goto fail;
248                 }
249         }
250
251         if (!isempty(root_directory)) {
252                 m->root_directory = strdup(root_directory);
253                 if (!m->root_directory) {
254                         r = -ENOMEM;
255                         goto fail;
256                 }
257         }
258
259         if (n_netif > 0) {
260                 assert_cc(sizeof(int32_t) == sizeof(int));
261                 m->netif = memdup(netif, sizeof(int32_t) * n_netif);
262                 if (!m->netif) {
263                         r = -ENOMEM;
264                         goto fail;
265                 }
266
267                 m->n_netif = n_netif;
268         }
269
270         *_m = m;
271
272         return 1;
273
274 fail:
275         machine_add_to_gc_queue(m);
276         return r;
277 }
278
279 static int method_create_machine_internal(sd_bus *bus, sd_bus_message *message, bool read_network, void *userdata, sd_bus_error *error) {
280         Manager *manager = userdata;
281         Machine *m = NULL;
282         int r;
283
284         r = method_create_or_register_machine(manager, message, read_network, &m, error);
285         if (r < 0)
286                 return r;
287
288         r = sd_bus_message_enter_container(message, 'a', "(sv)");
289         if (r < 0)
290                 goto fail;
291
292         r = machine_start(m, message, error);
293         if (r < 0)
294                 goto fail;
295
296         m->create_message = sd_bus_message_ref(message);
297         return 1;
298
299 fail:
300         machine_add_to_gc_queue(m);
301         return r;
302 }
303
304 static int method_create_machine_with_network(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
305         return method_create_machine_internal(bus, message, true, userdata, error);
306 }
307
308 static int method_create_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
309         return method_create_machine_internal(bus, message, false, userdata, error);
310 }
311
312 static int method_register_machine_internal(sd_bus *bus, sd_bus_message *message, bool read_network, void *userdata, sd_bus_error *error) {
313         Manager *manager = userdata;
314         _cleanup_free_ char *p = NULL;
315         Machine *m = NULL;
316         int r;
317
318         r = method_create_or_register_machine(manager, message, read_network, &m, error);
319         if (r < 0)
320                 return r;
321
322         r = cg_pid_get_unit(m->leader, &m->unit);
323         if (r < 0) {
324                 r = sd_bus_error_set_errnof(error, r, "Failed to determine unit of process "PID_FMT" : %s", m->leader, strerror(-r));
325                 goto fail;
326         }
327
328         m->registered = true;
329
330         r = machine_start(m, NULL, error);
331         if (r < 0)
332                 goto fail;
333
334         p = machine_bus_path(m);
335         if (!p) {
336                 r = -ENOMEM;
337                 goto fail;
338         }
339
340         return sd_bus_reply_method_return(message, "o", p);
341
342 fail:
343         machine_add_to_gc_queue(m);
344         return r;
345 }
346
347 static int method_register_machine_with_network(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
348         return method_register_machine_internal(bus, message, true, userdata, error);
349 }
350
351 static int method_register_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
352         return method_register_machine_internal(bus, message, false, userdata, error);
353 }
354
355 static int method_terminate_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
356         Manager *m = userdata;
357         Machine *machine;
358         const char *name;
359         int r;
360
361         assert(bus);
362         assert(message);
363         assert(m);
364
365         r = sd_bus_message_read(message, "s", &name);
366         if (r < 0)
367                 return sd_bus_error_set_errno(error, r);
368
369         machine = hashmap_get(m->machines, name);
370         if (!machine)
371                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
372
373         return bus_machine_method_terminate(bus, message, machine, error);
374 }
375
376 static int method_kill_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
377         Manager *m = userdata;
378         Machine *machine;
379         const char *name;
380         int r;
381
382         assert(bus);
383         assert(message);
384         assert(m);
385
386         r = sd_bus_message_read(message, "s", &name);
387         if (r < 0)
388                 return sd_bus_error_set_errno(error, r);
389
390         machine = hashmap_get(m->machines, name);
391         if (!machine)
392                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
393
394         return bus_machine_method_kill(bus, message, machine, error);
395 }
396
397 static int method_get_machine_addresses(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
398         Manager *m = userdata;
399         Machine *machine;
400         const char *name;
401         int r;
402
403         assert(bus);
404         assert(message);
405         assert(m);
406
407         r = sd_bus_message_read(message, "s", &name);
408         if (r < 0)
409                 return sd_bus_error_set_errno(error, r);
410
411         machine = hashmap_get(m->machines, name);
412         if (!machine)
413                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
414
415         return bus_machine_method_get_addresses(bus, message, machine, error);
416 }
417
418 static int method_get_machine_os_release(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
419         Manager *m = userdata;
420         Machine *machine;
421         const char *name;
422         int r;
423
424         assert(bus);
425         assert(message);
426         assert(m);
427
428         r = sd_bus_message_read(message, "s", &name);
429         if (r < 0)
430                 return sd_bus_error_set_errno(error, r);
431
432         machine = hashmap_get(m->machines, name);
433         if (!machine)
434                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
435
436         return bus_machine_method_get_os_release(bus, message, machine, error);
437 }
438
439 const sd_bus_vtable manager_vtable[] = {
440         SD_BUS_VTABLE_START(0),
441         SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, SD_BUS_VTABLE_UNPRIVILEGED),
442         SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
443         SD_BUS_METHOD("ListMachines", NULL, "a(ssso)", method_list_machines, SD_BUS_VTABLE_UNPRIVILEGED),
444         SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine, 0),
445         SD_BUS_METHOD("RegisterMachine", "sayssus", "o", method_register_machine, 0),
446         SD_BUS_METHOD("CreateMachineWithNetwork", "sayssusaia(sv)", "o", method_create_machine_with_network, 0),
447         SD_BUS_METHOD("RegisterMachineWithNetwork", "sayssusai", "o", method_register_machine_with_network, 0),
448         SD_BUS_METHOD("KillMachine", "ssi", NULL, method_kill_machine, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
449         SD_BUS_METHOD("TerminateMachine", "s", NULL, method_terminate_machine, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)),
450         SD_BUS_METHOD("GetMachineAddresses", "s", "a(iay)", method_get_machine_addresses, SD_BUS_VTABLE_UNPRIVILEGED),
451         SD_BUS_METHOD("GetMachineOSRelease", "s", "a{ss}", method_get_machine_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
452         SD_BUS_SIGNAL("MachineNew", "so", 0),
453         SD_BUS_SIGNAL("MachineRemoved", "so", 0),
454         SD_BUS_VTABLE_END
455 };
456
457 int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
458         const char *path, *result, *unit;
459         Manager *m = userdata;
460         Machine *machine;
461         uint32_t id;
462         int r;
463
464         assert(bus);
465         assert(message);
466         assert(m);
467
468         r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
469         if (r < 0) {
470                 bus_log_parse_error(r);
471                 return r;
472         }
473
474         machine = hashmap_get(m->machine_units, unit);
475         if (!machine)
476                 return 0;
477
478         if (streq_ptr(path, machine->scope_job)) {
479                 free(machine->scope_job);
480                 machine->scope_job = NULL;
481
482                 if (machine->started) {
483                         if (streq(result, "done"))
484                                 machine_send_create_reply(machine, NULL);
485                         else {
486                                 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
487
488                                 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
489
490                                 machine_send_create_reply(machine, &e);
491                         }
492                 } else
493                         machine_save(machine);
494         }
495
496         machine_add_to_gc_queue(machine);
497         return 0;
498 }
499
500 int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
501         _cleanup_free_ char *unit = NULL;
502         Manager *m = userdata;
503         Machine *machine;
504         const char *path;
505         int r;
506
507         assert(bus);
508         assert(message);
509         assert(m);
510
511         path = sd_bus_message_get_path(message);
512         if (!path)
513                 return 0;
514
515         r = unit_name_from_dbus_path(path, &unit);
516         if (r < 0)
517                 return r;
518
519         machine = hashmap_get(m->machine_units, unit);
520         if (machine)
521                 machine_add_to_gc_queue(machine);
522
523         return 0;
524 }
525
526 int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
527         const char *path, *unit;
528         Manager *m = userdata;
529         Machine *machine;
530         int r;
531
532         assert(bus);
533         assert(message);
534         assert(m);
535
536         r = sd_bus_message_read(message, "so", &unit, &path);
537         if (r < 0) {
538                 bus_log_parse_error(r);
539                 return r;
540         }
541
542         machine = hashmap_get(m->machine_units, unit);
543         if (machine)
544                 machine_add_to_gc_queue(machine);
545
546         return 0;
547 }
548
549 int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
550         Manager *m = userdata;
551         Machine *machine;
552         Iterator i;
553         int b, r;
554
555         assert(bus);
556
557         r = sd_bus_message_read(message, "b", &b);
558         if (r < 0) {
559                 bus_log_parse_error(r);
560                 return r;
561         }
562         if (b)
563                 return 0;
564
565         /* systemd finished reloading, let's recheck all our machines */
566         log_debug("System manager has been reloaded, rechecking machines...");
567
568         HASHMAP_FOREACH(machine, m->machines, i)
569                 machine_add_to_gc_queue(machine);
570
571         return 0;
572 }
573
574 int manager_start_scope(
575                 Manager *manager,
576                 const char *scope,
577                 pid_t pid,
578                 const char *slice,
579                 const char *description,
580                 sd_bus_message *more_properties,
581                 sd_bus_error *error,
582                 char **job) {
583
584         _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
585         int r;
586
587         assert(manager);
588         assert(scope);
589         assert(pid > 1);
590
591         r = sd_bus_message_new_method_call(
592                         manager->bus,
593                         &m,
594                         "org.freedesktop.systemd1",
595                         "/org/freedesktop/systemd1",
596                         "org.freedesktop.systemd1.Manager",
597                         "StartTransientUnit");
598         if (r < 0)
599                 return r;
600
601         r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
602         if (r < 0)
603                 return r;
604
605         r = sd_bus_message_open_container(m, 'a', "(sv)");
606         if (r < 0)
607                 return r;
608
609         if (!isempty(slice)) {
610                 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
611                 if (r < 0)
612                         return r;
613         }
614
615         if (!isempty(description)) {
616                 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
617                 if (r < 0)
618                         return r;
619         }
620
621         r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
622         if (r < 0)
623                 return r;
624
625         if (more_properties) {
626                 r = sd_bus_message_copy(m, more_properties, true);
627                 if (r < 0)
628                         return r;
629         }
630
631         r = sd_bus_message_close_container(m);
632         if (r < 0)
633                 return r;
634
635         r = sd_bus_message_append(m, "a(sa(sv))", 0);
636         if (r < 0)
637                 return r;
638
639         r = sd_bus_call(manager->bus, m, 0, error, &reply);
640         if (r < 0)
641                 return r;
642
643         if (job) {
644                 const char *j;
645                 char *copy;
646
647                 r = sd_bus_message_read(reply, "o", &j);
648                 if (r < 0)
649                         return r;
650
651                 copy = strdup(j);
652                 if (!copy)
653                         return -ENOMEM;
654
655                 *job = copy;
656         }
657
658         return 1;
659 }
660
661 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
662         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
663         int r;
664
665         assert(manager);
666         assert(unit);
667
668         r = sd_bus_call_method(
669                         manager->bus,
670                         "org.freedesktop.systemd1",
671                         "/org/freedesktop/systemd1",
672                         "org.freedesktop.systemd1.Manager",
673                         "StopUnit",
674                         error,
675                         &reply,
676                         "ss", unit, "fail");
677         if (r < 0) {
678                 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
679                     sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
680
681                         if (job)
682                                 *job = NULL;
683
684                         sd_bus_error_free(error);
685                         return 0;
686                 }
687
688                 return r;
689         }
690
691         if (job) {
692                 const char *j;
693                 char *copy;
694
695                 r = sd_bus_message_read(reply, "o", &j);
696                 if (r < 0)
697                         return r;
698
699                 copy = strdup(j);
700                 if (!copy)
701                         return -ENOMEM;
702
703                 *job = copy;
704         }
705
706         return 1;
707 }
708
709 int manager_kill_unit(Manager *manager, const char *unit, int signo, sd_bus_error *error) {
710         assert(manager);
711         assert(unit);
712
713         return sd_bus_call_method(
714                         manager->bus,
715                         "org.freedesktop.systemd1",
716                         "/org/freedesktop/systemd1",
717                         "org.freedesktop.systemd1.Manager",
718                         "KillUnit",
719                         error,
720                         NULL,
721                         "ssi", unit, "all", signo);
722 }
723
724 int manager_unit_is_active(Manager *manager, const char *unit) {
725         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
726         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
727         _cleanup_free_ char *path = NULL;
728         const char *state;
729         int r;
730
731         assert(manager);
732         assert(unit);
733
734         path = unit_dbus_path_from_name(unit);
735         if (!path)
736                 return -ENOMEM;
737
738         r = sd_bus_get_property(
739                         manager->bus,
740                         "org.freedesktop.systemd1",
741                         path,
742                         "org.freedesktop.systemd1.Unit",
743                         "ActiveState",
744                         &error,
745                         &reply,
746                         "s");
747         if (r < 0) {
748                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
749                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
750                         return true;
751
752                 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
753                     sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
754                         return false;
755
756                 return r;
757         }
758
759         r = sd_bus_message_read(reply, "s", &state);
760         if (r < 0)
761                 return -EINVAL;
762
763         return !streq(state, "inactive") && !streq(state, "failed");
764 }
765
766 int manager_job_is_active(Manager *manager, const char *path) {
767         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
768         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
769         int r;
770
771         assert(manager);
772         assert(path);
773
774         r = sd_bus_get_property(
775                         manager->bus,
776                         "org.freedesktop.systemd1",
777                         path,
778                         "org.freedesktop.systemd1.Job",
779                         "State",
780                         &error,
781                         &reply,
782                         "s");
783         if (r < 0) {
784                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
785                     sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
786                         return true;
787
788                 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
789                         return false;
790
791                 return r;
792         }
793
794         /* We don't actually care about the state really. The fact
795          * that we could read the job state is enough for us */
796
797         return true;
798 }
799
800 int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
801         _cleanup_free_ char *unit = NULL;
802         Machine *mm;
803         int r;
804
805         assert(m);
806         assert(pid >= 1);
807         assert(machine);
808
809         r = cg_pid_get_unit(pid, &unit);
810         if (r < 0)
811                 mm = hashmap_get(m->machine_leaders, UINT_TO_PTR(pid));
812         else
813                 mm = hashmap_get(m->machine_units, unit);
814
815         if (!mm)
816                 return 0;
817
818         *machine = mm;
819         return 1;
820 }
821
822 int manager_add_machine(Manager *m, const char *name, Machine **_machine) {
823         Machine *machine;
824
825         assert(m);
826         assert(name);
827
828         machine = hashmap_get(m->machines, name);
829         if (!machine) {
830                 machine = machine_new(m, name);
831                 if (!machine)
832                         return -ENOMEM;
833         }
834
835         if (_machine)
836                 *_machine = machine;
837
838         return 0;
839 }