core: add [Enable|Disable]UnitFilesWithFlags DBUS methods
The new methods work as the unflavoured ones, but takes flags as a single uint64_t DBUS parameters instead of different booleans, so that it can be extended without breaking backward compatibility. Add new flag to allow adding/removing symlinks in [/etc|/run]/systemd/system.attached so that portable services configuration files can be self-contained in those directories, without affecting the system services directories. Use the new methods and flags from portablectl --enable. Useful in case /etc is read-only, with only the portable services directories being mounted read-write.
This commit is contained in:
parent
f3f14c573b
commit
836540070d
|
@ -179,6 +179,13 @@ node /org/freedesktop/systemd1 {
|
||||||
DisableUnitFiles(in as files,
|
DisableUnitFiles(in as files,
|
||||||
in b runtime,
|
in b runtime,
|
||||||
out a(sss) changes);
|
out a(sss) changes);
|
||||||
|
EnableUnitFilesWithFlags(in as files,
|
||||||
|
in t flags,
|
||||||
|
out b carries_install_info,
|
||||||
|
out a(sss) changes);
|
||||||
|
DisableUnitFilesWithFlags(in as files,
|
||||||
|
in t flags,
|
||||||
|
out a(sss) changes);
|
||||||
ReenableUnitFiles(in as files,
|
ReenableUnitFiles(in as files,
|
||||||
in b runtime,
|
in b runtime,
|
||||||
in b force,
|
in b force,
|
||||||
|
@ -836,6 +843,10 @@ node /org/freedesktop/systemd1 {
|
||||||
|
|
||||||
<variablelist class="dbus-method" generated="True" extra-ref="DisableUnitFiles()"/>
|
<variablelist class="dbus-method" generated="True" extra-ref="DisableUnitFiles()"/>
|
||||||
|
|
||||||
|
<variablelist class="dbus-method" generated="True" extra-ref="EnableUnitFilesWithFlags()"/>
|
||||||
|
|
||||||
|
<variablelist class="dbus-method" generated="True" extra-ref="DisableUnitFilesWithFlags()"/>
|
||||||
|
|
||||||
<variablelist class="dbus-method" generated="True" extra-ref="ReenableUnitFiles()"/>
|
<variablelist class="dbus-method" generated="True" extra-ref="ReenableUnitFiles()"/>
|
||||||
|
|
||||||
<variablelist class="dbus-method" generated="True" extra-ref="LinkUnitFiles()"/>
|
<variablelist class="dbus-method" generated="True" extra-ref="LinkUnitFiles()"/>
|
||||||
|
@ -1292,6 +1303,20 @@ node /org/freedesktop/systemd1 {
|
||||||
<para>Similarly, <function>DisableUnitFiles()</function> disables one or more units in the system,
|
<para>Similarly, <function>DisableUnitFiles()</function> disables one or more units in the system,
|
||||||
i.e. removes all symlinks to them in <filename>/etc</filename> and <filename>/run</filename>.</para>
|
i.e. removes all symlinks to them in <filename>/etc</filename> and <filename>/run</filename>.</para>
|
||||||
|
|
||||||
|
<para>The <function>EnableUnitFilesWithFlags()</function> and <function>DisableUnitFilesWithFlags()</function>
|
||||||
|
take in options as flags instead of booleans to allow for extendability, defined as follows:</para>
|
||||||
|
|
||||||
|
<programlisting>
|
||||||
|
#define SD_SYSTEMD_UNIT_RUNTIME (UINT64_C(1) << 0)
|
||||||
|
#define SD_SYSTEMD_UNIT_FORCE (UINT64_C(1) << 1)
|
||||||
|
#define SD_SYSTEMD_UNIT_PORTABLE (UINT64_C(1) << 2)
|
||||||
|
</programlisting>
|
||||||
|
|
||||||
|
<para><varname>SD_SYSTEMD_UNIT_RUNTIME</varname> will enable or disable the unit for runtime only,
|
||||||
|
<varname>SD_SYSTEMD_UNIT_FORCE</varname> controls whether symlinks pointing to other units shall be
|
||||||
|
replaced if necessary. <varname>SD_SYSTEMD_UNIT_PORTABLE</varname> will add or remove the symlinks in
|
||||||
|
<filename>/etc/systemd/system.attached</filename> and <filename>/run/systemd/system.attached</filename>.</para>
|
||||||
|
|
||||||
<para>Similarly, <function>ReenableUnitFiles()</function> applies the changes to one or more units that
|
<para>Similarly, <function>ReenableUnitFiles()</function> applies the changes to one or more units that
|
||||||
would result from disabling and enabling the unit quickly one after the other in an atomic
|
would result from disabling and enabling the unit quickly one after the other in an atomic
|
||||||
fashion. This is useful to apply updated [Install] information contained in unit files.</para>
|
fashion. This is useful to apply updated [Install] information contained in unit files.</para>
|
||||||
|
@ -1480,6 +1505,7 @@ node /org/freedesktop/systemd1 {
|
||||||
<function>RestartUnit()</function> and similar, <function>SetProperty()</function>) require
|
<function>RestartUnit()</function> and similar, <function>SetProperty()</function>) require
|
||||||
<interfacename>org.freedesktop.systemd1.manage-units</interfacename>. Operations which modify unit file
|
<interfacename>org.freedesktop.systemd1.manage-units</interfacename>. Operations which modify unit file
|
||||||
enablement state (<function>EnableUnitFiles()</function>, <function>DisableUnitFiles()</function>,
|
enablement state (<function>EnableUnitFiles()</function>, <function>DisableUnitFiles()</function>,
|
||||||
|
<function>EnableUnitFilesWithFlags()</function>, <function>DisableUnitFilesWithFlags()</function>,
|
||||||
<function>ReenableUnitFiles()</function>, <function>LinkUnitFiles()</function>,
|
<function>ReenableUnitFiles()</function>, <function>LinkUnitFiles()</function>,
|
||||||
<function>PresetUnitFiles</function>, <function>MaskUnitFiles</function>, and similar) require
|
<function>PresetUnitFiles</function>, <function>MaskUnitFiles</function>, and similar) require
|
||||||
<interfacename>org.freedesktop.systemd1.manage-unit-files</interfacename>. Operations which modify the
|
<interfacename>org.freedesktop.systemd1.manage-unit-files</interfacename>. Operations which modify the
|
||||||
|
|
|
@ -2083,7 +2083,7 @@ static int method_enable_unit_files_generic(
|
||||||
UnitFileChange *changes = NULL;
|
UnitFileChange *changes = NULL;
|
||||||
size_t n_changes = 0;
|
size_t n_changes = 0;
|
||||||
UnitFileFlags flags;
|
UnitFileFlags flags;
|
||||||
int runtime, force, r;
|
int r;
|
||||||
|
|
||||||
assert(message);
|
assert(message);
|
||||||
assert(m);
|
assert(m);
|
||||||
|
@ -2092,11 +2092,23 @@ static int method_enable_unit_files_generic(
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = sd_bus_message_read(message, "bb", &runtime, &force);
|
if (sd_bus_message_is_method_call(message, NULL, "EnableUnitFilesWithFlags")) {
|
||||||
if (r < 0)
|
uint64_t raw_flags;
|
||||||
return r;
|
|
||||||
|
|
||||||
flags = unit_file_bools_to_flags(runtime, force);
|
r = sd_bus_message_read(message, "t", &raw_flags);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if ((raw_flags & ~_UNIT_FILE_FLAGS_MASK_PUBLIC) != 0)
|
||||||
|
return -EINVAL;
|
||||||
|
flags = raw_flags;
|
||||||
|
} else {
|
||||||
|
int runtime, force;
|
||||||
|
|
||||||
|
r = sd_bus_message_read(message, "bb", &runtime, &force);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
flags = unit_file_bools_to_flags(runtime, force);
|
||||||
|
}
|
||||||
|
|
||||||
r = bus_verify_manage_unit_files_async(m, message, error);
|
r = bus_verify_manage_unit_files_async(m, message, error);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -2111,6 +2123,10 @@ static int method_enable_unit_files_generic(
|
||||||
return reply_unit_file_changes_and_free(m, message, carries_install_info ? r : -1, changes, n_changes, error);
|
return reply_unit_file_changes_and_free(m, message, carries_install_info ? r : -1, changes, n_changes, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int method_enable_unit_files_with_flags(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||||
|
return method_enable_unit_files_generic(message, userdata, unit_file_enable, true, error);
|
||||||
|
}
|
||||||
|
|
||||||
static int method_enable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
static int method_enable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||||
return method_enable_unit_files_generic(message, userdata, unit_file_enable, true, error);
|
return method_enable_unit_files_generic(message, userdata, unit_file_enable, true, error);
|
||||||
}
|
}
|
||||||
|
@ -2188,8 +2204,9 @@ static int method_disable_unit_files_generic(
|
||||||
|
|
||||||
_cleanup_strv_free_ char **l = NULL;
|
_cleanup_strv_free_ char **l = NULL;
|
||||||
UnitFileChange *changes = NULL;
|
UnitFileChange *changes = NULL;
|
||||||
|
UnitFileFlags flags;
|
||||||
size_t n_changes = 0;
|
size_t n_changes = 0;
|
||||||
int r, runtime;
|
int r;
|
||||||
|
|
||||||
assert(message);
|
assert(message);
|
||||||
assert(m);
|
assert(m);
|
||||||
|
@ -2198,9 +2215,24 @@ static int method_disable_unit_files_generic(
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = sd_bus_message_read(message, "b", &runtime);
|
if (sd_bus_message_is_method_call(message, NULL, "DisableUnitFilesWithFlags")) {
|
||||||
if (r < 0)
|
uint64_t raw_flags;
|
||||||
return r;
|
|
||||||
|
r = sd_bus_message_read(message, "t", &raw_flags);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if ((raw_flags & ~_UNIT_FILE_FLAGS_MASK_PUBLIC) != 0 ||
|
||||||
|
FLAGS_SET(raw_flags, UNIT_FILE_FORCE))
|
||||||
|
return -EINVAL;
|
||||||
|
flags = raw_flags;
|
||||||
|
} else {
|
||||||
|
int runtime;
|
||||||
|
|
||||||
|
r = sd_bus_message_read(message, "b", &runtime);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
flags = unit_file_bools_to_flags(runtime, false);
|
||||||
|
}
|
||||||
|
|
||||||
r = bus_verify_manage_unit_files_async(m, message, error);
|
r = bus_verify_manage_unit_files_async(m, message, error);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -2208,13 +2240,17 @@ static int method_disable_unit_files_generic(
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||||
|
|
||||||
r = call(m->unit_file_scope, runtime ? UNIT_FILE_RUNTIME : 0, NULL, l, &changes, &n_changes);
|
r = call(m->unit_file_scope, flags, NULL, l, &changes, &n_changes);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return install_error(error, r, changes, n_changes);
|
return install_error(error, r, changes, n_changes);
|
||||||
|
|
||||||
return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes, error);
|
return reply_unit_file_changes_and_free(m, message, -1, changes, n_changes, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int method_disable_unit_files_with_flags(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||||
|
return method_disable_unit_files_generic(message, userdata, unit_file_disable, error);
|
||||||
|
}
|
||||||
|
|
||||||
static int method_disable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
static int method_disable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||||
return method_disable_unit_files_generic(message, userdata, unit_file_disable, error);
|
return method_disable_unit_files_generic(message, userdata, unit_file_disable, error);
|
||||||
}
|
}
|
||||||
|
@ -2984,6 +3020,23 @@ const sd_bus_vtable bus_manager_vtable[] = {
|
||||||
SD_BUS_PARAM(changes),
|
SD_BUS_PARAM(changes),
|
||||||
method_disable_unit_files,
|
method_disable_unit_files,
|
||||||
SD_BUS_VTABLE_UNPRIVILEGED),
|
SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
|
SD_BUS_METHOD_WITH_NAMES("EnableUnitFilesWithFlags",
|
||||||
|
"ast",
|
||||||
|
SD_BUS_PARAM(files)
|
||||||
|
SD_BUS_PARAM(flags),
|
||||||
|
"ba(sss)",
|
||||||
|
SD_BUS_PARAM(carries_install_info)
|
||||||
|
SD_BUS_PARAM(changes),
|
||||||
|
method_enable_unit_files_with_flags,
|
||||||
|
SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
|
SD_BUS_METHOD_WITH_NAMES("DisableUnitFilesWithFlags",
|
||||||
|
"ast",
|
||||||
|
SD_BUS_PARAM(files)
|
||||||
|
SD_BUS_PARAM(flags),
|
||||||
|
"a(sss)",
|
||||||
|
SD_BUS_PARAM(changes),
|
||||||
|
method_disable_unit_files_with_flags,
|
||||||
|
SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
SD_BUS_METHOD_WITH_NAMES("ReenableUnitFiles",
|
SD_BUS_METHOD_WITH_NAMES("ReenableUnitFiles",
|
||||||
"asbb",
|
"asbb",
|
||||||
SD_BUS_PARAM(files)
|
SD_BUS_PARAM(files)
|
||||||
|
|
|
@ -392,6 +392,7 @@ static int maybe_enable_disable(sd_bus *bus, const char *path, bool enable) {
|
||||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||||
_cleanup_strv_free_ char **names = NULL;
|
_cleanup_strv_free_ char **names = NULL;
|
||||||
UnitFileChange *changes = NULL;
|
UnitFileChange *changes = NULL;
|
||||||
|
const uint64_t flags = UNIT_FILE_PORTABLE | (arg_runtime ? UNIT_FILE_RUNTIME : 0);
|
||||||
size_t n_changes = 0;
|
size_t n_changes = 0;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -408,7 +409,7 @@ static int maybe_enable_disable(sd_bus *bus, const char *path, bool enable) {
|
||||||
"org.freedesktop.systemd1",
|
"org.freedesktop.systemd1",
|
||||||
"/org/freedesktop/systemd1",
|
"/org/freedesktop/systemd1",
|
||||||
"org.freedesktop.systemd1.Manager",
|
"org.freedesktop.systemd1.Manager",
|
||||||
enable ? "EnableUnitFiles" : "DisableUnitFiles");
|
enable ? "EnableUnitFilesWithFlags" : "DisableUnitFilesWithFlags");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return bus_log_create_error(r);
|
return bus_log_create_error(r);
|
||||||
|
|
||||||
|
@ -416,16 +417,10 @@ static int maybe_enable_disable(sd_bus *bus, const char *path, bool enable) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return bus_log_create_error(r);
|
return bus_log_create_error(r);
|
||||||
|
|
||||||
r = sd_bus_message_append(m, "b", arg_runtime);
|
r = sd_bus_message_append(m, "t", flags);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return bus_log_create_error(r);
|
return bus_log_create_error(r);
|
||||||
|
|
||||||
if (enable) {
|
|
||||||
r = sd_bus_message_append(m, "b", false);
|
|
||||||
if (r < 0)
|
|
||||||
return bus_log_create_error(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
r = sd_bus_call(bus, m, 0, &error, &reply);
|
r = sd_bus_call(bus, m, 0, &error, &reply);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to %s the portable service %s: %s",
|
return log_error_errno(r, "Failed to %s the portable service %s: %s",
|
||||||
|
|
|
@ -249,6 +249,15 @@ static int path_is_vendor_or_generator(const LookupPaths *p, const char *path) {
|
||||||
return path_equal(rpath, SYSTEM_DATA_UNIT_PATH);
|
return path_equal(rpath, SYSTEM_DATA_UNIT_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char* config_path_from_flags(const LookupPaths *paths, UnitFileFlags flags) {
|
||||||
|
assert(paths);
|
||||||
|
|
||||||
|
if (FLAGS_SET(flags, UNIT_FILE_PORTABLE))
|
||||||
|
return FLAGS_SET(flags, UNIT_FILE_RUNTIME) ? paths->runtime_attached : paths->persistent_attached;
|
||||||
|
else
|
||||||
|
return FLAGS_SET(flags, UNIT_FILE_RUNTIME) ? paths->runtime_config : paths->persistent_config;
|
||||||
|
}
|
||||||
|
|
||||||
int unit_file_changes_add(
|
int unit_file_changes_add(
|
||||||
UnitFileChange **changes,
|
UnitFileChange **changes,
|
||||||
size_t *n_changes,
|
size_t *n_changes,
|
||||||
|
@ -2582,7 +2591,7 @@ int unit_file_enable(
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
|
config_path = config_path_from_flags(&paths, flags);
|
||||||
if (!config_path)
|
if (!config_path)
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
|
|
||||||
|
@ -2625,7 +2634,7 @@ int unit_file_disable(
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
config_path = (flags & UNIT_FILE_RUNTIME) ? paths.runtime_config : paths.persistent_config;
|
config_path = config_path_from_flags(&paths, flags);
|
||||||
if (!config_path)
|
if (!config_path)
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
|
|
||||||
|
|
|
@ -35,9 +35,11 @@ enum UnitFileChangeType {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum UnitFileFlags {
|
enum UnitFileFlags {
|
||||||
UNIT_FILE_RUNTIME = 1 << 0,
|
UNIT_FILE_RUNTIME = 1 << 0, /* Public API via DBUS, do not change */
|
||||||
UNIT_FILE_FORCE = 1 << 1,
|
UNIT_FILE_FORCE = 1 << 1, /* Public API via DBUS, do not change */
|
||||||
UNIT_FILE_DRY_RUN = 1 << 2,
|
UNIT_FILE_PORTABLE = 1 << 2, /* Public API via DBUS, do not change */
|
||||||
|
UNIT_FILE_DRY_RUN = 1 << 3,
|
||||||
|
_UNIT_FILE_FLAGS_MASK_PUBLIC = UNIT_FILE_RUNTIME|UNIT_FILE_PORTABLE|UNIT_FILE_FORCE,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* type can either one of the UnitFileChangeTypes listed above, or a negative error.
|
/* type can either one of the UnitFileChangeTypes listed above, or a negative error.
|
||||||
|
|
Loading…
Reference in a new issue