]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/machine/machined.c
2 This file is part of systemd.
4 Copyright 2013 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include "sd-daemon.h"
26 #include "alloc-util.h"
27 #include "bus-error.h"
29 #include "cgroup-util.h"
30 #include "dirent-util.h"
32 #include "formats-util.h"
33 #include "hostname-util.h"
35 #include "machine-image.h"
37 #include "signal-util.h"
39 Manager
*manager_new(void) {
47 m
->machines
= hashmap_new(&string_hash_ops
);
48 m
->machine_units
= hashmap_new(&string_hash_ops
);
49 m
->machine_leaders
= hashmap_new(NULL
);
51 if (!m
->machines
|| !m
->machine_units
|| !m
->machine_leaders
) {
56 r
= sd_event_default(&m
->event
);
62 sd_event_set_watchdog(m
->event
, true);
67 void manager_free(Manager
*m
) {
74 operation_free(m
->operations
);
76 assert(m
->n_operations
== 0);
78 while ((machine
= hashmap_first(m
->machines
)))
79 machine_free(machine
);
81 hashmap_free(m
->machines
);
82 hashmap_free(m
->machine_units
);
83 hashmap_free(m
->machine_leaders
);
85 while ((i
= hashmap_steal_first(m
->image_cache
)))
88 hashmap_free(m
->image_cache
);
90 sd_event_source_unref(m
->image_cache_defer_event
);
92 bus_verify_polkit_async_registry_free(m
->polkit_registry
);
95 sd_event_unref(m
->event
);
100 static int manager_add_host_machine(Manager
*m
) {
101 _cleanup_free_
char *rd
= NULL
, *unit
= NULL
;
109 r
= sd_id128_get_machine(&mid
);
111 return log_error_errno(r
, "Failed to get machine ID: %m");
117 unit
= strdup("-.slice");
121 t
= machine_new(m
, MACHINE_HOST
, ".host");
128 t
->root_directory
= rd
;
132 dual_timestamp_from_boottime_or_monotonic(&t
->timestamp
, 0);
139 int manager_enumerate_machines(Manager
*m
) {
140 _cleanup_closedir_
DIR *d
= NULL
;
146 r
= manager_add_host_machine(m
);
150 /* Read in machine data stored on disk */
151 d
= opendir("/run/systemd/machines");
156 return log_error_errno(errno
, "Failed to open /run/systemd/machines: %m");
159 FOREACH_DIRENT(de
, d
, return -errno
) {
160 struct Machine
*machine
;
163 if (!dirent_is_file(de
))
166 /* Ignore symlinks that map the unit name to the machine */
167 if (startswith(de
->d_name
, "unit:"))
170 if (!machine_name_is_valid(de
->d_name
))
173 k
= manager_add_machine(m
, de
->d_name
, &machine
);
175 r
= log_error_errno(k
, "Failed to add machine by file name %s: %m", de
->d_name
);
179 machine_add_to_gc_queue(machine
);
181 k
= machine_load(machine
);
189 static int manager_connect_bus(Manager
*m
) {
190 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
196 r
= sd_bus_default_system(&m
->bus
);
198 return log_error_errno(r
, "Failed to connect to system bus: %m");
200 r
= sd_bus_add_object_vtable(m
->bus
, NULL
, "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", manager_vtable
, m
);
202 return log_error_errno(r
, "Failed to add manager object vtable: %m");
204 r
= sd_bus_add_fallback_vtable(m
->bus
, NULL
, "/org/freedesktop/machine1/machine", "org.freedesktop.machine1.Machine", machine_vtable
, machine_object_find
, m
);
206 return log_error_errno(r
, "Failed to add machine object vtable: %m");
208 r
= sd_bus_add_node_enumerator(m
->bus
, NULL
, "/org/freedesktop/machine1/machine", machine_node_enumerator
, m
);
210 return log_error_errno(r
, "Failed to add machine enumerator: %m");
212 r
= sd_bus_add_fallback_vtable(m
->bus
, NULL
, "/org/freedesktop/machine1/image", "org.freedesktop.machine1.Image", image_vtable
, image_object_find
, m
);
214 return log_error_errno(r
, "Failed to add image object vtable: %m");
216 r
= sd_bus_add_node_enumerator(m
->bus
, NULL
, "/org/freedesktop/machine1/image", image_node_enumerator
, m
);
218 return log_error_errno(r
, "Failed to add image enumerator: %m");
220 r
= sd_bus_add_match(m
->bus
,
223 "sender='org.freedesktop.systemd1',"
224 "interface='org.freedesktop.systemd1.Manager',"
225 "member='JobRemoved',"
226 "path='/org/freedesktop/systemd1'",
230 return log_error_errno(r
, "Failed to add match for JobRemoved: %m");
232 r
= sd_bus_add_match(m
->bus
,
235 "sender='org.freedesktop.systemd1',"
236 "interface='org.freedesktop.systemd1.Manager',"
237 "member='UnitRemoved',"
238 "path='/org/freedesktop/systemd1'",
242 return log_error_errno(r
, "Failed to add match for UnitRemoved: %m");
244 r
= sd_bus_add_match(m
->bus
,
247 "sender='org.freedesktop.systemd1',"
248 "interface='org.freedesktop.DBus.Properties',"
249 "member='PropertiesChanged',"
250 "arg0='org.freedesktop.systemd1.Unit'",
251 match_properties_changed
,
254 return log_error_errno(r
, "Failed to add match for PropertiesChanged: %m");
256 r
= sd_bus_add_match(m
->bus
,
259 "sender='org.freedesktop.systemd1',"
260 "interface='org.freedesktop.systemd1.Manager',"
261 "member='Reloading',"
262 "path='/org/freedesktop/systemd1'",
266 return log_error_errno(r
, "Failed to add match for Reloading: %m");
268 r
= sd_bus_call_method(
270 "org.freedesktop.systemd1",
271 "/org/freedesktop/systemd1",
272 "org.freedesktop.systemd1.Manager",
277 log_error("Failed to enable subscription: %s", bus_error_message(&error
, r
));
281 r
= sd_bus_request_name(m
->bus
, "org.freedesktop.machine1", 0);
283 return log_error_errno(r
, "Failed to register name: %m");
285 r
= sd_bus_attach_event(m
->bus
, m
->event
, 0);
287 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
292 void manager_gc(Manager
*m
, bool drop_not_started
) {
297 while ((machine
= m
->machine_gc_queue
)) {
298 LIST_REMOVE(gc_queue
, m
->machine_gc_queue
, machine
);
299 machine
->in_gc_queue
= false;
301 /* First, if we are not closing yet, initiate stopping */
302 if (!machine_check_gc(machine
, drop_not_started
) &&
303 machine_get_state(machine
) != MACHINE_CLOSING
)
304 machine_stop(machine
);
306 /* Now, the stop probably made this referenced
307 * again, but if it didn't, then it's time to let it
309 if (!machine_check_gc(machine
, drop_not_started
)) {
310 machine_finalize(machine
);
311 machine_free(machine
);
316 int manager_startup(Manager
*m
) {
323 /* Connect to the bus */
324 r
= manager_connect_bus(m
);
328 /* Deserialize state */
329 manager_enumerate_machines(m
);
331 /* Remove stale objects before we start them */
332 manager_gc(m
, false);
334 /* And start everything */
335 HASHMAP_FOREACH(machine
, m
->machines
, i
)
336 machine_start(machine
, NULL
, NULL
);
341 static bool check_idle(void *userdata
) {
342 Manager
*m
= userdata
;
349 return hashmap_isempty(m
->machines
);
352 int manager_run(Manager
*m
) {
355 return bus_event_loop_with_idle(
358 "org.freedesktop.machine1",
363 int main(int argc
, char *argv
[]) {
367 log_set_target(LOG_TARGET_AUTO
);
368 log_set_facility(LOG_AUTH
);
369 log_parse_environment();
375 log_error("This program takes no arguments.");
380 /* Always create the directories people can create inotify
381 * watches in. Note that some applications might check for the
382 * existence of /run/systemd/machines/ to determine whether
383 * machined is available, so please always make sure this
385 mkdir_label("/run/systemd/machines", 0755);
387 assert_se(sigprocmask_many(SIG_BLOCK
, NULL
, SIGCHLD
, -1) >= 0);
395 r
= manager_startup(m
);
397 log_error_errno(r
, "Failed to fully start up daemon: %m");
401 log_debug("systemd-machined running as pid "PID_FMT
, getpid());
405 "STATUS=Processing requests...");
409 log_debug("systemd-machined stopped as pid "PID_FMT
, getpid());
414 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;