cloud-setup: parse OCI metadata related to VLAN config

Baremetal instances in Oracle Cloud require special VLAN config. Parse
the metadata related to it.
This commit is contained in:
Íñigo Huguet 2024-11-19 17:04:09 +01:00 committed by Lubomir Rintel
parent dd5b4fcf24
commit 1d412859c0
3 changed files with 82 additions and 2 deletions

View file

@ -13,6 +13,8 @@
#define NM_OCI_HOST "169.254.169.254"
#define NM_OCI_BASE "http://" NM_OCI_HOST
#define MAX_NIC_INDEX 1
NMCS_DEFINE_HOST_BASE(_oci_base, NMCS_ENV_NM_CLOUD_SETUP_OCI_HOST, NM_OCI_BASE);
#define _oci_uri_concat(...) nmcs_utils_uri_build_concat(_oci_base(), "opc/v2/", __VA_ARGS__)
@ -92,6 +94,9 @@ _get_config_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
gs_unref_bytes GBytes *response = NULL;
gs_free_error GError *error = NULL;
nm_auto_decref_json json_t *vnics = NULL;
gboolean is_baremetal;
const char *phys_nic_macs[MAX_NIC_INDEX + 1] = {NULL};
GHashTableIter h_iter;
size_t i;
nm_http_client_poll_req_finish(NM_HTTP_CLIENT(source), result, NULL, &response, &error);
@ -112,12 +117,21 @@ _get_config_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
goto out;
}
if (json_array_size(vnics) > 0) {
is_baremetal = NULL != json_object_get(json_array_get(vnics, 0), "nicIndex");
_LOGI("get-config: detected %s instance", is_baremetal ? "baremetal" : "VM");
} else {
is_baremetal = FALSE;
_LOGI("get-config: empty VNICs metadata, cannot detect instance type");
}
for (i = 0; i < json_array_size(vnics); i++) {
json_t *vnic, *field;
const char *vnic_id = "", *val;
gs_free char *mac = NULL;
in_addr_t addr;
int prefix;
json_int_t nic_index = -1, vlan_tag = -1;
vnic = json_array_get(vnics, i);
if (!json_is_object(vnic)) {
@ -130,12 +144,28 @@ _get_config_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
field = json_object_get(vnic, "macAddr");
val = field && json_is_string(field) ? json_string_value(field) : NULL;
if (!val) {
mac = val ? nmcs_utils_hwaddr_normalize(val, json_string_length(field)) : NULL;
if (!mac) {
_VNIC_WARN("missing or invalid 'macAddr', ignoring VNIC");
continue;
}
mac = nmcs_utils_hwaddr_normalize(val, json_string_length(field));
if (is_baremetal) {
field = json_object_get(vnic, "nicIndex");
nic_index = field && json_is_integer(field) ? json_integer_value(field) : -1;
if (nic_index < 0 || nic_index > MAX_NIC_INDEX) {
_VNIC_WARN("missing or invalid 'nicIndex', ignoring VNIC");
continue;
}
field = json_object_get(vnic, "vlanTag");
vlan_tag = field && json_is_integer(field) ? json_integer_value(field) : -1;
if (vlan_tag < 0) {
_VNIC_WARN("missing or invalid 'vlanTag', ignoring VNIC");
continue;
}
}
config_iface_data = nmcs_provider_get_config_iface_data_create(get_config_data, FALSE, mac);
config_iface_data->iface_idx = i;
@ -168,6 +198,45 @@ _get_config_done_cb(GObject *source, GAsyncResult *result, gpointer user_data)
} else {
_VNIC_WARN("missing or invalid 'subnetCidrBlock'");
}
if (is_baremetal) {
gboolean is_phys_nic = vlan_tag == 0;
/* In baremetal instances, configure VNICs' VLAN (physical NICs don't need it) */
if (is_phys_nic) {
config_iface_data->priv.oci.vlan_tag = 0;
config_iface_data->priv.oci.parent_hwaddr = NULL;
phys_nic_macs[nic_index] = config_iface_data->hwaddr;
} else {
/* We might not have all the physical NICs' MACs yet, save nicIndex for later */
config_iface_data->priv.oci.parent_hwaddr = GINT_TO_POINTER((int) nic_index);
config_iface_data->priv.oci.vlan_tag = vlan_tag;
}
}
}
if (is_baremetal) {
g_hash_table_iter_init(&h_iter, get_config_data->result_dict);
/* Now that all the metadata is processed we should have all the physical NICs' MACs */
while (g_hash_table_iter_next(&h_iter, NULL, (gpointer *) &config_iface_data)) {
bool is_phys_nic = config_iface_data->priv.oci.vlan_tag == 0;
int nic_index = GPOINTER_TO_INT(config_iface_data->priv.oci.parent_hwaddr);
if (is_phys_nic)
continue;
if (phys_nic_macs[nic_index] == NULL) {
_LOGW("get-config: physical NIC for nicIndex=%d not found, ignoring VNIC "
"(VNIC macAddr=%s)",
nic_index,
config_iface_data->hwaddr);
g_hash_table_iter_remove(&h_iter);
continue;
}
config_iface_data->priv.oci.parent_hwaddr = g_strdup(phys_nic_macs[nic_index]);
}
}
out:

View file

@ -203,6 +203,11 @@ nmcs_provider_get_config_iface_data_create(NMCSProviderGetConfigTaskData *get_co
iface_data->priv.aliyun = (typeof(iface_data->priv.aliyun)) {
.has_primary_ip_address = FALSE,
};
} else if (G_OBJECT_TYPE(get_config_data->self) == nmcs_provider_oci_get_type()) {
iface_data->priv.oci = (typeof(iface_data->priv.oci)){
.vlan_tag = 0,
.parent_hwaddr = NULL,
};
}
/* the has does not own the key (iface_datta->hwaddr), the lifetime of the
@ -220,6 +225,8 @@ _iface_data_free(gpointer data)
g_free(iface_data->ipv4s_arr);
nm_g_ptr_array_unref(iface_data->iproutes);
g_free((char *) iface_data->hwaddr);
if (G_OBJECT_TYPE(iface_data->get_config_data->self) == nmcs_provider_oci_get_type())
g_free((char *) iface_data->priv.oci.parent_hwaddr);
nm_g_slice_free(iface_data);
}

View file

@ -51,6 +51,10 @@ typedef struct {
bool has_primary_ip_address : 1;
bool ipv4s_arr_ordered : 1;
} aliyun;
struct {
guint32 vlan_tag; /* 0 if no VLAN is needed */
const char *parent_hwaddr;
} oci;
} priv;
} NMCSProviderGetConfigIfaceData;