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/>.
27 #include <sys/epoll.h>
29 #include "sd-daemon.h"
32 #include "conf-parser.h"
33 #include "cgroup-util.h"
36 #include "bus-error.h"
39 Manager *manager_new(void) {
47 m->machines = hashmap_new(string_hash_func, string_compare_func);
48 m->machine_units = hashmap_new(string_hash_func, string_compare_func);
49 m->machine_leaders = hashmap_new(trivial_hash_func, trivial_compare_func);
51 if (!m->machines || !m->machine_units || !m->machine_leaders) {
56 r = sd_event_default(&m->event);
65 void manager_free(Manager *m) {
70 while ((machine = hashmap_first(m->machines)))
71 machine_free(machine);
73 hashmap_free(m->machines);
74 hashmap_free(m->machine_units);
75 hashmap_free(m->machine_leaders);
78 sd_event_unref(m->event);
83 int manager_enumerate_machines(Manager *m) {
84 _cleanup_closedir_ DIR *d = NULL;
90 /* Read in machine data stored on disk */
91 d = opendir("/run/systemd/machines");
96 log_error("Failed to open /run/systemd/machines: %m");
100 FOREACH_DIRENT(de, d, return -errno) {
101 struct Machine *machine;
104 if (!dirent_is_file(de))
107 k = manager_add_machine(m, de->d_name, &machine);
109 log_error("Failed to add machine by file name %s: %s", de->d_name, strerror(-k));
115 machine_add_to_gc_queue(machine);
117 k = machine_load(machine);
125 static int manager_connect_bus(Manager *m) {
126 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
132 r = sd_bus_default_system(&m->bus);
134 log_error("Failed to connect to system bus: %s", strerror(-r));
138 r = sd_bus_add_object_vtable(m->bus, "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", manager_vtable, m);
140 log_error("Failed to add manager object vtable: %s", strerror(-r));
144 r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/machine1/machine", "org.freedesktop.machine1.Machine", machine_vtable, machine_object_find, m);
146 log_error("Failed to add machine object vtable: %s", strerror(-r));
150 r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/machine1/machine", machine_node_enumerator, m);
152 log_error("Failed to add machine enumerator: %s", strerror(-r));
156 r = sd_bus_add_match(m->bus,
158 "sender='org.freedesktop.systemd1',"
159 "interface='org.freedesktop.systemd1.Manager',"
160 "member='JobRemoved',"
161 "path='/org/freedesktop/systemd1'",
165 log_error("Failed to add match for JobRemoved: %s", strerror(-r));
169 r = sd_bus_add_match(m->bus,
171 "sender='org.freedesktop.systemd1',"
172 "interface='org.freedesktop.systemd1.Manager',"
173 "member='UnitRemoved',"
174 "path='/org/freedesktop/systemd1'",
178 log_error("Failed to add match for UnitRemoved: %s", strerror(-r));
182 r = sd_bus_add_match(m->bus,
184 "sender='org.freedesktop.systemd1',"
185 "interface='org.freedesktop.DBus.Properties',"
186 "member='PropertiesChanged'",
187 match_properties_changed,
190 log_error("Failed to add match for PropertiesChanged: %s", strerror(-r));
194 r = sd_bus_add_match(m->bus,
196 "sender='org.freedesktop.systemd1',"
197 "interface='org.freedesktop.systemd1.Manager',"
198 "member='Reloading',"
199 "path='/org/freedesktop/systemd1'",
203 log_error("Failed to add match for Reloading: %s", strerror(-r));
207 r = sd_bus_call_method(
209 "org.freedesktop.systemd1",
210 "/org/freedesktop/systemd1",
211 "org.freedesktop.systemd1.Manager",
216 log_error("Failed to enable subscription: %s", bus_error_message(&error, r));
220 r = sd_bus_request_name(m->bus, "org.freedesktop.machine1", SD_BUS_NAME_DO_NOT_QUEUE);
222 log_error("Failed to register name: %s", strerror(-r));
226 if (r != SD_BUS_NAME_PRIMARY_OWNER) {
227 log_error("Failed to acquire name.");
231 r = sd_bus_attach_event(m->bus, m->event, 0);
233 log_error("Failed to attach bus to event loop: %s", strerror(-r));
240 void manager_gc(Manager *m, bool drop_not_started) {
245 while ((machine = m->machine_gc_queue)) {
246 LIST_REMOVE(gc_queue, m->machine_gc_queue, machine);
247 machine->in_gc_queue = false;
249 if (!machine_check_gc(machine, drop_not_started)) {
250 machine_stop(machine);
251 machine_free(machine);
256 int manager_startup(Manager *m) {
263 /* Connect to the bus */
264 r = manager_connect_bus(m);
268 /* Deserialize state */
269 manager_enumerate_machines(m);
271 /* Remove stale objects before we start them */
272 manager_gc(m, false);
274 /* And start everything */
275 HASHMAP_FOREACH(machine, m->machines, i)
276 machine_start(machine, NULL, NULL);
281 int manager_run(Manager *m) {
287 r = sd_event_get_state(m->event);
290 if (r == SD_EVENT_FINISHED)
295 r = sd_event_run(m->event, (uint64_t) -1);
303 int main(int argc, char *argv[]) {
307 log_set_target(LOG_TARGET_AUTO);
308 log_set_facility(LOG_AUTH);
309 log_parse_environment();
315 log_error("This program takes no arguments.");
320 /* Always create the directories people can create inotify
321 * watches in. Note that some applications might check for the
322 * existence of /run/systemd/machines/ to determine whether
323 * machined is available, so please always make sure this
325 mkdir_label("/run/systemd/machines", 0755);
333 r = manager_startup(m);
335 log_error("Failed to fully start up daemon: %s", strerror(-r));
339 log_debug("systemd-machined running as pid %lu", (unsigned long) getpid());
343 "STATUS=Processing requests...");
347 log_debug("systemd-machined stopped as pid %lu", (unsigned long) getpid());
351 "STATUS=Shutting down...");
356 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;