]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/machine/machined.c
54f8d836a25d91b0c6d74960453f49c47512363d
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"
42 Manager
*manager_new(void) {
50 m
->machines
= hashmap_new(&string_hash_ops
);
51 m
->machine_units
= hashmap_new(&string_hash_ops
);
52 m
->machine_leaders
= hashmap_new(NULL
);
54 if (!m
->machines
|| !m
->machine_units
|| !m
->machine_leaders
) {
59 r
= sd_event_default(&m
->event
);
65 sd_event_set_watchdog(m
->event
, true);
70 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 hashmap_free_with_destructor(m
->image_cache
, image_unref
);
89 sd_event_source_unref(m
->image_cache_defer_event
);
91 bus_verify_polkit_async_registry_free(m
->polkit_registry
);
94 sd_event_unref(m
->event
);
99 static int manager_add_host_machine(Manager
*m
) {
100 _cleanup_free_
char *rd
= NULL
, *unit
= NULL
;
108 r
= sd_id128_get_machine(&mid
);
110 return log_error_errno(r
, "Failed to get machine ID: %m");
116 unit
= strdup(SPECIAL_ROOT_SLICE
);
120 t
= machine_new(m
, MACHINE_HOST
, ".host");
127 t
->root_directory
= TAKE_PTR(rd
);
128 t
->unit
= TAKE_PTR(unit
);
130 dual_timestamp_from_boottime_or_monotonic(&t
->timestamp
, 0);
137 int manager_enumerate_machines(Manager
*m
) {
138 _cleanup_closedir_
DIR *d
= NULL
;
144 r
= manager_add_host_machine(m
);
148 /* Read in machine data stored on disk */
149 d
= opendir("/run/systemd/machines");
154 return log_error_errno(errno
, "Failed to open /run/systemd/machines: %m");
157 FOREACH_DIRENT(de
, d
, return -errno
) {
158 struct Machine
*machine
;
161 if (!dirent_is_file(de
))
164 /* Ignore symlinks that map the unit name to the machine */
165 if (startswith(de
->d_name
, "unit:"))
168 if (!machine_name_is_valid(de
->d_name
))
171 k
= manager_add_machine(m
, de
->d_name
, &machine
);
173 r
= log_error_errno(k
, "Failed to add machine by file name %s: %m", de
->d_name
);
177 machine_add_to_gc_queue(machine
);
179 k
= machine_load(machine
);
187 static int manager_connect_bus(Manager
*m
) {
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_match_signal_async(
220 "org.freedesktop.systemd1",
221 "/org/freedesktop/systemd1",
222 "org.freedesktop.systemd1.Manager",
224 match_job_removed
, NULL
, m
);
226 return log_error_errno(r
, "Failed to add match for JobRemoved: %m");
228 r
= sd_bus_match_signal_async(
231 "org.freedesktop.systemd1",
232 "/org/freedesktop/systemd1",
233 "org.freedesktop.systemd1.Manager",
235 match_unit_removed
, NULL
, m
);
237 return log_error_errno(r
, "Failed to request match for UnitRemoved: %m");
239 r
= sd_bus_match_signal_async(
242 "org.freedesktop.systemd1",
244 "org.freedesktop.DBus.Properties",
246 match_properties_changed
, NULL
, m
);
248 return log_error_errno(r
, "Failed to request match for PropertiesChanged: %m");
250 r
= sd_bus_match_signal_async(
253 "org.freedesktop.systemd1",
254 "/org/freedesktop/systemd1",
255 "org.freedesktop.systemd1.Manager",
257 match_reloading
, NULL
, m
);
259 return log_error_errno(r
, "Failed to request match for Reloading: %m");
261 r
= sd_bus_call_method_async(
264 "org.freedesktop.systemd1",
265 "/org/freedesktop/systemd1",
266 "org.freedesktop.systemd1.Manager",
271 return log_error_errno(r
, "Failed to enable subscription: %m");
273 r
= sd_bus_request_name_async(m
->bus
, NULL
, "org.freedesktop.machine1", 0, NULL
, NULL
);
275 return log_error_errno(r
, "Failed to request name: %m");
277 r
= sd_bus_attach_event(m
->bus
, m
->event
, 0);
279 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
284 void manager_gc(Manager
*m
, bool drop_not_started
) {
289 while ((machine
= m
->machine_gc_queue
)) {
290 LIST_REMOVE(gc_queue
, m
->machine_gc_queue
, machine
);
291 machine
->in_gc_queue
= false;
293 /* First, if we are not closing yet, initiate stopping */
294 if (machine_may_gc(machine
, drop_not_started
) &&
295 machine_get_state(machine
) != MACHINE_CLOSING
)
296 machine_stop(machine
);
298 /* Now, the stop probably made this referenced
299 * again, but if it didn't, then it's time to let it
301 if (machine_may_gc(machine
, drop_not_started
)) {
302 machine_finalize(machine
);
303 machine_free(machine
);
308 int manager_startup(Manager
*m
) {
315 /* Connect to the bus */
316 r
= manager_connect_bus(m
);
320 /* Deserialize state */
321 manager_enumerate_machines(m
);
323 /* Remove stale objects before we start them */
324 manager_gc(m
, false);
326 /* And start everything */
327 HASHMAP_FOREACH(machine
, m
->machines
, i
)
328 machine_start(machine
, NULL
, NULL
);
333 static bool check_idle(void *userdata
) {
334 Manager
*m
= userdata
;
341 return hashmap_isempty(m
->machines
);
344 int manager_run(Manager
*m
) {
347 return bus_event_loop_with_idle(
350 "org.freedesktop.machine1",
355 int main(int argc
, char *argv
[]) {
359 log_set_target(LOG_TARGET_AUTO
);
360 log_set_facility(LOG_AUTH
);
361 log_parse_environment();
367 log_error("This program takes no arguments.");
372 /* Always create the directories people can create inotify
373 * watches in. Note that some applications might check for the
374 * existence of /run/systemd/machines/ to determine whether
375 * machined is available, so please always make sure this
377 mkdir_label("/run/systemd/machines", 0755);
379 assert_se(sigprocmask_many(SIG_BLOCK
, NULL
, SIGCHLD
, -1) >= 0);
387 r
= manager_startup(m
);
389 log_error_errno(r
, "Failed to fully start up daemon: %m");
393 log_debug("systemd-machined running as pid "PID_FMT
, getpid_cached());
397 "STATUS=Processing requests...");
401 log_debug("systemd-machined stopped as pid "PID_FMT
, getpid_cached());
406 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;