]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/machine/machined.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
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.
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.
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/>.
26 #include "sd-daemon.h"
28 #include "alloc-util.h"
29 #include "bus-error.h"
31 #include "cgroup-util.h"
32 #include "dirent-util.h"
34 #include "formats-util.h"
35 #include "hostname-util.h"
37 #include "machine-image.h"
39 #include "signal-util.h"
41 Manager
*manager_new(void) {
49 m
->machines
= hashmap_new(&string_hash_ops
);
50 m
->machine_units
= hashmap_new(&string_hash_ops
);
51 m
->machine_leaders
= hashmap_new(NULL
);
53 if (!m
->machines
|| !m
->machine_units
|| !m
->machine_leaders
) {
58 r
= sd_event_default(&m
->event
);
64 sd_event_set_watchdog(m
->event
, true);
69 void manager_free(Manager
*m
) {
75 while ((machine
= hashmap_first(m
->machines
)))
76 machine_free(machine
);
78 hashmap_free(m
->machines
);
79 hashmap_free(m
->machine_units
);
80 hashmap_free(m
->machine_leaders
);
82 while ((i
= hashmap_steal_first(m
->image_cache
)))
85 hashmap_free(m
->image_cache
);
87 sd_event_source_unref(m
->image_cache_defer_event
);
89 bus_verify_polkit_async_registry_free(m
->polkit_registry
);
92 sd_event_unref(m
->event
);
97 static int manager_add_host_machine(Manager
*m
) {
98 _cleanup_free_
char *rd
= NULL
, *unit
= NULL
;
106 r
= sd_id128_get_machine(&mid
);
108 return log_error_errno(r
, "Failed to get machine ID: %m");
114 unit
= strdup("-.slice");
118 t
= machine_new(m
, MACHINE_HOST
, ".host");
125 t
->root_directory
= rd
;
129 dual_timestamp_from_boottime_or_monotonic(&t
->timestamp
, 0);
136 int manager_enumerate_machines(Manager
*m
) {
137 _cleanup_closedir_
DIR *d
= NULL
;
143 r
= manager_add_host_machine(m
);
147 /* Read in machine data stored on disk */
148 d
= opendir("/run/systemd/machines");
153 return log_error_errno(errno
, "Failed to open /run/systemd/machines: %m");
156 FOREACH_DIRENT(de
, d
, return -errno
) {
157 struct Machine
*machine
;
160 if (!dirent_is_file(de
))
163 /* Ignore symlinks that map the unit name to the machine */
164 if (startswith(de
->d_name
, "unit:"))
167 if (!machine_name_is_valid(de
->d_name
))
170 k
= manager_add_machine(m
, de
->d_name
, &machine
);
172 r
= log_error_errno(k
, "Failed to add machine by file name %s: %m", de
->d_name
);
176 machine_add_to_gc_queue(machine
);
178 k
= machine_load(machine
);
186 static int manager_connect_bus(Manager
*m
) {
187 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
193 r
= sd_bus_default_system(&m
->bus
);
195 return log_error_errno(r
, "Failed to connect to system bus: %m");
197 r
= sd_bus_add_object_vtable(m
->bus
, NULL
, "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", manager_vtable
, m
);
199 return log_error_errno(r
, "Failed to add manager object vtable: %m");
201 r
= sd_bus_add_fallback_vtable(m
->bus
, NULL
, "/org/freedesktop/machine1/machine", "org.freedesktop.machine1.Machine", machine_vtable
, machine_object_find
, m
);
203 return log_error_errno(r
, "Failed to add machine object vtable: %m");
205 r
= sd_bus_add_node_enumerator(m
->bus
, NULL
, "/org/freedesktop/machine1/machine", machine_node_enumerator
, m
);
207 return log_error_errno(r
, "Failed to add machine enumerator: %m");
209 r
= sd_bus_add_fallback_vtable(m
->bus
, NULL
, "/org/freedesktop/machine1/image", "org.freedesktop.machine1.Image", image_vtable
, image_object_find
, m
);
211 return log_error_errno(r
, "Failed to add image object vtable: %m");
213 r
= sd_bus_add_node_enumerator(m
->bus
, NULL
, "/org/freedesktop/machine1/image", image_node_enumerator
, m
);
215 return log_error_errno(r
, "Failed to add image enumerator: %m");
217 r
= sd_bus_add_match(m
->bus
,
220 "sender='org.freedesktop.systemd1',"
221 "interface='org.freedesktop.systemd1.Manager',"
222 "member='JobRemoved',"
223 "path='/org/freedesktop/systemd1'",
227 return log_error_errno(r
, "Failed to add match for JobRemoved: %m");
229 r
= sd_bus_add_match(m
->bus
,
232 "sender='org.freedesktop.systemd1',"
233 "interface='org.freedesktop.systemd1.Manager',"
234 "member='UnitRemoved',"
235 "path='/org/freedesktop/systemd1'",
239 return log_error_errno(r
, "Failed to add match for UnitRemoved: %m");
241 r
= sd_bus_add_match(m
->bus
,
244 "sender='org.freedesktop.systemd1',"
245 "interface='org.freedesktop.DBus.Properties',"
246 "member='PropertiesChanged',"
247 "arg0='org.freedesktop.systemd1.Unit'",
248 match_properties_changed
,
251 return log_error_errno(r
, "Failed to add match for PropertiesChanged: %m");
253 r
= sd_bus_add_match(m
->bus
,
256 "sender='org.freedesktop.systemd1',"
257 "interface='org.freedesktop.systemd1.Manager',"
258 "member='Reloading',"
259 "path='/org/freedesktop/systemd1'",
263 return log_error_errno(r
, "Failed to add match for Reloading: %m");
265 r
= sd_bus_call_method(
267 "org.freedesktop.systemd1",
268 "/org/freedesktop/systemd1",
269 "org.freedesktop.systemd1.Manager",
274 log_error("Failed to enable subscription: %s", bus_error_message(&error
, r
));
278 r
= sd_bus_request_name(m
->bus
, "org.freedesktop.machine1", 0);
280 return log_error_errno(r
, "Failed to register name: %m");
282 r
= sd_bus_attach_event(m
->bus
, m
->event
, 0);
284 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
289 void manager_gc(Manager
*m
, bool drop_not_started
) {
294 while ((machine
= m
->machine_gc_queue
)) {
295 LIST_REMOVE(gc_queue
, m
->machine_gc_queue
, machine
);
296 machine
->in_gc_queue
= false;
298 /* First, if we are not closing yet, initiate stopping */
299 if (!machine_check_gc(machine
, drop_not_started
) &&
300 machine_get_state(machine
) != MACHINE_CLOSING
)
301 machine_stop(machine
);
303 /* Now, the stop stop probably made this referenced
304 * again, but if it didn't, then it's time to let it
306 if (!machine_check_gc(machine
, drop_not_started
)) {
307 machine_finalize(machine
);
308 machine_free(machine
);
313 int manager_startup(Manager
*m
) {
320 /* Connect to the bus */
321 r
= manager_connect_bus(m
);
325 /* Deserialize state */
326 manager_enumerate_machines(m
);
328 /* Remove stale objects before we start them */
329 manager_gc(m
, false);
331 /* And start everything */
332 HASHMAP_FOREACH(machine
, m
->machines
, i
)
333 machine_start(machine
, NULL
, NULL
);
338 static bool check_idle(void *userdata
) {
339 Manager
*m
= userdata
;
343 return hashmap_isempty(m
->machines
);
346 int manager_run(Manager
*m
) {
349 return bus_event_loop_with_idle(
352 "org.freedesktop.machine1",
357 int main(int argc
, char *argv
[]) {
361 log_set_target(LOG_TARGET_AUTO
);
362 log_set_facility(LOG_AUTH
);
363 log_parse_environment();
369 log_error("This program takes no arguments.");
374 /* Always create the directories people can create inotify
375 * watches in. Note that some applications might check for the
376 * existence of /run/systemd/machines/ to determine whether
377 * machined is available, so please always make sure this
379 mkdir_label("/run/systemd/machines", 0755);
381 assert_se(sigprocmask_many(SIG_BLOCK
, NULL
, SIGCHLD
, -1) >= 0);
389 r
= manager_startup(m
);
391 log_error_errno(r
, "Failed to fully start up daemon: %m");
395 log_debug("systemd-machined running as pid "PID_FMT
, getpid());
399 "STATUS=Processing requests...");
403 log_debug("systemd-machined stopped as pid "PID_FMT
, getpid());
408 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;