]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/machine/machined.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include "sd-daemon.h"
27 #include "alloc-util.h"
28 #include "bus-error.h"
30 #include "cgroup-util.h"
31 #include "dirent-util.h"
33 #include "format-util.h"
34 #include "hostname-util.h"
36 #include "machine-image.h"
38 #include "process-util.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
) {
76 operation_free(m
->operations
);
78 assert(m
->n_operations
== 0);
80 while ((machine
= hashmap_first(m
->machines
)))
81 machine_free(machine
);
83 hashmap_free(m
->machines
);
84 hashmap_free(m
->machine_units
);
85 hashmap_free(m
->machine_leaders
);
87 while ((i
= hashmap_steal_first(m
->image_cache
)))
90 hashmap_free(m
->image_cache
);
92 sd_event_source_unref(m
->image_cache_defer_event
);
94 bus_verify_polkit_async_registry_free(m
->polkit_registry
);
97 sd_event_unref(m
->event
);
102 static int manager_add_host_machine(Manager
*m
) {
103 _cleanup_free_
char *rd
= NULL
, *unit
= NULL
;
111 r
= sd_id128_get_machine(&mid
);
113 return log_error_errno(r
, "Failed to get machine ID: %m");
119 unit
= strdup("-.slice");
123 t
= machine_new(m
, MACHINE_HOST
, ".host");
130 t
->root_directory
= rd
;
134 dual_timestamp_from_boottime_or_monotonic(&t
->timestamp
, 0);
141 int manager_enumerate_machines(Manager
*m
) {
142 _cleanup_closedir_
DIR *d
= NULL
;
148 r
= manager_add_host_machine(m
);
152 /* Read in machine data stored on disk */
153 d
= opendir("/run/systemd/machines");
158 return log_error_errno(errno
, "Failed to open /run/systemd/machines: %m");
161 FOREACH_DIRENT(de
, d
, return -errno
) {
162 struct Machine
*machine
;
165 if (!dirent_is_file(de
))
168 /* Ignore symlinks that map the unit name to the machine */
169 if (startswith(de
->d_name
, "unit:"))
172 if (!machine_name_is_valid(de
->d_name
))
175 k
= manager_add_machine(m
, de
->d_name
, &machine
);
177 r
= log_error_errno(k
, "Failed to add machine by file name %s: %m", de
->d_name
);
181 machine_add_to_gc_queue(machine
);
183 k
= machine_load(machine
);
191 static int manager_connect_bus(Manager
*m
) {
192 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
198 r
= sd_bus_default_system(&m
->bus
);
200 return log_error_errno(r
, "Failed to connect to system bus: %m");
202 r
= sd_bus_add_object_vtable(m
->bus
, NULL
, "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", manager_vtable
, m
);
204 return log_error_errno(r
, "Failed to add manager object vtable: %m");
206 r
= sd_bus_add_fallback_vtable(m
->bus
, NULL
, "/org/freedesktop/machine1/machine", "org.freedesktop.machine1.Machine", machine_vtable
, machine_object_find
, m
);
208 return log_error_errno(r
, "Failed to add machine object vtable: %m");
210 r
= sd_bus_add_node_enumerator(m
->bus
, NULL
, "/org/freedesktop/machine1/machine", machine_node_enumerator
, m
);
212 return log_error_errno(r
, "Failed to add machine enumerator: %m");
214 r
= sd_bus_add_fallback_vtable(m
->bus
, NULL
, "/org/freedesktop/machine1/image", "org.freedesktop.machine1.Image", image_vtable
, image_object_find
, m
);
216 return log_error_errno(r
, "Failed to add image object vtable: %m");
218 r
= sd_bus_add_node_enumerator(m
->bus
, NULL
, "/org/freedesktop/machine1/image", image_node_enumerator
, m
);
220 return log_error_errno(r
, "Failed to add image enumerator: %m");
222 r
= sd_bus_add_match(m
->bus
,
225 "sender='org.freedesktop.systemd1',"
226 "interface='org.freedesktop.systemd1.Manager',"
227 "member='JobRemoved',"
228 "path='/org/freedesktop/systemd1'",
232 return log_error_errno(r
, "Failed to add match for JobRemoved: %m");
234 r
= sd_bus_add_match(m
->bus
,
237 "sender='org.freedesktop.systemd1',"
238 "interface='org.freedesktop.systemd1.Manager',"
239 "member='UnitRemoved',"
240 "path='/org/freedesktop/systemd1'",
244 return log_error_errno(r
, "Failed to add match for UnitRemoved: %m");
246 r
= sd_bus_add_match(m
->bus
,
249 "sender='org.freedesktop.systemd1',"
250 "interface='org.freedesktop.DBus.Properties',"
251 "member='PropertiesChanged',"
252 "arg0='org.freedesktop.systemd1.Unit'",
253 match_properties_changed
,
256 return log_error_errno(r
, "Failed to add match for PropertiesChanged: %m");
258 r
= sd_bus_add_match(m
->bus
,
261 "sender='org.freedesktop.systemd1',"
262 "interface='org.freedesktop.systemd1.Manager',"
263 "member='Reloading',"
264 "path='/org/freedesktop/systemd1'",
268 return log_error_errno(r
, "Failed to add match for Reloading: %m");
270 r
= sd_bus_call_method(
272 "org.freedesktop.systemd1",
273 "/org/freedesktop/systemd1",
274 "org.freedesktop.systemd1.Manager",
279 log_error("Failed to enable subscription: %s", bus_error_message(&error
, r
));
283 r
= sd_bus_request_name(m
->bus
, "org.freedesktop.machine1", 0);
285 return log_error_errno(r
, "Failed to register name: %m");
287 r
= sd_bus_attach_event(m
->bus
, m
->event
, 0);
289 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
294 void manager_gc(Manager
*m
, bool drop_not_started
) {
299 while ((machine
= m
->machine_gc_queue
)) {
300 LIST_REMOVE(gc_queue
, m
->machine_gc_queue
, machine
);
301 machine
->in_gc_queue
= false;
303 /* First, if we are not closing yet, initiate stopping */
304 if (!machine_check_gc(machine
, drop_not_started
) &&
305 machine_get_state(machine
) != MACHINE_CLOSING
)
306 machine_stop(machine
);
308 /* Now, the stop probably made this referenced
309 * again, but if it didn't, then it's time to let it
311 if (!machine_check_gc(machine
, drop_not_started
)) {
312 machine_finalize(machine
);
313 machine_free(machine
);
318 int manager_startup(Manager
*m
) {
325 /* Connect to the bus */
326 r
= manager_connect_bus(m
);
330 /* Deserialize state */
331 manager_enumerate_machines(m
);
333 /* Remove stale objects before we start them */
334 manager_gc(m
, false);
336 /* And start everything */
337 HASHMAP_FOREACH(machine
, m
->machines
, i
)
338 machine_start(machine
, NULL
, NULL
);
343 static bool check_idle(void *userdata
) {
344 Manager
*m
= userdata
;
351 return hashmap_isempty(m
->machines
);
354 int manager_run(Manager
*m
) {
357 return bus_event_loop_with_idle(
360 "org.freedesktop.machine1",
365 int main(int argc
, char *argv
[]) {
369 log_set_target(LOG_TARGET_AUTO
);
370 log_set_facility(LOG_AUTH
);
371 log_parse_environment();
377 log_error("This program takes no arguments.");
382 /* Always create the directories people can create inotify
383 * watches in. Note that some applications might check for the
384 * existence of /run/systemd/machines/ to determine whether
385 * machined is available, so please always make sure this
387 mkdir_label("/run/systemd/machines", 0755);
389 assert_se(sigprocmask_many(SIG_BLOCK
, NULL
, SIGCHLD
, -1) >= 0);
397 r
= manager_startup(m
);
399 log_error_errno(r
, "Failed to fully start up daemon: %m");
403 log_debug("systemd-machined running as pid "PID_FMT
, getpid_cached());
407 "STATUS=Processing requests...");
411 log_debug("systemd-machined stopped as pid "PID_FMT
, getpid_cached());
416 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;