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);
50 if (!m->machines || !m->machine_units) {
55 r = sd_event_new(&m->event);
64 void manager_free(Manager *m) {
69 while ((machine = hashmap_first(m->machines)))
70 machine_free(machine);
72 hashmap_free(m->machines);
73 hashmap_free(m->machine_units);
76 sd_event_unref(m->event);
81 int manager_add_machine(Manager *m, const char *name, Machine **_machine) {
87 machine = hashmap_get(m->machines, name);
89 machine = machine_new(m, name);
100 int manager_get_machine_by_pid(Manager *m, pid_t pid, Machine **machine) {
101 _cleanup_free_ char *unit = NULL;
109 r = cg_pid_get_unit(pid, &unit);
113 mm = hashmap_get(m->machine_units, unit);
121 int manager_enumerate_machines(Manager *m) {
122 _cleanup_closedir_ DIR *d = NULL;
128 /* Read in machine data stored on disk */
129 d = opendir("/run/systemd/machines");
134 log_error("Failed to open /run/systemd/machines: %m");
138 FOREACH_DIRENT(de, d, return -errno) {
139 struct Machine *machine;
142 if (!dirent_is_file(de))
145 k = manager_add_machine(m, de->d_name, &machine);
147 log_error("Failed to add machine by file name %s: %s", de->d_name, strerror(-k));
153 machine_add_to_gc_queue(machine);
155 k = machine_load(machine);
163 static int manager_connect_bus(Manager *m) {
164 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
170 r = sd_bus_open_system(&m->bus);
172 log_error("Failed to connect to system bus: %s", strerror(-r));
176 r = sd_bus_add_object_vtable(m->bus, "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", manager_vtable, m);
178 log_error("Failed to add manager object vtable: %s", strerror(-r));
182 r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/machine1/machine", "org.freedesktop.machine1.Machine", machine_vtable, machine_object_find, m);
184 log_error("Failed to add machine object vtable: %s", strerror(-r));
188 r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/machine1/machine", machine_node_enumerator, m);
190 log_error("Failed to add machine enumerator: %s", strerror(-r));
194 r = sd_bus_add_match(m->bus,
196 "sender='org.freedesktop.systemd1',"
197 "interface='org.freedesktop.systemd1.Manager',"
198 "member='JobRemoved',"
199 "path='/org/freedesktop/systemd1'",
203 log_error("Failed to add match for JobRemoved: %s", strerror(-r));
207 r = sd_bus_add_match(m->bus,
209 "sender='org.freedesktop.systemd1',"
210 "interface='org.freedesktop.systemd1.Manager',"
211 "member='UnitRemoved',"
212 "path='/org/freedesktop/systemd1'",
216 log_error("Failed to add match for UnitRemoved: %s", strerror(-r));
220 r = sd_bus_add_match(m->bus,
222 "sender='org.freedesktop.systemd1',"
223 "interface='org.freedesktop.DBus.Properties',"
224 "member='PropertiesChanged'",
225 match_properties_changed,
228 log_error("Failed to add match for PropertiesChanged: %s", strerror(-r));
232 r = sd_bus_add_match(m->bus,
234 "sender='org.freedesktop.systemd1',"
235 "interface='org.freedesktop.systemd1.Manager',"
236 "member='Reloading',"
237 "path='/org/freedesktop/systemd1'",
241 log_error("Failed to add match for Reloading: %s", strerror(-r));
245 r = sd_bus_call_method(
247 "org.freedesktop.systemd1",
248 "/org/freedesktop/systemd1",
249 "org.freedesktop.systemd1.Manager",
254 log_error("Failed to enable subscription: %s", bus_error_message(&error, r));
258 r = sd_bus_request_name(m->bus, "org.freedesktop.machine1", SD_BUS_NAME_DO_NOT_QUEUE);
260 log_error("Failed to register name: %s", strerror(-r));
264 if (r != SD_BUS_NAME_PRIMARY_OWNER) {
265 log_error("Failed to acquire name.");
269 r = sd_bus_attach_event(m->bus, m->event, 0);
271 log_error("Failed to attach bus to event loop: %s", strerror(-r));
278 void manager_gc(Manager *m, bool drop_not_started) {
283 while ((machine = m->machine_gc_queue)) {
284 LIST_REMOVE(gc_queue, m->machine_gc_queue, machine);
285 machine->in_gc_queue = false;
287 if (!machine_check_gc(machine, drop_not_started)) {
288 machine_stop(machine);
289 machine_free(machine);
294 int manager_startup(Manager *m) {
301 /* Connect to the bus */
302 r = manager_connect_bus(m);
306 /* Deserialize state */
307 manager_enumerate_machines(m);
309 /* Remove stale objects before we start them */
310 manager_gc(m, false);
312 /* And start everything */
313 HASHMAP_FOREACH(machine, m->machines, i)
314 machine_start(machine, NULL, NULL);
319 int manager_run(Manager *m) {
325 r = sd_event_get_state(m->event);
328 if (r == SD_EVENT_FINISHED)
333 r = sd_event_run(m->event, (uint64_t) -1);
341 int main(int argc, char *argv[]) {
345 log_set_target(LOG_TARGET_AUTO);
346 log_set_facility(LOG_AUTH);
347 log_parse_environment();
353 log_error("This program takes no arguments.");
358 /* Always create the directories people can create inotify
359 * watches in. Note that some applications might check for the
360 * existence of /run/systemd/machines/ to determine whether
361 * machined is available, so please always make sure this
363 mkdir_label("/run/systemd/machines", 0755);
371 r = manager_startup(m);
373 log_error("Failed to fully start up daemon: %s", strerror(-r));
377 log_debug("systemd-machined running as pid %lu", (unsigned long) getpid());
381 "STATUS=Processing requests...");
385 log_debug("systemd-machined stopped as pid %lu", (unsigned long) getpid());
389 "STATUS=Shutting down...");
394 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;