Merge pull request #13452 from yuwata/network-reload

network: add networkctl reload and reconfigure
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2019-10-24 11:07:24 +02:00 committed by GitHub
commit 1048436869
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 362 additions and 67 deletions

View file

@ -261,6 +261,25 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR)
Takes interface name or index number.</para></listitem>
</varlistentry>
<varlistentry>
<term>
<command>reconfigure</command>
</term>
<listitem><para>Reconfigure network interfaces. Takes interface name or index number.</para></listitem>
</varlistentry>
<varlistentry>
<term>
<command>reload</command>
</term>
<listitem><para>Reload <filename>.netdev</filename> and <filename>.network</filename> files.
If a new <filename>.netdev</filename> file is found, then the corresponding netdev is created.
Note that even if an existing <filename>.netdev</filename> is modified or removed,
<command>systemd-networkd</command> does not update or remove the netdev.
If a new, modified or removed <filename>.network</filename> file is found, then all interfaces
which match the file are reconfigured.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>

View file

@ -4,11 +4,24 @@
#include "format-util.h"
#include "memory-util.h"
#include "stdio-util.h"
char *format_ifname(int ifindex, char buf[static IF_NAMESIZE + 1]) {
assert_cc(DECIMAL_STR_MAX(int) + 1 <= IF_NAMESIZE + 1);
char *format_ifname_full(int ifindex, char buf[static IF_NAMESIZE + 1], FormatIfnameFlag flag) {
/* Buffer is always cleared */
memzero(buf, IF_NAMESIZE + 1);
return if_indextoname(ifindex, buf);
if (if_indextoname(ifindex, buf))
return buf;
if (!FLAGS_SET(flag, FORMAT_IFNAME_IFINDEX))
return NULL;
if (FLAGS_SET(flag, FORMAT_IFNAME_IFINDEX_WITH_PERCENT))
snprintf(buf, IF_NAMESIZE + 1, "%%%d", ifindex);
else
snprintf(buf, IF_NAMESIZE + 1, "%d", ifindex);
return buf;
}
char *format_bytes_full(char *buf, size_t l, uint64_t t, FormatBytesFlag flag) {

View file

@ -68,7 +68,15 @@
# error Unknown ino_t size
#endif
char *format_ifname(int ifindex, char buf[static IF_NAMESIZE + 1]);
typedef enum {
FORMAT_IFNAME_IFINDEX = 1 << 0,
FORMAT_IFNAME_IFINDEX_WITH_PERCENT = (1 << 1) | FORMAT_IFNAME_IFINDEX,
} FormatIfnameFlag;
char *format_ifname_full(int ifindex, char buf[static IF_NAMESIZE + 1], FormatIfnameFlag flag);
static inline char *format_ifname(int ifindex, char buf[static IF_NAMESIZE + 1]) {
return format_ifname_full(ifindex, buf, 0);
}
typedef enum {
FORMAT_BYTES_USE_IEC = 1 << 0,

View file

@ -23,6 +23,6 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
fflush(f);
assert_se(manager_new(&manager) >= 0);
(void) network_load_one(manager, network_config);
(void) network_load_one(manager, &manager->networks, network_config);
return 0;
}

View file

@ -757,9 +757,10 @@ int netdev_load_one(Manager *manager, const char *filename) {
NetDev *n = hashmap_get(netdev->manager->netdevs, netdev->ifname);
assert(n);
log_netdev_warning_errno(netdev, r,
"The setting Name=%s in %s conflicts with the one in %s, ignoring",
netdev->ifname, netdev->filename, n->filename);
if (!streq(netdev->filename, n->filename))
log_netdev_warning_errno(netdev, r,
"The setting Name=%s in %s conflicts with the one in %s, ignoring",
netdev->ifname, netdev->filename, n->filename);
/* Clear ifname before netdev_free() is called. Otherwise, the NetDev object 'n' is
* removed from the hashmap 'manager->netdevs'. */
@ -828,14 +829,15 @@ int netdev_load_one(Manager *manager, const char *filename) {
return 0;
}
int netdev_load(Manager *manager) {
int netdev_load(Manager *manager, bool reload) {
_cleanup_strv_free_ char **files = NULL;
char **f;
int r;
assert(manager);
hashmap_clear_with_destructor(manager->netdevs, netdev_unref);
if (!reload)
hashmap_clear_with_destructor(manager->netdevs, netdev_unref);
r = conf_files_list_strv(&files, ".netdev", NULL, 0, NETWORK_DIRS);
if (r < 0)

View file

@ -156,7 +156,7 @@ extern const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX];
/* For casting the various netdev kinds into a netdev */
#define NETDEV(n) (&(n)->meta)
int netdev_load(Manager *manager);
int netdev_load(Manager *manager, bool reload);
int netdev_load_one(Manager *manager, const char *filename);
void netdev_drop(NetDev *netdev);

View file

@ -719,10 +719,8 @@ static int dump_gateways(
if (ifindex <= 0) {
char name[IF_NAMESIZE+1];
if (format_ifname(local[i].ifindex, name))
r = table_add_cell_stringf(table, NULL, "%s on %s", with_description ?: gateway, name);
else
r = table_add_cell_stringf(table, NULL, "%s on %%%i", with_description ?: gateway, local[i].ifindex);
r = table_add_cell_stringf(table, NULL, "%s on %s", with_description ?: gateway,
format_ifname_full(local[i].ifindex, name, FORMAT_IFNAME_IFINDEX_WITH_PERCENT));
} else
r = table_add_cell(table, NULL, TABLE_STRING, with_description ?: gateway);
if (r < 0)
@ -775,10 +773,8 @@ static int dump_addresses(
if (ifindex <= 0) {
char name[IF_NAMESIZE+1];
if (format_ifname(local[i].ifindex, name))
r = table_add_cell_stringf(table, NULL, "%s on %s", pretty, name);
else
r = table_add_cell_stringf(table, NULL, "%s on %%%i", pretty, local[i].ifindex);
r = table_add_cell_stringf(table, NULL, "%s on %s", pretty,
format_ifname_full(local[i].ifindex, name, FORMAT_IFNAME_IFINDEX_WITH_PERCENT));
} else
r = table_add_cell(table, NULL, TABLE_STRING, pretty);
if (r < 0)
@ -1759,14 +1755,13 @@ static int link_delete(int argc, char *argv[], void *userdata) {
}
SET_FOREACH(p, indexes, j) {
r = link_delete_send_message(rtnl, PTR_TO_INT(p));
index = PTR_TO_INT(p);
r = link_delete_send_message(rtnl, index);
if (r < 0) {
char ifname[IF_NAMESIZE + 1];
if (format_ifname(index, ifname))
return log_error_errno(r, "Failed to delete interface %s: %m", ifname);
else
return log_error_errno(r, "Failed to delete interface %d: %m", index);
return log_error_errno(r, "Failed to delete interface %s: %m",
format_ifname_full(index, ifname, FORMAT_IFNAME_IFINDEX));
}
}
@ -1815,6 +1810,73 @@ static int link_renew(int argc, char *argv[], void *userdata) {
}
static int verb_reload(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
r = sd_bus_open_system(&bus);
if (r < 0)
return log_error_errno(r, "Failed to connect system bus: %m");
r = sd_bus_call_method(
bus,
"org.freedesktop.network1",
"/org/freedesktop/network1",
"org.freedesktop.network1.Manager",
"Reload",
&error, NULL, NULL);
if (r < 0)
return log_error_errno(r, "Failed to reload network settings: %m");
return 0;
}
static int verb_reconfigure(int argc, char *argv[], void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
_cleanup_set_free_ Set *indexes = NULL;
int index, i, r;
Iterator j;
void *p;
r = sd_bus_open_system(&bus);
if (r < 0)
return log_error_errno(r, "Failed to connect system bus: %m");
indexes = set_new(NULL);
if (!indexes)
return log_oom();
for (i = 1; i < argc; i++) {
r = parse_ifindex_or_ifname(argv[i], &index);
if (r < 0)
return log_error_errno(r, "Failed to resolve interface %s", argv[i]);
r = set_put(indexes, INT_TO_PTR(index));
if (r < 0)
return log_oom();
}
SET_FOREACH(p, indexes, j) {
index = PTR_TO_INT(p);
r = sd_bus_call_method(
bus,
"org.freedesktop.network1",
"/org/freedesktop/network1",
"org.freedesktop.network1.Manager",
"ReconfigureLink",
&error, NULL, "i", index);
if (r < 0) {
char ifname[IF_NAMESIZE + 1];
return log_error_errno(r, "Failed to reconfigure network interface %s: %m", format_ifname_full(index, ifname, FORMAT_IFNAME_IFINDEX));
}
}
return 0;
}
static int help(void) {
_cleanup_free_ char *link = NULL;
int r;
@ -1826,19 +1888,21 @@ static int help(void) {
printf("%s%s [OPTIONS...]\n\n"
"Query and control the networking subsystem.%s\n"
"\nCommands:\n"
" list [PATTERN...] List links\n"
" status [PATTERN...] Show link status\n"
" lldp [PATTERN...] Show LLDP neighbors\n"
" label Show current address label entries in the kernel\n"
" delete DEVICES... Delete virtual netdevs\n"
" renew DEVICES... Renew dynamic configurations\n"
" list [PATTERN...] List links\n"
" status [PATTERN...] Show link status\n"
" lldp [PATTERN...] Show LLDP neighbors\n"
" label Show current address label entries in the kernel\n"
" delete DEVICES... Delete virtual netdevs\n"
" renew DEVICES... Renew dynamic configurations\n"
" reconfigure DEVICES... Reconfigure interfaces\n"
" reload Reload .network and .netdev files\n"
"\nOptions\n"
" -h --help Show this help\n"
" --version Show package version\n"
" --no-pager Do not pipe output into a pager\n"
" --no-legend Do not show the headers and footers\n"
" -a --all Show status for all links\n"
" -s --stats Show detailed link statics\n"
" -h --help Show this help\n"
" --version Show package version\n"
" --no-pager Do not pipe output into a pager\n"
" --no-legend Do not show the headers and footers\n"
" -a --all Show status for all links\n"
" -s --stats Show detailed link statics\n"
"\nSee the %s for details.\n"
, ansi_highlight()
, program_invocation_short_name
@ -1911,12 +1975,14 @@ static int parse_argv(int argc, char *argv[]) {
static int networkctl_main(int argc, char *argv[]) {
static const Verb verbs[] = {
{ "list", VERB_ANY, VERB_ANY, VERB_DEFAULT, list_links },
{ "status", VERB_ANY, VERB_ANY, 0, link_status },
{ "lldp", VERB_ANY, VERB_ANY, 0, link_lldp_status },
{ "label", VERB_ANY, VERB_ANY, 0, list_address_labels },
{ "delete", 2, VERB_ANY, 0, link_delete },
{ "renew", 2, VERB_ANY, 0, link_renew },
{ "list", VERB_ANY, VERB_ANY, VERB_DEFAULT, list_links },
{ "status", VERB_ANY, VERB_ANY, 0, link_status },
{ "lldp", VERB_ANY, VERB_ANY, 0, link_lldp_status },
{ "label", VERB_ANY, VERB_ANY, 0, list_address_labels },
{ "delete", 2, VERB_ANY, 0, link_delete },
{ "renew", 2, VERB_ANY, 0, link_renew },
{ "reconfigure", 2, VERB_ANY, 0, verb_reconfigure },
{ "reload", 1, 1, 0, verb_reload },
{}
};

View file

@ -604,6 +604,29 @@ int bus_link_method_renew(sd_bus_message *message, void *userdata, sd_bus_error
return sd_bus_reply_method_return(message, NULL);
}
int bus_link_method_reconfigure(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Link *l = userdata;
int r;
assert(message);
assert(l);
r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
"org.freedesktop.network1.reconfigure",
NULL, true, UID_INVALID,
&l->manager->polkit_registry, error);
if (r < 0)
return r;
if (r == 0)
return 1; /* Polkit will call us back */
r = link_reconfigure(l, true);
if (r < 0)
return r;
return sd_bus_reply_method_return(message, NULL);
}
const sd_bus_vtable link_vtable[] = {
SD_BUS_VTABLE_START(0),
@ -625,6 +648,7 @@ const sd_bus_vtable link_vtable[] = {
SD_BUS_METHOD("RevertNTP", NULL, NULL, bus_link_method_revert_ntp, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("RevertDNS", NULL, NULL, bus_link_method_revert_dns, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Renew", NULL, NULL, bus_link_method_renew, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Reconfigure", NULL, NULL, bus_link_method_reconfigure, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_VTABLE_END
};

View file

@ -31,3 +31,4 @@ int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, v
int bus_link_method_revert_ntp(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_link_method_revert_dns(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_link_method_renew(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_link_method_reconfigure(sd_bus_message *message, void *userdata, sd_bus_error *error);

View file

@ -2857,7 +2857,7 @@ static int link_configure_duid(Link *link) {
return 0;
}
int link_reconfigure(Link *link) {
int link_reconfigure(Link *link, bool force) {
Network *network;
int r;
@ -2875,7 +2875,7 @@ int link_reconfigure(Link *link) {
} else if (r < 0)
return r;
if (link->network == network)
if (link->network == network && !force)
return 0;
log_link_info(link, "Re-configuring with %s", network->filename);
@ -3337,7 +3337,7 @@ static int link_carrier_gained(Link *link) {
if (r < 0)
return r;
if (r > 0) {
r = link_reconfigure(link);
r = link_reconfigure(link, false);
if (r < 0)
return r;
}

View file

@ -208,7 +208,7 @@ uint32_t link_get_ipv6_accept_ra_route_table(Link *link);
int link_request_set_routes(Link *link);
int link_request_set_nexthop(Link *link);
int link_reconfigure(Link *link);
int link_reconfigure(Link *link, bool force);
#define ADDRESS_FMT_VAL(address) \
be32toh((address).s_addr) >> 24, \

View file

@ -1,6 +1,8 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <net/if.h>
#include <netinet/in.h>
#include <sys/capability.h>
#include "alloc-util.h"
#include "bus-common-errors.h"
@ -11,6 +13,7 @@
#include "networkd-manager.h"
#include "path-util.h"
#include "strv.h"
#include "user-util.h"
static int method_list_links(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
@ -187,6 +190,42 @@ static int bus_method_renew_link(sd_bus_message *message, void *userdata, sd_bus
return call_link_method(userdata, message, bus_link_method_renew, error);
}
static int bus_method_reconfigure_link(sd_bus_message *message, void *userdata, sd_bus_error *error) {
return call_link_method(userdata, message, bus_link_method_reconfigure, error);
}
static int bus_method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *manager = userdata;
Iterator i;
Link *link;
int r;
r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
"org.freedesktop.network1.reload",
NULL, true, UID_INVALID,
&manager->polkit_registry, error);
if (r < 0)
return r;
if (r == 0)
return 1; /* Polkit will call us back */
r = netdev_load(manager, true);
if (r < 0)
return r;
r = network_reload(manager);
if (r < 0)
return r;
HASHMAP_FOREACH(link, manager->links, i) {
r = link_reconfigure(link, false);
if (r < 0)
return r;
}
return sd_bus_reply_method_return(message, NULL);
}
const sd_bus_vtable manager_vtable[] = {
SD_BUS_VTABLE_START(0),
@ -209,6 +248,8 @@ const sd_bus_vtable manager_vtable[] = {
SD_BUS_METHOD("RevertLinkNTP", "i", NULL, bus_method_revert_link_ntp, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("RevertLinkDNS", "i", NULL, bus_method_revert_link_dns, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("RenewLink", "i", NULL, bus_method_renew_link, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ReconfigureLink", "i", NULL, bus_method_reconfigure_link, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Reload", NULL, NULL, bus_method_reload, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_VTABLE_END
};

View file

@ -1856,11 +1856,11 @@ int manager_load_config(Manager *m) {
/* update timestamp */
paths_check_timestamp(NETWORK_DIRS, &m->network_dirs_ts_usec, true);
r = netdev_load(m);
r = netdev_load(m, false);
if (r < 0)
return r;
r = network_load(m);
r = network_load(m, &m->networks);
if (r < 0)
return r;

View file

@ -314,7 +314,7 @@ int network_verify(Network *network) {
return 0;
}
int network_load_one(Manager *manager, const char *filename) {
int network_load_one(Manager *manager, OrderedHashmap **networks, const char *filename) {
_cleanup_free_ char *fname = NULL, *name = NULL;
_cleanup_(network_unrefp) Network *network = NULL;
_cleanup_fclose_ FILE *file = NULL;
@ -488,36 +488,42 @@ int network_load_one(Manager *manager, const char *filename) {
log_warning_errno(r, "%s: Failed to add default route on device, ignoring: %m",
network->filename);
r = ordered_hashmap_ensure_allocated(&manager->networks, &string_hash_ops);
if (r < 0)
return r;
r = ordered_hashmap_put(manager->networks, network->name, network);
if (r < 0)
return r;
struct stat stats;
if (stat(filename, &stats) < 0)
return -errno;
network->timestamp = timespec_load(&stats.st_mtim);
if (network_verify(network) < 0)
/* Ignore .network files that do not match the conditions. */
return 0;
r = ordered_hashmap_ensure_allocated(networks, &string_hash_ops);
if (r < 0)
return r;
r = ordered_hashmap_put(*networks, network->name, network);
if (r < 0)
return r;
network = NULL;
return 0;
}
int network_load(Manager *manager) {
int network_load(Manager *manager, OrderedHashmap **networks) {
_cleanup_strv_free_ char **files = NULL;
char **f;
int r;
assert(manager);
ordered_hashmap_clear_with_destructor(manager->networks, network_unref);
ordered_hashmap_clear_with_destructor(*networks, network_unref);
r = conf_files_list_strv(&files, ".network", NULL, 0, NETWORK_DIRS);
if (r < 0)
return log_error_errno(r, "Failed to enumerate network files: %m");
STRV_FOREACH(f, files) {
r = network_load_one(manager, *f);
r = network_load_one(manager, networks, *f);
if (r < 0)
log_error_errno(r, "Failed to load %s, ignoring: %m", *f);
}
@ -525,6 +531,48 @@ int network_load(Manager *manager) {
return 0;
}
int network_reload(Manager *manager) {
OrderedHashmap *new_networks = NULL;
Network *n, *old;
Iterator i;
int r;
assert(manager);
r = network_load(manager, &new_networks);
if (r < 0)
goto failure;
ORDERED_HASHMAP_FOREACH(n, new_networks, i) {
r = network_get_by_name(manager, n->name, &old);
if (r < 0)
continue; /* The .network file is new. */
if (n->timestamp != old->timestamp)
continue; /* The .network file is modified. */
if (!streq(n->filename, old->filename))
continue;
r = ordered_hashmap_replace(new_networks, old->name, old);
if (r < 0)
goto failure;
network_ref(old);
network_unref(n);
}
ordered_hashmap_free_with_destructor(manager->networks, network_unref);
manager->networks = new_networks;
return 0;
failure:
ordered_hashmap_free_with_destructor(new_networks, network_unref);
return r;
}
static Network *network_free(Network *network) {
IPv6ProxyNDPAddress *ipv6_proxy_ndp_address;
RoutingPolicyRule *rule;
@ -615,13 +663,9 @@ static Network *network_free(Network *network) {
hashmap_free(network->prefixes_by_section);
hashmap_free(network->rules_by_section);
if (network->manager) {
if (network->manager->networks && network->name)
ordered_hashmap_remove(network->manager->networks, network->name);
if (network->manager->duids_requesting_uuid)
set_remove(network->manager->duids_requesting_uuid, &network->duid);
}
if (network->manager &&
network->manager->duids_requesting_uuid)
set_remove(network->manager->duids_requesting_uuid, &network->duid);
free(network->name);

View file

@ -54,6 +54,7 @@ struct Network {
char *filename;
char *name;
usec_t timestamp;
unsigned n_ref;
@ -283,8 +284,9 @@ Network *network_ref(Network *network);
Network *network_unref(Network *network);
DEFINE_TRIVIAL_CLEANUP_FUNC(Network*, network_unref);
int network_load(Manager *manager);
int network_load_one(Manager *manager, const char *filename);
int network_load(Manager *manager, OrderedHashmap **networks);
int network_reload(Manager *manager);
int network_load_one(Manager *manager, OrderedHashmap **networks, const char *filename);
int network_verify(Network *network);
int network_get_by_name(Manager *manager, const char *name, Network **ret);

View file

@ -150,4 +150,26 @@
<annotate key="org.freedesktop.policykit.owner">unix-user:systemd-network</annotate>
</action>
<action id="org.freedesktop.network1.reload">
<description gettext-domain="systemd">Reload network settings</description>
<message gettext-domain="systemd">Authentication is required to reload network settings.</message>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.owner">unix-user:systemd-network</annotate>
</action>
<action id="org.freedesktop.network1.reconfigure">
<description gettext-domain="systemd">Reconfigure network interface</description>
<message gettext-domain="systemd">Authentication is required to reconfigure network interface.</message>
<defaults>
<allow_any>auth_admin</allow_any>
<allow_inactive>auth_admin</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.owner">unix-user:systemd-network</annotate>
</action>
</policyconfig>

View file

@ -380,6 +380,7 @@ class Utilities():
class NetworkctlTests(unittest.TestCase, Utilities):
links = [
'dummy98',
'test1',
'veth99',
]
@ -388,6 +389,8 @@ class NetworkctlTests(unittest.TestCase, Utilities):
'11-dummy.netdev',
'11-dummy-mtu.netdev',
'11-dummy.network',
'12-dummy.netdev',
'25-address-static.network',
'25-veth.netdev',
'netdev-link-local-addressing-yes.network',
]
@ -401,6 +404,56 @@ class NetworkctlTests(unittest.TestCase, Utilities):
remove_unit_from_networkd_path(self.units)
stop_networkd(show_logs=True)
def test_reconfigure(self):
copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
start_networkd()
self.wait_online(['dummy98:routable'])
output = check_output('ip -4 address show dev dummy98')
print(output)
self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
check_output('ip address del 10.1.2.3/16 dev dummy98')
check_output('ip address del 10.1.2.4/16 dev dummy98')
check_output('ip address del 10.2.2.4/16 dev dummy98')
check_output(*networkctl_cmd, 'reconfigure', 'dummy98', env=env)
self.wait_online(['dummy98:routable'])
output = check_output('ip -4 address show dev dummy98')
print(output)
self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
self.assertRegex(output, 'inet 10.2.2.4/16 brd 10.2.255.255 scope global dummy98')
def test_reload(self):
start_networkd(3)
copy_unit_to_networkd_unit_path('11-dummy.netdev')
check_output(*networkctl_cmd, 'reload', env=env)
time.sleep(3)
self.check_link_exists('test1')
self.check_operstate('test1', 'off', setup_state='unmanaged')
copy_unit_to_networkd_unit_path('11-dummy.network')
check_output(*networkctl_cmd, 'reload', env=env)
self.wait_online(['test1:degraded'])
remove_unit_from_networkd_path(['11-dummy.network'])
check_output(*networkctl_cmd, 'reload', env=env)
time.sleep(1)
self.check_operstate('test1', 'degraded', setup_state='unmanaged')
remove_unit_from_networkd_path(['11-dummy.netdev'])
check_output(*networkctl_cmd, 'reload', env=env)
self.check_operstate('test1', 'degraded', setup_state='unmanaged')
copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
check_output(*networkctl_cmd, 'reload', env=env)
self.check_operstate('test1', 'degraded')
def test_glob(self):
copy_unit_to_networkd_unit_path('11-dummy.netdev', '11-dummy.network')
start_networkd()