]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/snapshot.c
core: convert PID 1 to libsystemd-bus
[thirdparty/systemd.git] / src / core / snapshot.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
5cb5a6ff 2
a7334b09
LP
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
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
a7334b09
LP
11 (at your option) any later version.
12
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
5430f7f2 16 Lesser General Public License for more details.
a7334b09 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
41447faf
LP
22#include <errno.h>
23
87f0e418 24#include "unit.h"
5cb5a6ff 25#include "snapshot.h"
41447faf
LP
26#include "unit-name.h"
27#include "dbus-snapshot.h"
398ef8ba 28#include "bus-errors.h"
41447faf
LP
29
30static const UnitActiveState state_translation_table[_SNAPSHOT_STATE_MAX] = {
31 [SNAPSHOT_DEAD] = UNIT_INACTIVE,
32 [SNAPSHOT_ACTIVE] = UNIT_ACTIVE
33};
34
7a6000a6
LP
35static void snapshot_init(Unit *u) {
36 Snapshot *s = SNAPSHOT(u);
37
38 assert(s);
1124fe6f 39 assert(UNIT(s)->load_state == UNIT_STUB);
7a6000a6 40
1124fe6f
MS
41 UNIT(s)->ignore_on_isolate = true;
42 UNIT(s)->ignore_on_snapshot = true;
a190eeb8 43 UNIT(s)->allow_isolate = true;
7a6000a6
LP
44}
45
a16e1123
LP
46static void snapshot_set_state(Snapshot *s, SnapshotState state) {
47 SnapshotState old_state;
48 assert(s);
41447faf 49
a16e1123
LP
50 old_state = s->state;
51 s->state = state;
41447faf 52
a16e1123 53 if (state != old_state)
40d50879 54 log_debug("%s changed %s -> %s",
1124fe6f 55 UNIT(s)->id,
a16e1123
LP
56 snapshot_state_to_string(old_state),
57 snapshot_state_to_string(state));
5cb5a6ff 58
e2f3b44c 59 unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], true);
a16e1123 60}
41447faf 61
6ec1117a
LP
62static int snapshot_load(Unit *u) {
63 Snapshot *s = SNAPSHOT(u);
64
65 assert(u);
ac155bb8 66 assert(u->load_state == UNIT_STUB);
6ec1117a
LP
67
68 /* Make sure that only snapshots created via snapshot_create()
69 * can be loaded */
a190eeb8 70 if (!u->transient && UNIT(s)->manager->n_reloading <= 0)
6ec1117a
LP
71 return -ENOENT;
72
ac155bb8 73 u->load_state = UNIT_LOADED;
6ec1117a
LP
74 return 0;
75}
76
a16e1123
LP
77static int snapshot_coldplug(Unit *u) {
78 Snapshot *s = SNAPSHOT(u);
41447faf 79
a16e1123
LP
80 assert(s);
81 assert(s->state == SNAPSHOT_DEAD);
41447faf 82
a16e1123
LP
83 if (s->deserialized_state != s->state)
84 snapshot_set_state(s, s->deserialized_state);
41447faf
LP
85
86 return 0;
87}
88
89static void snapshot_dump(Unit *u, FILE *f, const char *prefix) {
87f0e418 90 Snapshot *s = SNAPSHOT(u);
5cb5a6ff
LP
91
92 assert(s);
41447faf 93 assert(f);
5cb5a6ff 94
41447faf
LP
95 fprintf(f,
96 "%sSnapshot State: %s\n"
97 "%sClean Up: %s\n",
a16e1123 98 prefix, snapshot_state_to_string(s->state),
41447faf
LP
99 prefix, yes_no(s->cleanup));
100}
101
41447faf
LP
102static int snapshot_start(Unit *u) {
103 Snapshot *s = SNAPSHOT(u);
104
105 assert(s);
106 assert(s->state == SNAPSHOT_DEAD);
107
108 snapshot_set_state(s, SNAPSHOT_ACTIVE);
109
110 if (s->cleanup)
111 unit_add_to_cleanup_queue(u);
112
113 return 0;
114}
115
116static int snapshot_stop(Unit *u) {
117 Snapshot *s = SNAPSHOT(u);
118
119 assert(s);
120 assert(s->state == SNAPSHOT_ACTIVE);
121
122 snapshot_set_state(s, SNAPSHOT_DEAD);
123 return 0;
5cb5a6ff
LP
124}
125
a16e1123
LP
126static int snapshot_serialize(Unit *u, FILE *f, FDSet *fds) {
127 Snapshot *s = SNAPSHOT(u);
128 Unit *other;
129 Iterator i;
130
131 assert(s);
132 assert(f);
133 assert(fds);
134
135 unit_serialize_item(u, f, "state", snapshot_state_to_string(s->state));
136 unit_serialize_item(u, f, "cleanup", yes_no(s->cleanup));
ac155bb8
MS
137 SET_FOREACH(other, u->dependencies[UNIT_WANTS], i)
138 unit_serialize_item(u, f, "wants", other->id);
a16e1123
LP
139
140 return 0;
141}
142
143static int snapshot_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
144 Snapshot *s = SNAPSHOT(u);
145 int r;
146
147 assert(u);
148 assert(key);
149 assert(value);
150 assert(fds);
151
152 if (streq(key, "state")) {
153 SnapshotState state;
154
a190eeb8
LP
155 state = snapshot_state_from_string(value);
156 if (state < 0)
a16e1123
LP
157 log_debug("Failed to parse state value %s", value);
158 else
159 s->deserialized_state = state;
160
161 } else if (streq(key, "cleanup")) {
162
a190eeb8
LP
163 r = parse_boolean(value);
164 if (r < 0)
a16e1123
LP
165 log_debug("Failed to parse cleanup value %s", value);
166 else
167 s->cleanup = r;
168
daf32cc7 169 } else if (streq(key, "wants")) {
a16e1123 170
a190eeb8
LP
171 r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_WANTS, value, NULL, true);
172 if (r < 0)
a16e1123
LP
173 return r;
174 } else
175 log_debug("Unknown serialization key '%s'", key);
176
177 return 0;
178}
179
44a6b1b6 180_pure_ static UnitActiveState snapshot_active_state(Unit *u) {
41447faf
LP
181 assert(u);
182
183 return state_translation_table[SNAPSHOT(u)->state];
184}
185
44a6b1b6 186_pure_ static const char *snapshot_sub_state_to_string(Unit *u) {
41447faf
LP
187 assert(u);
188
a16e1123 189 return snapshot_state_to_string(SNAPSHOT(u)->state);
41447faf
LP
190}
191
718db961 192int snapshot_create(Manager *m, const char *name, bool cleanup, sd_bus_error *e, Snapshot **_s) {
a190eeb8 193 _cleanup_free_ char *n = NULL;
a16e1123 194 Unit *other, *u = NULL;
a190eeb8 195 Iterator i;
41447faf 196 int r;
a16e1123 197 const char *k;
41447faf
LP
198
199 assert(m);
200 assert(_s);
201
202 if (name) {
718db961
LP
203 if (!unit_name_is_valid(name, false))
204 return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s is not valid.", name);
41447faf 205
718db961
LP
206 if (unit_name_to_type(name) != UNIT_SNAPSHOT)
207 return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Unit name %s lacks snapshot suffix.", name);
41447faf 208
718db961
LP
209 if (manager_get_unit(m, name))
210 sd_bus_error_setf(e, BUS_ERROR_UNIT_EXISTS, "Snapshot %s exists already.", name);
41447faf
LP
211
212 } else {
213
214 for (;;) {
215 if (asprintf(&n, "snapshot-%u.snapshot", ++ m->n_snapshots) < 0)
216 return -ENOMEM;
217
ebec5783
ZJS
218 if (!manager_get_unit(m, n)) {
219 name = n;
41447faf 220 break;
ebec5783 221 }
41447faf
LP
222
223 free(n);
a190eeb8 224 n = NULL;
41447faf 225 }
41447faf
LP
226 }
227
398ef8ba 228 r = manager_load_unit_prepare(m, name, NULL, e, &u);
41447faf 229 if (r < 0)
a16e1123
LP
230 goto fail;
231
a190eeb8 232 u->transient = true;
6ec1117a 233 manager_dispatch_load_queue(m);
ac155bb8 234 assert(u->load_state == UNIT_LOADED);
6ec1117a 235
a16e1123
LP
236 HASHMAP_FOREACH_KEY(other, k, m->units, i) {
237
a190eeb8
LP
238 if (other->ignore_on_snapshot ||
239 other->transient)
a16e1123
LP
240 continue;
241
ac155bb8 242 if (k != other->id)
a16e1123
LP
243 continue;
244
701cc384
LP
245 if (UNIT_VTABLE(other)->check_snapshot)
246 if (!UNIT_VTABLE(other)->check_snapshot(other))
247 continue;
248
a16e1123
LP
249 if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
250 continue;
251
a190eeb8
LP
252 r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_WANTS, other, true);
253 if (r < 0)
a16e1123
LP
254 goto fail;
255 }
41447faf
LP
256
257 SNAPSHOT(u)->cleanup = cleanup;
258 *_s = SNAPSHOT(u);
259
260 return 0;
a16e1123
LP
261
262fail:
263 if (u)
264 unit_add_to_cleanup_queue(u);
265
266 return r;
41447faf
LP
267}
268
269void snapshot_remove(Snapshot *s) {
270 assert(s);
271
272 unit_add_to_cleanup_queue(UNIT(s));
034c6ed7
LP
273}
274
a16e1123
LP
275static const char* const snapshot_state_table[_SNAPSHOT_STATE_MAX] = {
276 [SNAPSHOT_DEAD] = "dead",
277 [SNAPSHOT_ACTIVE] = "active"
278};
279
280DEFINE_STRING_TABLE_LOOKUP(snapshot_state, SnapshotState);
281
87f0e418 282const UnitVTable snapshot_vtable = {
7d17cfbc 283 .object_size = sizeof(Snapshot),
5cb5a6ff 284
41447faf
LP
285 .no_alias = true,
286 .no_instances = true,
701cc384 287 .no_gc = true,
41447faf 288
7a6000a6 289 .init = snapshot_init,
6ec1117a 290 .load = snapshot_load,
718db961 291
a16e1123 292 .coldplug = snapshot_coldplug,
41447faf
LP
293
294 .dump = snapshot_dump,
295
296 .start = snapshot_start,
297 .stop = snapshot_stop,
298
a16e1123
LP
299 .serialize = snapshot_serialize,
300 .deserialize_item = snapshot_deserialize_item,
301
41447faf
LP
302 .active_state = snapshot_active_state,
303 .sub_state_to_string = snapshot_sub_state_to_string,
5cb5a6ff 304
c4e2ceae 305 .bus_interface = "org.freedesktop.systemd1.Snapshot",
718db961 306 .bus_vtable = bus_snapshot_vtable
5cb5a6ff 307};