mirror of
https://github.com/systemd/systemd.git
synced 2024-11-27 04:03:36 +08:00
portablectl: add --force attach/detach
Allows to skip check that ensures units must not be running. I have a use case that would use reattach, except the orchestrator is using a non-standard versioning scheme, so image matching cannot work. As a workaround, need to be able to detach and then attach manually, without stopping the units to avoid extended downtimes and loss of FD store.
This commit is contained in:
parent
e638a062e8
commit
ace212f577
@ -307,10 +307,13 @@ node /org/freedesktop/portable1 {
|
||||
<para>The <function>AttachImageWithExtensions()</function>,
|
||||
<function>DetachImageWithExtensions()</function> and
|
||||
<function>ReattachImageWithExtensions()</function> methods take in options as flags instead of
|
||||
booleans to allow for extendability, defined as follows:</para>
|
||||
booleans to allow for extendability. <varname>SD_SYSTEMD_PORTABLE_FORCE</varname> will cause
|
||||
safety checks that ensure the units are not running while the new image is attached or detached
|
||||
to be skipped. They are defined as follows:</para>
|
||||
|
||||
<programlisting>
|
||||
#define SD_SYSTEMD_PORTABLE_RUNTIME (UINT64_C(1) << 0)
|
||||
#define SD_SYSTEMD_PORTABLE_FORCE (UINT64_C(1) << 1)
|
||||
</programlisting>
|
||||
</refsect2>
|
||||
|
||||
|
@ -374,6 +374,13 @@
|
||||
and detaching.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--force</option></term>
|
||||
|
||||
<listitem><para>Skip safety checks and attach or detach images (with extensions) without first ensuring
|
||||
that the units are not running.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<xi:include href="user-system-options.xml" xpointer="host" />
|
||||
<xi:include href="user-system-options.xml" xpointer="machine" />
|
||||
|
||||
|
@ -1357,19 +1357,20 @@ int portable_attach(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
HASHMAP_FOREACH(item, unit_files) {
|
||||
r = unit_file_exists(LOOKUP_SCOPE_SYSTEM, &paths, item->name);
|
||||
if (r < 0)
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to determine whether unit '%s' exists on the host: %m", item->name);
|
||||
if (!FLAGS_SET(flags, PORTABLE_REATTACH) && r > 0)
|
||||
return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit file '%s' exists on the host already, refusing.", item->name);
|
||||
if (!FLAGS_SET(flags, PORTABLE_REATTACH) && !FLAGS_SET(flags, PORTABLE_FORCE))
|
||||
HASHMAP_FOREACH(item, unit_files) {
|
||||
r = unit_file_exists(LOOKUP_SCOPE_SYSTEM, &paths, item->name);
|
||||
if (r < 0)
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to determine whether unit '%s' exists on the host: %m", item->name);
|
||||
if (r > 0)
|
||||
return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit file '%s' exists on the host already, refusing.", item->name);
|
||||
|
||||
r = unit_file_is_active(bus, item->name, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (!FLAGS_SET(flags, PORTABLE_REATTACH) && r > 0)
|
||||
return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit file '%s' is active already, refusing.", item->name);
|
||||
}
|
||||
r = unit_file_is_active(bus, item->name, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit file '%s' is active already, refusing.", item->name);
|
||||
}
|
||||
|
||||
HASHMAP_FOREACH(item, unit_files) {
|
||||
r = attach_unit_file(&paths, image->path, image->type, extension_images,
|
||||
@ -1599,11 +1600,13 @@ int portable_detach(
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
r = unit_file_is_active(bus, unit_name, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (!FLAGS_SET(flags, PORTABLE_REATTACH) && r > 0)
|
||||
return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit file '%s' is active, can't detach.", unit_name);
|
||||
if (!FLAGS_SET(flags, PORTABLE_REATTACH) && !FLAGS_SET(flags, PORTABLE_FORCE)) {
|
||||
r = unit_file_is_active(bus, unit_name, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit file '%s' is active, can't detach.", unit_name);
|
||||
}
|
||||
|
||||
r = set_ensure_consume(&unit_files, &string_hash_ops_free, TAKE_PTR(unit_name));
|
||||
if (r < 0)
|
||||
|
@ -22,10 +22,11 @@ typedef struct PortableMetadata {
|
||||
|
||||
typedef enum PortableFlags {
|
||||
PORTABLE_RUNTIME = 1 << 0, /* Public API via DBUS, do not change */
|
||||
PORTABLE_PREFER_COPY = 1 << 1,
|
||||
PORTABLE_PREFER_SYMLINK = 1 << 2,
|
||||
PORTABLE_REATTACH = 1 << 3,
|
||||
_PORTABLE_MASK_PUBLIC = PORTABLE_RUNTIME,
|
||||
PORTABLE_FORCE = 1 << 1, /* Public API via DBUS, do not change */
|
||||
PORTABLE_PREFER_COPY = 1 << 2,
|
||||
PORTABLE_PREFER_SYMLINK = 1 << 3,
|
||||
PORTABLE_REATTACH = 1 << 4,
|
||||
_PORTABLE_MASK_PUBLIC = PORTABLE_RUNTIME | PORTABLE_FORCE,
|
||||
_PORTABLE_TYPE_MAX,
|
||||
_PORTABLE_TYPE_INVALID = -EINVAL,
|
||||
} PortableFlags;
|
||||
|
@ -48,6 +48,7 @@ static bool arg_enable = false;
|
||||
static bool arg_now = false;
|
||||
static bool arg_no_block = false;
|
||||
static char **arg_extension_images = NULL;
|
||||
static bool arg_force = false;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_extension_images, strv_freep);
|
||||
|
||||
@ -868,7 +869,7 @@ static int attach_reattach_image(int argc, char *argv[], const char *method) {
|
||||
return bus_log_create_error(r);
|
||||
|
||||
if (STR_IN_SET(method, "AttachImageWithExtensions", "ReattachImageWithExtensions")) {
|
||||
uint64_t flags = arg_runtime ? PORTABLE_RUNTIME : 0;
|
||||
uint64_t flags = (arg_runtime ? PORTABLE_RUNTIME : 0) | (arg_force ? PORTABLE_FORCE : 0);
|
||||
|
||||
r = sd_bus_message_append(m, "st", arg_copy_mode, flags);
|
||||
} else
|
||||
@ -940,7 +941,7 @@ static int detach_image(int argc, char *argv[], void *userdata) {
|
||||
if (strv_isempty(arg_extension_images))
|
||||
r = sd_bus_message_append(m, "b", arg_runtime);
|
||||
else {
|
||||
uint64_t flags = arg_runtime ? PORTABLE_RUNTIME : 0;
|
||||
uint64_t flags = (arg_runtime ? PORTABLE_RUNTIME : 0) | (arg_force ? PORTABLE_FORCE : 0);
|
||||
|
||||
r = sd_bus_message_append(m, "t", flags);
|
||||
}
|
||||
@ -1241,6 +1242,8 @@ static int help(int argc, char *argv[], void *userdata) {
|
||||
" attach/before detach\n"
|
||||
" --no-block Don't block waiting for attach --now to complete\n"
|
||||
" --extension=PATH Extend the image with an overlay\n"
|
||||
" --force Skip 'already active' check when attaching or\n"
|
||||
" detaching an image (with extensions)\n"
|
||||
"\nSee the %s for details.\n",
|
||||
program_invocation_short_name,
|
||||
ansi_highlight(),
|
||||
@ -1266,6 +1269,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_NOW,
|
||||
ARG_NO_BLOCK,
|
||||
ARG_EXTENSION,
|
||||
ARG_FORCE,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
@ -1286,6 +1290,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "now", no_argument, NULL, ARG_NOW },
|
||||
{ "no-block", no_argument, NULL, ARG_NO_BLOCK },
|
||||
{ "extension", required_argument, NULL, ARG_EXTENSION },
|
||||
{ "force", no_argument, NULL, ARG_FORCE },
|
||||
{}
|
||||
};
|
||||
|
||||
@ -1390,6 +1395,10 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return log_oom();
|
||||
break;
|
||||
|
||||
case ARG_FORCE:
|
||||
arg_force = true;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -124,7 +124,16 @@ systemctl is-active app1.service
|
||||
status="$(portablectl is-attached --extension app1 minimal_1)"
|
||||
[[ "${status}" == "running-runtime" ]]
|
||||
|
||||
portablectl detach --now --runtime --extension /usr/share/app1.raw /usr/share/minimal_1.raw app1
|
||||
portablectl detach --force --no-reload --runtime --extension /usr/share/app1.raw /usr/share/minimal_1.raw app1
|
||||
portablectl "${ARGS[@]}" attach --force --no-reload --runtime --extension /usr/share/app1.raw /usr/share/minimal_0.raw app1
|
||||
systemctl daemon-reload
|
||||
systemctl restart app1.service
|
||||
|
||||
systemctl is-active app1.service
|
||||
status="$(portablectl is-attached --extension app1 minimal_0)"
|
||||
[[ "${status}" == "running-runtime" ]]
|
||||
|
||||
portablectl detach --now --runtime --extension /usr/share/app1.raw /usr/share/minimal_0.raw app1
|
||||
|
||||
# Ensure that the combination of read-only images, state directory and dynamic user works, and that
|
||||
# state is retained. Check after detaching, as on slow systems (eg: sanitizers) it might take a while
|
||||
|
Loading…
Reference in New Issue
Block a user