2 This file is part of systemd.
4 Copyright 2015 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include "bus-error.h"
23 #include "bus-unit-util.h"
25 #include "nspawn-register.h"
26 #include "stat-util.h"
30 static int append_machine_properties(
42 r
= sd_bus_message_append(m
, "(sv)", "DevicePolicy", "s", "closed");
44 return bus_log_create_error(r
);
46 /* If you make changes here, also make sure to update systemd-nspawn@.service, to keep the device policies in
47 * sync regardless if we are run with or without the --keep-unit switch. */
48 r
= sd_bus_message_append(m
, "(sv)", "DeviceAllow", "a(ss)", 2,
49 /* Allow the container to
50 * access and create the API
51 * device nodes, so that
52 * PrivateDevices= in the
55 "/dev/net/tun", "rwm",
56 /* Allow the container
57 * access to ptys. However,
59 * container to ever create
60 * these device nodes. */
63 return bus_log_create_error(r
);
65 for (j
= 0; j
< n_mounts
; j
++) {
66 CustomMount
*cm
= mounts
+ j
;
68 if (cm
->type
!= CUSTOM_MOUNT_BIND
)
71 r
= is_device_node(cm
->source
);
73 /* The bind source might only appear as the image is put together, hence don't complain */
74 log_debug_errno(r
, "Bind mount source %s not found, ignoring: %m", cm
->source
);
78 return log_error_errno(r
, "Failed to stat %s: %m", cm
->source
);
81 r
= sd_bus_message_append(m
, "(sv)", "DeviceAllow", "a(ss)", 1,
82 cm
->source
, cm
->read_only
? "r" : "rw");
84 return log_error_errno(r
, "Failed to append message arguments: %m");
88 if (kill_signal
!= 0) {
89 r
= sd_bus_message_append(m
, "(sv)", "KillSignal", "i", kill_signal
);
91 return bus_log_create_error(r
);
93 r
= sd_bus_message_append(m
, "(sv)", "KillMode", "s", "mixed");
95 return bus_log_create_error(r
);
101 int register_machine(
102 const char *machine_name
,
104 const char *directory
,
113 const char *service
) {
115 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
116 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
119 r
= sd_bus_default_system(&bus
);
121 return log_error_errno(r
, "Failed to open system bus: %m");
124 r
= sd_bus_call_method(
126 "org.freedesktop.machine1",
127 "/org/freedesktop/machine1",
128 "org.freedesktop.machine1.Manager",
129 "RegisterMachineWithNetwork",
134 SD_BUS_MESSAGE_APPEND_ID128(uuid
),
139 local_ifindex
> 0 ? 1 : 0, local_ifindex
);
141 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
143 r
= sd_bus_message_new_method_call(
146 "org.freedesktop.machine1",
147 "/org/freedesktop/machine1",
148 "org.freedesktop.machine1.Manager",
149 "CreateMachineWithNetwork");
151 return bus_log_create_error(r
);
153 r
= sd_bus_message_append(
157 SD_BUS_MESSAGE_APPEND_ID128(uuid
),
162 local_ifindex
> 0 ? 1 : 0, local_ifindex
);
164 return bus_log_create_error(r
);
166 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
168 return bus_log_create_error(r
);
170 if (!isempty(slice
)) {
171 r
= sd_bus_message_append(m
, "(sv)", "Slice", "s", slice
);
173 return bus_log_create_error(r
);
176 r
= append_machine_properties(
185 r
= bus_append_unit_property_assignment_many(m
, properties
);
189 r
= sd_bus_message_close_container(m
);
191 return bus_log_create_error(r
);
193 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
197 log_error("Failed to register machine: %s", bus_error_message(&error
, r
));
204 int terminate_machine(pid_t pid
) {
205 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
206 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
207 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
211 r
= sd_bus_default_system(&bus
);
213 return log_error_errno(r
, "Failed to open system bus: %m");
215 r
= sd_bus_call_method(
217 "org.freedesktop.machine1",
218 "/org/freedesktop/machine1",
219 "org.freedesktop.machine1.Manager",
226 /* Note that the machine might already have been
227 * cleaned up automatically, hence don't consider it a
228 * failure if we cannot get the machine object. */
229 log_debug("Failed to get machine: %s", bus_error_message(&error
, r
));
233 r
= sd_bus_message_read(reply
, "o", &path
);
235 return bus_log_parse_error(r
);
237 r
= sd_bus_call_method(
239 "org.freedesktop.machine1",
241 "org.freedesktop.machine1.Machine",
247 log_debug("Failed to terminate machine: %s", bus_error_message(&error
, r
));
255 const char *machine_name
,
263 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
264 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
265 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
266 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
267 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
268 _cleanup_free_
char *scope
= NULL
;
269 const char *description
, *object
;
272 r
= sd_bus_default_system(&bus
);
274 return log_error_errno(r
, "Failed to open system bus: %m");
276 r
= bus_wait_for_jobs_new(bus
, &w
);
278 return log_error_errno(r
, "Could not watch job: %m");
280 r
= unit_name_mangle_with_suffix(machine_name
, UNIT_NAME_NOGLOB
, ".scope", &scope
);
282 return log_error_errno(r
, "Failed to mangle scope name: %m");
284 r
= sd_bus_message_new_method_call(
287 "org.freedesktop.systemd1",
288 "/org/freedesktop/systemd1",
289 "org.freedesktop.systemd1.Manager",
290 "StartTransientUnit");
292 return bus_log_create_error(r
);
294 r
= sd_bus_message_append(m
, "ss", scope
, "fail");
296 return bus_log_create_error(r
);
299 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
301 return bus_log_create_error(r
);
303 description
= strjoina("Container ", machine_name
);
305 r
= sd_bus_message_append(m
, "(sv)(sv)(sv)(sv)",
306 "PIDs", "au", 1, pid
,
307 "Description", "s", description
,
309 "Slice", "s", isempty(slice
) ? "machine.slice" : slice
);
311 return bus_log_create_error(r
);
313 r
= append_machine_properties(
322 r
= bus_append_unit_property_assignment_many(m
, properties
);
326 r
= sd_bus_message_close_container(m
);
328 return bus_log_create_error(r
);
330 /* No auxiliary units */
331 r
= sd_bus_message_append(
336 return bus_log_create_error(r
);
338 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
340 log_error("Failed to allocate scope: %s", bus_error_message(&error
, r
));
344 r
= sd_bus_message_read(reply
, "o", &object
);
346 return bus_log_parse_error(r
);
348 r
= bus_wait_for_jobs_one(w
, object
, false);