summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2023-05-15 20:01:06 +0200
committerThomas Haller <thaller@redhat.com>2023-05-17 20:27:56 +0200
commit1757e78c7faa386cc7dfb710599aa29ab6984a2e (patch)
treee8c116f06ade3b250736ff6d7521f6b5c685e00b
parent83f928652f27751cea9f23476780b054906a20eb (diff)
downloadNetworkManager-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.c105
-rw-r--r--src/nm-cloud-setup/nm-cloud-setup-utils.h9
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"
/*****************************************************************************/