diff options
author | Thomas Haller <thaller@redhat.com> | 2023-05-15 20:01:06 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2023-05-17 20:27:56 +0200 |
commit | 1757e78c7faa386cc7dfb710599aa29ab6984a2e (patch) | |
tree | e8c116f06ade3b250736ff6d7521f6b5c685e00b | |
parent | 83f928652f27751cea9f23476780b054906a20eb (diff) | |
download | NetworkManager-1757e78c7faa386cc7dfb710599aa29ab6984a2e.tar.gz |
cloud-setup: allow mapping device for testing
In production systems, the associate an interface by their permanate MAC address.
For testing and CI, we may want to hook that. That allows for example to run
nm-cloud-setup on a veth interface, which doesn't have a permanent MAC address.
This is only for testing.
-rw-r--r-- | src/nm-cloud-setup/main.c | 105 | ||||
-rw-r--r-- | src/nm-cloud-setup/nm-cloud-setup-utils.h | 9 |
2 files changed, 108 insertions, 6 deletions
diff --git a/src/nm-cloud-setup/main.c b/src/nm-cloud-setup/main.c index d9a4a51e21..0a0a1ab7e6 100644 --- a/src/nm-cloud-setup/main.c +++ b/src/nm-cloud-setup/main.c @@ -123,6 +123,107 @@ out: /*****************************************************************************/ +static NMUtilsNamedValue * +_map_interfaces_parse(void) +{ + gs_free const char **split = NULL; + NMUtilsNamedValue *map_interfaces; + const char *env_var; + gsize i; + gsize j; + gsize alloc_len; + + env_var = g_getenv(NMCS_ENV_NM_CLOUD_SETUP_MAP_INTERFACES); + + if (nm_str_is_empty(env_var)) + return NULL; + + split = nm_strsplit_set_full(env_var, ";", NM_STRSPLIT_SET_FLAGS_STRSTRIP); + + alloc_len = NM_PTRARRAY_LEN(split) + 1u; + + map_interfaces = g_new(NMUtilsNamedValue, alloc_len); + + _LOGD("test: map interfaces via NM_CLOUD_SETUP_MAP_INTERFACES=\"%s\"", env_var); + + for (i = 0, j = 0; split && split[i]; i++) { + NMUtilsNamedValue *m; + const char *str = split[i]; + char *hwaddr; + const char *s; + + s = strchr(str, '='); + if (!s || str == s) + continue; + + hwaddr = nmcs_utils_hwaddr_normalize(&s[1], -1); + if (!hwaddr) + continue; + + nm_assert(j < alloc_len); + m = &map_interfaces[j++]; + + *m = (NMUtilsNamedValue){ + .name = g_strndup(str, s - str), + .value_str = hwaddr, + }; + + _LOGD("test: map \"%s\" -> %s", m->name, m->value_str); + } + + nm_assert(j < alloc_len); + map_interfaces[j++] = (NMUtilsNamedValue){ + .name = NULL, + .value_str = NULL, + }; + + return g_steal_pointer(&map_interfaces); +} + +static const char * +_device_get_hwaddr(NMDeviceEthernet *device) +{ + static const NMUtilsNamedValue *gl_map_interfaces_map = NULL; + static gsize gl_initialized = 0; + const NMUtilsNamedValue *map = NULL; + + nm_assert(NM_IS_DEVICE_ETHERNET(device)); + + /* Network interfaces in cloud environments are identified by their permanent + * MAC address. + * + * For testing, we can set NMCS_ENV_NM_CLOUD_SETUP_MAP_INTERFACES + * to a ';' separate list of "$INTERFACE=$HWADDR", which means that we + * pretend that device with ip-interface "$INTERFACE" has the specified permanent + * MAC address. */ + + if (g_once_init_enter(&gl_initialized)) { + gl_map_interfaces_map = _map_interfaces_parse(); + g_once_init_leave(&gl_initialized, 1); + } + + map = gl_map_interfaces_map; + if (G_UNLIKELY(map)) { + const char *const iface = nm_device_get_iface(NM_DEVICE(device)); + + /* For testing, the device<->hwaddr is remapped and the actual permanent + * MAC address of the device ignored. This mapping is configured via + * NMCS_ENV_NM_CLOUD_SETUP_MAP_INTERFACES environment variable. */ + + if (!iface) + return NULL; + + for (; map->name; map++) { + if (nm_streq(map->name, iface)) + return map->value_str; + } + + return NULL; + } + + return nm_device_ethernet_get_permanent_hw_address(device); +} + static char ** _nmc_get_hwaddrs(NMClient *nmc) { @@ -145,7 +246,7 @@ _nmc_get_hwaddrs(NMClient *nmc) if (nm_device_get_state(device) < NM_DEVICE_STATE_UNAVAILABLE) continue; - hwaddr = nm_device_ethernet_get_permanent_hw_address(NM_DEVICE_ETHERNET(device)); + hwaddr = _device_get_hwaddr(NM_DEVICE_ETHERNET(device)); if (!hwaddr) continue; @@ -187,7 +288,7 @@ _nmc_get_device_by_hwaddr(NMClient *nmc, const char *hwaddr) if (!NM_IS_DEVICE_ETHERNET(device)) continue; - hwaddr_dev = nm_device_ethernet_get_permanent_hw_address(NM_DEVICE_ETHERNET(device)); + hwaddr_dev = _device_get_hwaddr(NM_DEVICE_ETHERNET(device)); if (!hwaddr_dev) continue; diff --git a/src/nm-cloud-setup/nm-cloud-setup-utils.h b/src/nm-cloud-setup/nm-cloud-setup-utils.h index e4c7a28534..5b34f49d4d 100644 --- a/src/nm-cloud-setup/nm-cloud-setup-utils.h +++ b/src/nm-cloud-setup/nm-cloud-setup-utils.h @@ -16,10 +16,11 @@ /* Undocumented/internal environment variables for configuring nm-cloud-setup. * These are mainly for testing/debugging. */ -#define NMCS_ENV_NM_CLOUD_SETUP_ALIYUN_HOST "NM_CLOUD_SETUP_ALIYUN_HOST" -#define NMCS_ENV_NM_CLOUD_SETUP_AZURE_HOST "NM_CLOUD_SETUP_AZURE_HOST" -#define NMCS_ENV_NM_CLOUD_SETUP_EC2_HOST "NM_CLOUD_SETUP_EC2_HOST" -#define NMCS_ENV_NM_CLOUD_SETUP_GCP_HOST "NM_CLOUD_SETUP_GCP_HOST" +#define NMCS_ENV_NM_CLOUD_SETUP_ALIYUN_HOST "NM_CLOUD_SETUP_ALIYUN_HOST" +#define NMCS_ENV_NM_CLOUD_SETUP_AZURE_HOST "NM_CLOUD_SETUP_AZURE_HOST" +#define NMCS_ENV_NM_CLOUD_SETUP_EC2_HOST "NM_CLOUD_SETUP_EC2_HOST" +#define NMCS_ENV_NM_CLOUD_SETUP_GCP_HOST "NM_CLOUD_SETUP_GCP_HOST" +#define NMCS_ENV_NM_CLOUD_SETUP_MAP_INTERFACES "NM_CLOUD_SETUP_MAP_INTERFACES" /*****************************************************************************/ |