Skip to content

Commit

Permalink
v15:
Browse files Browse the repository at this point in the history
- use dhcp6 on ipv6 only primary vnics
  • Loading branch information
a-dubs committed Oct 9, 2024
1 parent 21c3018 commit f950064
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 17 deletions.
22 changes: 12 additions & 10 deletions cloudinit/sources/DataSourceOracle.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,7 @@ def ds_detect() -> bool:
def _get_data(self):

self.system_uuid = _read_system_uuid()
iface = (net.find_fallback_nic(),)
# Convert tuple to string
nic_name = "".join(iface)
nic_name = net.find_fallback_nic()

ipv4_connectivity_url_data = {
"url": IPV4_METADATA_PATTERN.format(version=1, path="instance"),
Expand Down Expand Up @@ -370,28 +368,33 @@ def _add_network_config_from_opc_imds(self, set_primary: bool = False):
vnics_data = self._vnics_data if set_primary else self._vnics_data[1:]

# If the metadata address is an IPv6 address
is_ipv6 = _is_ipv6_metadata_url(self.metadata_address)

for index, vnic_dict in enumerate(vnics_data):
is_primary = set_primary and index == 0
mac_address = vnic_dict["macAddr"].lower()
is_ipv6_only = (vnic_dict.get("ipv6SubnetCidrBlock", False)
and not vnic_dict.get("privateIp", False))
if mac_address not in interfaces_by_mac:
LOG.warning(
"Interface with MAC %s not found; skipping",
mac_address,
)
continue
name = interfaces_by_mac[mac_address]
if is_ipv6:
if is_ipv6_only:
network = ipaddress.ip_network(
vnic_dict["ipv6SubnetCidrBlock"]
vnic_dict["ipv6Addresses"][0],
# strict=False,
)
else:
network = ipaddress.ip_network(vnic_dict["subnetCidrBlock"])

if self._network_config["version"] == 1:
if is_primary:
subnets = [{"type": "dhcp"}]
if is_ipv6_only:
subnets = [{"type": "dhcp6"}]
else:
subnets = [{"type": "dhcp"}]
else:
subnets = []
if vnic_dict.get("privateIp"):
Expand All @@ -408,7 +411,6 @@ def _add_network_config_from_opc_imds(self, set_primary: bool = False):
f"{vnic_dict['ipv6Addresses'][0]}/{network.prefixlen}"
),
})

interface_config = {
"name": name,
"type": "physical",
Expand All @@ -426,8 +428,8 @@ def _add_network_config_from_opc_imds(self, set_primary: bool = False):
}
self._network_config["ethernets"][name] = interface_config

interface_config["dhcp6"] = False
interface_config["dhcp4"] = is_primary
interface_config["dhcp6"] = is_primary and is_ipv6_only
interface_config["dhcp4"] = is_primary and not is_ipv6_only
if not is_primary:
interface_config["addresses"] = []
if vnic_dict.get("privateIp"):
Expand Down
130 changes: 123 additions & 7 deletions tests/unittests/sources/test_oracle.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"virtualRouterIp" : "10.0.0.1",
"subnetCidrBlock" : "10.0.0.0/24"
} ]"""

###############################################################################
OPC_VM_DUAL_STACK_SECONDARY_VNIC_RESPONSE = """\
[
{
Expand All @@ -73,7 +73,7 @@
"subnetCidrBlock": "10.0.0.0/24",
"virtualRouterIp": "10.0.0.1",
"vlanTag": 929,
"vnicId": "ocid1.vnic.oc1.iad.abuwcljtr2b6363afca55nzerlvwmfhxpqr4ij7dni4uiltqryx3vwyzpxdq"
"vnicId": "ocid1.vnic.oc1.iad.abuwcljtr2b6363afca55nzerlvwmfhxp_truncated"
},
{
"ipv6Addresses": [
Expand All @@ -84,9 +84,33 @@
"macAddr": "02:00:17:18:F6:FF",
"subnetCidrBlock": "\u003cnull\u003e",
"vlanTag": 2659,
"vnicId": "ocid1.vnic.oc1.iad.abuwcljtpfktyl2e3xm2ez4spj7wiliyclj5bpakhcric7ipykzdx7lxcikq"
"vnicId": "ocid1.vnic.oc1.iad.abuwcljtpfktyl2e3xm2ez4spj7wiliyc_truncated"
}
]"""
OPC_VM_IPV6_ONLY_SECONDARY_VNIC_RESPONSE = """\
[
{
"ipv6Addresses": [
"2603:c020:400d:5dbb:e94a:a85d:26e3:e0d4"
],
"ipv6SubnetCidrBlock": "2603:c020:400d:5dbb::/64",
"ipv6VirtualRouterIp": "fe80::200:17ff:fe40:8972",
"macAddr": "02:00:17:0D:6B:BE",
"vlanTag": 929,
"vnicId": "ocid1.vnic.oc1.iad.abuwcljtr2b6363afca55nzerlvwmfhxp_truncated"
},
{
"ipv6Addresses": [
"2603:c020:400d:5d7e:aacc:8e5f:3b1b:3a4a"
],
"ipv6SubnetCidrBlock": "2603:c020:400d:5d7e::/64",
"ipv6VirtualRouterIp": "fe80::200:17ff:fe40:8972",
"macAddr": "02:00:17:18:F6:FF",
"vlanTag": 2659,
"vnicId": "ocid1.vnic.oc1.iad.abuwcljtpfktyl2e3xm2ez4spj7wiliyc_truncated"
}
]"""
###############################################################################

OPC_DUAL_STACK_VM_VNIC_RESPONSE = """\
[
Expand All @@ -101,7 +125,7 @@
"subnetCidrBlock": "10.0.0.0/24",
"virtualRouterIp": "10.0.0.1",
"vlanTag": 929,
"vnicId": "ocid1.vnic.oc1.iad.abuwcljtr2b6363afca55nzerlvwmfhxpqr4ij7dni4uiltqryx3vwyzpxdq"
"vnicId": "ocid1.vnic.oc1.iad.abuwcljtr2b6363afca55nzerlvwmfhxp_truncated"
}
]"""

Expand All @@ -118,7 +142,7 @@
"subnetCidrBlock": "10.0.0.0/24",
"virtualRouterIp": "10.0.0.1",
"vlanTag": 929,
"vnicId": "ocid1.vnic.oc1.iad.abuwcljtr2b6363afca55nzerlvwmfhxpqr4ij7dni4uiltqryx3vwyzpxdq"
"vnicId": "ocid1.vnic.oc1.iad.abuwcljtr2b6363afca55nzerlvwmfhx4_truncated"
},
{
"ipv6Addresses": [
Expand All @@ -129,7 +153,7 @@
"macAddr": "02:00:17:18:F6:FF",
"subnetCidrBlock": "\u003cnull\u003e",
"vlanTag": 2659,
"vnicId": "ocid1.vnic.oc1.iad.abuwcljtpfktyl2e3xm2ez4spj7wiliyclj5bpakhcric7ipykzdx7lxcikq"
"vnicId": "ocid1.vnic.oc1.iad.abuwcljtpfktyl2e3xm2ez4spj7wiliy_truncated"
}
]"""

Expand All @@ -143,7 +167,7 @@
"ipv6VirtualRouterIp": "fe80::200:17ff:fe40:8972",
"macAddr": "02:00:17:15:92:4E",
"vlanTag": 1970,
"vnicId": "ocid1.vnic.oc1.iad.abuwcljtqdmvgobi2kewwmgxybt5uyf6mnimho2pai4xa76pr4dbfckookgq"
"vnicId": "ocid1.vnic.oc1.iad.abuwcljtpfktyl2e3xm2ez4spj7wiliy_truncated"
}
]"""

Expand Down Expand Up @@ -521,6 +545,98 @@ def test_secondary_nic_v2(self, set_primary, oracle_ds):
assert 1 == len(secondary_cfg["addresses"])
assert "10.0.0.231/24" == secondary_cfg["addresses"][0]


@pytest.mark.parametrize(
"set_primary",
[
pytest.param(True, id="set_primary"),
pytest.param(False, id="dont_set_primary"),
],
)
def test_imds_nic_setup_v1_ipv6_only(self, set_primary, oracle_ds):
oracle_ds._vnics_data = json.loads(OPC_VM_IPV6_ONLY_SECONDARY_VNIC_RESPONSE)
oracle_ds._network_config = {
"version": 1,
"config": [{"primary": "nic"}],
}
with mock.patch(
f"{DS_PATH}.get_interfaces_by_mac",
return_value={
"02:00:17:0d:6b:be": "ens3",
"02:00:17:18:f6:ff": "ens4",
},
):
oracle_ds._add_network_config_from_opc_imds(
set_primary=set_primary
)

secondary_nic_index = 1
nic_cfg = oracle_ds.network_config["config"]
if set_primary:
primary_cfg = nic_cfg[1]
secondary_nic_index += 1

assert "ens3" == primary_cfg["name"]
assert "physical" == primary_cfg["type"]
assert "02:00:17:0d:6b:be" == primary_cfg["mac_address"]
assert 9000 == primary_cfg["mtu"]
assert 1 == len(primary_cfg["subnets"])
assert "address" not in primary_cfg["subnets"][0]
assert "dhcp6" == primary_cfg["subnets"][0]["type"]
secondary_cfg = nic_cfg[secondary_nic_index]
assert "ens4" == secondary_cfg["name"]
assert "physical" == secondary_cfg["type"]
assert "02:00:17:18:f6:ff" == secondary_cfg["mac_address"]
assert 9000 == secondary_cfg["mtu"]
assert 1 == len(secondary_cfg["subnets"])
assert "2603:c020:400d:5d7e:aacc:8e5f:3b1b:3a4a/128" == secondary_cfg["subnets"][0]["address"]
assert "static" == secondary_cfg["subnets"][0]["type"]



@pytest.mark.parametrize(
"set_primary",
[True, False],
)
def test_secondary_nic_v2_ipv6_only(self, set_primary, oracle_ds):
oracle_ds._vnics_data = json.loads(OPC_VM_IPV6_ONLY_SECONDARY_VNIC_RESPONSE)
oracle_ds._network_config = {
"version": 2,
"ethernets": {"primary": {"nic": {}}},
}
with mock.patch(
f"{DS_PATH}.get_interfaces_by_mac",
return_value={
"02:00:17:0d:6b:be": "ens3",
"02:00:17:18:f6:ff": "ens4",
},
):
oracle_ds._add_network_config_from_opc_imds(
set_primary=set_primary
)

nic_cfg = oracle_ds.network_config["ethernets"]
if set_primary:
assert "ens3" in nic_cfg
primary_cfg = nic_cfg["ens3"]

assert primary_cfg["dhcp4"] is False
assert primary_cfg["dhcp6"] is True
assert "02:00:17:0d:6b:be" == primary_cfg["match"]["macaddress"]
assert 9000 == primary_cfg["mtu"]
assert "addresses" not in primary_cfg

assert "ens4" in nic_cfg
secondary_cfg = nic_cfg["ens4"]
assert secondary_cfg["dhcp4"] is False
assert secondary_cfg["dhcp6"] is False
assert "02:00:17:18:f6:ff" == secondary_cfg["match"]["macaddress"]
assert 9000 == secondary_cfg["mtu"]

assert 1 == len(secondary_cfg["addresses"])
assert "2603:c020:400d:5d7e:aacc:8e5f:3b1b:3a4a/128" == secondary_cfg["addresses"][0]


@pytest.mark.parametrize("error_add_network", [None, Exception])
@pytest.mark.parametrize(
"configure_secondary_nics",
Expand Down

0 comments on commit f950064

Please sign in to comment.