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