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