]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/machine/machined.c
everywhere: port everything to sigprocmask_many() and friends
[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
a658cafa 250 if (!machine_check_gc(machine, drop_not_started)) {
1ee306e1
LP
251 machine_stop(machine);
252 machine_free(machine);
253 }
254 }
255}
256
257int manager_startup(Manager *m) {
1ee306e1
LP
258 Machine *machine;
259 Iterator i;
c3350683 260 int r;
1ee306e1
LP
261
262 assert(m);
1ee306e1
LP
263
264 /* Connect to the bus */
265 r = manager_connect_bus(m);
266 if (r < 0)
267 return r;
268
269 /* Deserialize state */
270 manager_enumerate_machines(m);
271
272 /* Remove stale objects before we start them */
273 manager_gc(m, false);
274
275 /* And start everything */
276 HASHMAP_FOREACH(machine, m->machines, i)
c3350683 277 machine_start(machine, NULL, NULL);
1ee306e1
LP
278
279 return 0;
280}
281
d9e34bfd
LP
282static bool check_idle(void *userdata) {
283 Manager *m = userdata;
1ee306e1 284
d9e34bfd 285 manager_gc(m, true);
1ee306e1 286
d9e34bfd
LP
287 return hashmap_isempty(m->machines);
288}
1ee306e1 289
d9e34bfd
LP
290int manager_run(Manager *m) {
291 assert(m);
1ee306e1 292
d9e34bfd
LP
293 return bus_event_loop_with_idle(
294 m->event,
295 m->bus,
296 "org.freedesktop.machine1",
297 DEFAULT_EXIT_USEC,
298 check_idle, m);
1ee306e1
LP
299}
300
301int main(int argc, char *argv[]) {
302 Manager *m = NULL;
303 int r;
304
305 log_set_target(LOG_TARGET_AUTO);
306 log_set_facility(LOG_AUTH);
307 log_parse_environment();
308 log_open();
309
310 umask(0022);
311
312 if (argc != 1) {
313 log_error("This program takes no arguments.");
314 r = -EINVAL;
315 goto finish;
316 }
317
318 /* Always create the directories people can create inotify
319 * watches in. Note that some applications might check for the
c3350683
LP
320 * existence of /run/systemd/machines/ to determine whether
321 * machined is available, so please always make sure this
322 * check stays in. */
1ee306e1
LP
323 mkdir_label("/run/systemd/machines", 0755);
324
72c0a2c2 325 assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
0370612e 326
1ee306e1
LP
327 m = manager_new();
328 if (!m) {
329 r = log_oom();
330 goto finish;
331 }
332
333 r = manager_startup(m);
334 if (r < 0) {
da927ba9 335 log_error_errno(r, "Failed to fully start up daemon: %m");
1ee306e1
LP
336 goto finish;
337 }
338
de0671ee 339 log_debug("systemd-machined running as pid "PID_FMT, getpid());
1ee306e1
LP
340
341 sd_notify(false,
342 "READY=1\n"
343 "STATUS=Processing requests...");
344
345 r = manager_run(m);
346
de0671ee 347 log_debug("systemd-machined stopped as pid "PID_FMT, getpid());
1ee306e1
LP
348
349finish:
1ee306e1
LP
350 if (m)
351 manager_free(m);
352
353 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
354}