1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-24 06:04:05 +03:00

networkctl: introduce --runtime for editing network config under /run/

This commit is contained in:
Mike Yuan 2023-11-17 22:08:28 +08:00
parent 7050f7419b
commit 2b98926f98
No known key found for this signature in database
GPG Key ID: 417471C0A40F58B3
3 changed files with 55 additions and 10 deletions

View File

@ -430,7 +430,8 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR)
</term>
<listitem><para>Edit network configuration files, which include <filename>.network</filename>,
<filename>.netdev</filename>, and <filename>.link</filename> files. If no network config file
matching the given name is found, a new one will be created under <filename>/etc/</filename>.
matching the given name is found, a new one will be created under <filename>/etc/</filename> or
<filename>/run/</filename>, depending on whether <option>--runtime</option> is specified.
Specially, if the name is prefixed by <literal>@</literal>, it will be treated as
a network interface, and editing will be performed on the network config files associated
with it. Additionally, the interface name can be suffixed with <literal>:network</literal> (default)
@ -541,6 +542,17 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR)
<xi:include href="version-info.xml" xpointer="v254"/>
</listitem>
<varlistentry>
<term><option>--runtime</option></term>
<listitem>
<para>When used with <command>edit</command>, edit the file under <filename>/run/</filename>
instead of <filename>/etc/</filename>.</para>
<xi:include href="version-info.xml" xpointer="v256"/>
</listitem>
</varlistentry>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="json" />

View File

@ -87,6 +87,7 @@ static bool arg_no_reload = false;
static bool arg_all = false;
static bool arg_stats = false;
static bool arg_full = false;
static bool arg_runtime = false;
static unsigned arg_lines = 10;
static char *arg_drop_in = NULL;
static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
@ -3076,14 +3077,20 @@ static int add_config_to_edit(
assert(context);
assert(path);
if (path_startswith(path, "/usr")) {
/* If we're supposed to edit main config file in /run/, but a config with the same name is present
* under /etc/, we bail out since the one in /etc/ always overrides that in /run/. */
if (arg_runtime && !arg_drop_in && path_startswith(path, "/etc"))
return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
"Cannot edit runtime config file: overriden by %s", path);
if (path_startswith(path, "/usr") || arg_runtime != !!path_startswith(path, "/run")) {
_cleanup_free_ char *name = NULL;
r = path_extract_filename(path, &name);
if (r < 0)
return log_error_errno(r, "Failed to extract filename from '%s': %m", path);
new_path = path_join(NETWORK_DIRS[0], name);
new_path = path_join(NETWORK_DIRS[arg_runtime ? 1 : 0], name);
if (!new_path)
return log_oom();
}
@ -3091,16 +3098,27 @@ static int add_config_to_edit(
if (!arg_drop_in)
return edit_files_add(context, new_path ?: path, path, NULL);
bool need_new_dropin;
r = get_dropin_by_name(arg_drop_in, dropins, &old_dropin);
if (r < 0)
return log_error_errno(r, "Failed to acquire drop-in '%s': %m", arg_drop_in);
if (r > 0) {
/* See the explanation above */
if (arg_runtime && path_startswith(old_dropin, "/etc"))
return log_error_errno(SYNTHETIC_ERRNO(EEXIST),
"Cannot edit runtime config file: overriden by %s", old_dropin);
if (r > 0 && !path_startswith(old_dropin, "/usr"))
/* An existing drop-in is found and not in /usr/. Let's edit it directly. */
need_new_dropin = path_startswith(old_dropin, "/usr") || arg_runtime != !!path_startswith(old_dropin, "/run");
} else
need_new_dropin = true;
if (!need_new_dropin)
/* An existing drop-in is found in the correct scope. Let's edit it directly. */
dropin_path = TAKE_PTR(old_dropin);
else {
/* No drop-in was found or an existing drop-in resides in /usr/. Let's create
* a new drop-in file. */
/* No drop-in was found or an existing drop-in is in a different scope. Let's create a new
* drop-in file. */
dropin_path = strjoin(new_path ?: path, ".d/", arg_drop_in);
if (!dropin_path)
return log_oom();
@ -3209,7 +3227,7 @@ static int verb_edit(int argc, char *argv[], void *userdata) {
log_debug("No existing network config '%s' found, creating a new file.", *name);
path = path_join(NETWORK_DIRS[0], *name);
path = path_join(NETWORK_DIRS[arg_runtime ? 1 : 0], *name);
if (!path)
return log_oom();
@ -3340,6 +3358,7 @@ static int help(void) {
" --no-reload Do not reload systemd-networkd or systemd-udevd\n"
" after editing network config\n"
" --drop-in=NAME Edit specified drop-in instead of main config file\n"
" --runtime Edit runtime config files\n"
"\nSee the %s for details.\n",
program_invocation_short_name,
ansi_highlight(),
@ -3357,6 +3376,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_JSON,
ARG_NO_RELOAD,
ARG_DROP_IN,
ARG_RUNTIME,
};
static const struct option options[] = {
@ -3371,6 +3391,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "json", required_argument, NULL, ARG_JSON },
{ "no-reload", no_argument, NULL, ARG_NO_RELOAD },
{ "drop-in", required_argument, NULL, ARG_DROP_IN },
{ "runtime", no_argument, NULL, ARG_RUNTIME },
{}
};
@ -3401,6 +3422,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_no_reload = true;
break;
case ARG_RUNTIME:
arg_runtime = true;
break;
case ARG_DROP_IN:
if (isempty(optarg))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Empty drop-in file name.");

View File

@ -11,7 +11,7 @@ at_exit() {
systemctl stop systemd-networkd
if [[ -v NETWORK_NAME && -v NETDEV_NAME && -v LINK_NAME ]]; then
rm -fvr {/usr/lib,/etc}/systemd/network/"$NETWORK_NAME" "/usr/lib/systemd/network/$NETDEV_NAME" \
rm -fvr {/usr/lib,/etc,/run}/systemd/network/"$NETWORK_NAME" "/usr/lib/systemd/network/$NETDEV_NAME" \
{/usr/lib,/etc}/systemd/network/"$LINK_NAME" "/etc/systemd/network/${NETWORK_NAME}.d" \
"new" "+4"
fi
@ -35,9 +35,14 @@ cat >new <<EOF
Name=test2
EOF
EDITOR='mv new' script -ec 'networkctl edit "$NETWORK_NAME"' /dev/null
EDITOR='mv new' script -ec 'networkctl edit --runtime "$NETWORK_NAME"' /dev/null
printf '%s\n' '[Match]' 'Name=test2' | cmp - "/run/systemd/network/$NETWORK_NAME"
EDITOR='true' script -ec 'networkctl edit "$NETWORK_NAME"' /dev/null
printf '%s\n' '[Match]' 'Name=test2' | cmp - "/etc/systemd/network/$NETWORK_NAME"
(! EDITOR='true' script -ec 'networkctl edit --runtime "$NETWORK_NAME"' /dev/null)
cat >"+4" <<EOF
[Network]
IPv6AcceptRA=no
@ -80,6 +85,9 @@ networkctl cat @test2:network | cmp - <(networkctl cat "$NETWORK_NAME")
EDITOR='cp' script -ec 'networkctl edit @test2 --drop-in test2.conf' /dev/null
cmp "+4" "/etc/systemd/network/${NETWORK_NAME}.d/test2.conf"
sleep 1
(! EDITOR='true' script -ec 'networkctl edit @test2 --runtime --drop-in test2.conf' /dev/null)
ip_link="$(ip link show test2)"
if systemctl --quiet is-active systemd-udevd; then
assert_in 'alias test_alias' "$ip_link"