]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/machine/machined.c
Bug #944: Deletion of unnecessary checks before a few calls of systemd functions
[thirdparty/systemd.git] / src / machine / machined.c
CommitLineData
1ee306e1
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 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>
1ee306e1
LP
23#include <string.h>
24#include <unistd.h>
1ee306e1 25
c3350683 26#include "sd-daemon.h"
c3350683 27#include "cgroup-util.h"
c3350683
LP
28#include "bus-util.h"
29#include "bus-error.h"
c34255bd 30#include "label.h"
24882e06
LP
31#include "formats-util.h"
32#include "signal-util.h"
1ddb263d 33#include "machine-image.h"
ebeccf9e 34#include "machined.h"
1ee306e1
LP
35
36Manager *manager_new(void) {
37 Manager *m;
c3350683 38 int r;
1ee306e1
LP
39
40 m = new0(Manager, 1);
41 if (!m)
42 return NULL;
43
d5099efc
MS
44 m->machines = hashmap_new(&string_hash_ops);
45 m->machine_units = hashmap_new(&string_hash_ops);
46 m->machine_leaders = hashmap_new(NULL);
1ee306e1 47
d3e84ddb 48 if (!m->machines || !m->machine_units || !m->machine_leaders) {
c3350683
LP
49 manager_free(m);
50 return NULL;
51 }
52
afc6adb5 53 r = sd_event_default(&m->event);
a658cafa 54 if (r < 0) {
1ee306e1
LP
55 manager_free(m);
56 return NULL;
57 }
58
cde93897
LP
59 sd_event_set_watchdog(m->event, true);
60
1ee306e1
LP
61 return m;
62}
63
64void manager_free(Manager *m) {
65 Machine *machine;
1ddb263d 66 Image *i;
1ee306e1
LP
67
68 assert(m);
69
70 while ((machine = hashmap_first(m->machines)))
71 machine_free(machine);
72
73 hashmap_free(m->machines);
74 hashmap_free(m->machine_units);
d3e84ddb 75 hashmap_free(m->machine_leaders);
1ee306e1 76
1ddb263d
LP
77 while ((i = hashmap_steal_first(m->image_cache)))
78 image_unref(i);
79
80 hashmap_free(m->image_cache);
81
82 sd_event_source_unref(m->image_cache_defer_event);
83
d04c1fb8
LP
84 bus_verify_polkit_async_registry_free(m->polkit_registry);
85
c3350683
LP
86 sd_bus_unref(m->bus);
87 sd_event_unref(m->event);
88
89 free(m);
90}
91
1ee306e1
LP
92int manager_enumerate_machines(Manager *m) {
93 _cleanup_closedir_ DIR *d = NULL;
94 struct dirent *de;
95 int r = 0;
96
97 assert(m);
98
99 /* Read in machine data stored on disk */
100 d = opendir("/run/systemd/machines");
101 if (!d) {
102 if (errno == ENOENT)
103 return 0;
104
56f64d95 105 log_error_errno(errno, "Failed to open /run/systemd/machines: %m");
1ee306e1
LP
106 return -errno;
107 }
108
109 FOREACH_DIRENT(de, d, return -errno) {
110 struct Machine *machine;
111 int k;
112
113 if (!dirent_is_file(de))
114 continue;
115
b87633c4
LP
116 /* Ignore symlinks that map the unit name to the machine */
117 if (startswith(de->d_name, "unit:"))
118 continue;
119
1ee306e1
LP
120 k = manager_add_machine(m, de->d_name, &machine);
121 if (k < 0) {
da927ba9 122 log_error_errno(k, "Failed to add machine by file name %s: %m", de->d_name);
1ee306e1
LP
123
124 r = k;
125 continue;
126 }
127
128 machine_add_to_gc_queue(machine);
129
130 k = machine_load(machine);
131 if (k < 0)
132 r = k;
133 }
134
135 return r;
136}
137
1ee306e1 138static int manager_connect_bus(Manager *m) {
c3350683 139 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1ee306e1 140 int r;
1ee306e1
LP
141
142 assert(m);
143 assert(!m->bus);
1ee306e1 144
76b54375 145 r = sd_bus_default_system(&m->bus);
f647962d
MS
146 if (r < 0)
147 return log_error_errno(r, "Failed to connect to system bus: %m");
1ee306e1 148
19befb2d 149 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", manager_vtable, m);
f647962d
MS
150 if (r < 0)
151 return log_error_errno(r, "Failed to add manager object vtable: %m");
1ee306e1 152
19befb2d 153 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/machine1/machine", "org.freedesktop.machine1.Machine", machine_vtable, machine_object_find, m);
f647962d
MS
154 if (r < 0)
155 return log_error_errno(r, "Failed to add machine object vtable: %m");
c3350683 156
19befb2d 157 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/machine1/machine", machine_node_enumerator, m);
f647962d
MS
158 if (r < 0)
159 return log_error_errno(r, "Failed to add machine enumerator: %m");
1ee306e1 160
ebeccf9e
LP
161 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/machine1/image", "org.freedesktop.machine1.Image", image_vtable, image_object_find, m);
162 if (r < 0)
163 return log_error_errno(r, "Failed to add image object vtable: %m");
164
165 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/machine1/image", image_node_enumerator, m);
166 if (r < 0)
167 return log_error_errno(r, "Failed to add image enumerator: %m");
168
c3350683 169 r = sd_bus_add_match(m->bus,
19befb2d 170 NULL,
c3350683
LP
171 "type='signal',"
172 "sender='org.freedesktop.systemd1',"
173 "interface='org.freedesktop.systemd1.Manager',"
174 "member='JobRemoved',"
175 "path='/org/freedesktop/systemd1'",
176 match_job_removed,
177 m);
f647962d
MS
178 if (r < 0)
179 return log_error_errno(r, "Failed to add match for JobRemoved: %m");
1ee306e1 180
c3350683 181 r = sd_bus_add_match(m->bus,
19befb2d 182 NULL,
c3350683
LP
183 "type='signal',"
184 "sender='org.freedesktop.systemd1',"
185 "interface='org.freedesktop.systemd1.Manager',"
186 "member='UnitRemoved',"
187 "path='/org/freedesktop/systemd1'",
188 match_unit_removed,
189 m);
f647962d
MS
190 if (r < 0)
191 return log_error_errno(r, "Failed to add match for UnitRemoved: %m");
943aca8e 192
c3350683 193 r = sd_bus_add_match(m->bus,
19befb2d 194 NULL,
c3350683
LP
195 "type='signal',"
196 "sender='org.freedesktop.systemd1',"
197 "interface='org.freedesktop.DBus.Properties',"
11b90e69
LP
198 "member='PropertiesChanged',"
199 "arg0='org.freedesktop.systemd1.Unit'",
c3350683
LP
200 match_properties_changed,
201 m);
f647962d
MS
202 if (r < 0)
203 return log_error_errno(r, "Failed to add match for PropertiesChanged: %m");
1ee306e1 204
c3350683 205 r = sd_bus_add_match(m->bus,
19befb2d 206 NULL,
c3350683
LP
207 "type='signal',"
208 "sender='org.freedesktop.systemd1',"
209 "interface='org.freedesktop.systemd1.Manager',"
210 "member='Reloading',"
211 "path='/org/freedesktop/systemd1'",
212 match_reloading,
213 m);
f647962d
MS
214 if (r < 0)
215 return log_error_errno(r, "Failed to add match for Reloading: %m");
6797c324 216
c3350683 217 r = sd_bus_call_method(
1ee306e1
LP
218 m->bus,
219 "org.freedesktop.systemd1",
220 "/org/freedesktop/systemd1",
221 "org.freedesktop.systemd1.Manager",
222 "Subscribe",
1ee306e1 223 &error,
c3350683 224 NULL, NULL);
1ee306e1 225 if (r < 0) {
c3350683
LP
226 log_error("Failed to enable subscription: %s", bus_error_message(&error, r));
227 return r;
1ee306e1
LP
228 }
229
5bb658a1 230 r = sd_bus_request_name(m->bus, "org.freedesktop.machine1", 0);
f647962d
MS
231 if (r < 0)
232 return log_error_errno(r, "Failed to register name: %m");
1ee306e1 233
c3350683 234 r = sd_bus_attach_event(m->bus, m->event, 0);
f647962d
MS
235 if (r < 0)
236 return log_error_errno(r, "Failed to attach bus to event loop: %m");
1ee306e1 237
1ee306e1 238 return 0;
1ee306e1
LP
239}
240
241void manager_gc(Manager *m, bool drop_not_started) {
242 Machine *machine;
243
244 assert(m);
245
246 while ((machine = m->machine_gc_queue)) {
71fda00f 247 LIST_REMOVE(gc_queue, m->machine_gc_queue, machine);
1ee306e1
LP
248 machine->in_gc_queue = false;
249
49f3fffd
LP
250 /* First, if we are not closing yet, initiate stopping */
251 if (!machine_check_gc(machine, drop_not_started) &&
252 machine_get_state(machine) != MACHINE_CLOSING)
1ee306e1 253 machine_stop(machine);
49f3fffd
LP
254
255 /* Now, the stop stop probably made this referenced
256 * again, but if it didn't, then it's time to let it
257 * go entirely. */
258 if (!machine_check_gc(machine, drop_not_started)) {
259 machine_finalize(machine);
1ee306e1
LP
260 machine_free(machine);
261 }
262 }
263}
264
265int manager_startup(Manager *m) {
1ee306e1
LP
266 Machine *machine;
267 Iterator i;
c3350683 268 int r;
1ee306e1
LP
269
270 assert(m);
1ee306e1
LP
271
272 /* Connect to the bus */
273 r = manager_connect_bus(m);
274 if (r < 0)
275 return r;
276
277 /* Deserialize state */
278 manager_enumerate_machines(m);
279
280 /* Remove stale objects before we start them */
281 manager_gc(m, false);
282
283 /* And start everything */
284 HASHMAP_FOREACH(machine, m->machines, i)
c3350683 285 machine_start(machine, NULL, NULL);
1ee306e1
LP
286
287 return 0;
288}
289
d9e34bfd
LP
290static bool check_idle(void *userdata) {
291 Manager *m = userdata;
1ee306e1 292
d9e34bfd 293 manager_gc(m, true);
1ee306e1 294
d9e34bfd
LP
295 return hashmap_isempty(m->machines);
296}
1ee306e1 297
d9e34bfd
LP
298int manager_run(Manager *m) {
299 assert(m);
1ee306e1 300
d9e34bfd
LP
301 return bus_event_loop_with_idle(
302 m->event,
303 m->bus,
304 "org.freedesktop.machine1",
305 DEFAULT_EXIT_USEC,
306 check_idle, m);
1ee306e1
LP
307}
308
309int main(int argc, char *argv[]) {
310 Manager *m = NULL;
311 int r;
312
313 log_set_target(LOG_TARGET_AUTO);
314 log_set_facility(LOG_AUTH);
315 log_parse_environment();
316 log_open();
317
318 umask(0022);
319
320 if (argc != 1) {
321 log_error("This program takes no arguments.");
322 r = -EINVAL;
323 goto finish;
324 }
325
326 /* Always create the directories people can create inotify
327 * watches in. Note that some applications might check for the
c3350683
LP
328 * existence of /run/systemd/machines/ to determine whether
329 * machined is available, so please always make sure this
330 * check stays in. */
1ee306e1
LP
331 mkdir_label("/run/systemd/machines", 0755);
332
72c0a2c2 333 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
0370612e 334
1ee306e1
LP
335 m = manager_new();
336 if (!m) {
337 r = log_oom();
338 goto finish;
339 }
340
341 r = manager_startup(m);
342 if (r < 0) {
da927ba9 343 log_error_errno(r, "Failed to fully start up daemon: %m");
1ee306e1
LP
344 goto finish;
345 }
346
de0671ee 347 log_debug("systemd-machined running as pid "PID_FMT, getpid());
1ee306e1
LP
348
349 sd_notify(false,
350 "READY=1\n"
351 "STATUS=Processing requests...");
352
353 r = manager_run(m);
354
de0671ee 355 log_debug("systemd-machined stopped as pid "PID_FMT, getpid());
1ee306e1
LP
356
357finish:
3e044c49 358 manager_free(m);
1ee306e1
LP
359
360 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
361}