Using "set-name" with interface specific DNS with a v2 network config causes a KeyError
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
cloud-init |
Fix Released
|
Medium
|
Unassigned |
Bug Description
This bug was first reported at https:/
Cloud-Provider: VMware, but does not matter as this bug is distro and DS agnostic
Config: The metadata was set to the following:
instance-id: "wlan-1-
local-hostname: "wlan-1-
wait-
ipv4: false
ipv6: false
network:
version: 2
ethernets:
id0:
match:
set-name: "eth0"
- "10.196.27.122/28"
gateway4: "10.196.27.126"
- "10.102.102.132"
- "10.102.102.133"
- "10.90.24.1"
search:
- "refsa1.
Again though, the platform is likely irrelevant as this seems to be a bug introduced with https:/
The bug can be surfaced via unit test by patching the v21.3 version of Cloud-Init with the following:
diff --git a/cloudinit/
index 84e8308a..c0aa78a0 100644
--- a/cloudinit/
+++ b/cloudinit/
@@ -52,6 +52,7 @@ network:
eth1:
match:
+ set-name: "eth2"
Next, run the affected test from the root of the Cloud-Init source tree:
$ make clean_pyc && \
PYTHONPAT
python3 -m pytest -v cloudinit/
The output will resemble the following:
===
platform darwin -- Python 3.9.7, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- /usr/local/
cachedir: .pytest_cache
rootdir: /Users/
collected 10 items
cloudinit/
cloudinit/
cloudinit/
cloudinit/
cloudinit/
cloudinit/
cloudinit/
cloudinit/
cloudinit/
cloudinit/
===
___
self = <cloudinit.
def test_v2_
> config = self._parse_
cloudinit/
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
cloudinit/
return network_
cloudinit/
cloudinit/
cloudinit/
cloudinit/
cloudinit/
return func(self, command, *args, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <cloudinit.
command = {'address': ['4.4.4.4'], 'search': ['foo.local', 'bar.local'], 'type': 'nameserver'}, iface = 'eth1'
def _handle_
_iface = self._network_
> _iface[
E KeyError: 'eth1'
cloudinit/
---
2021-10-08 00:57:41 DEBUG cloudinit.
{'type': 'physical', 'name': 'eth0', 'mac_address': '00:11:
2021-10-08 00:57:41 DEBUG cloudinit.
{'type': 'physical', 'name': 'eth2', 'mac_address': '66:77:
2021-10-08 00:57:41 DEBUG cloudinit.
{'eth0': {'match': {'macaddress': '00:11:
===
../
/
conftest.py:68
/
Use @pytest.fixture instead; they are the same.
conftest.py:169
/
Use @pytest.fixture instead; they are the same.
def httpretty():
-- Docs: https:/
===
FAILED cloudinit/
===
This is is occurring because the code to iterate over the interfaces when configuring interface-specific DNS is using the original interface name, not the one from the "set-name" directive. The following patch corrects the issue:
diff --git a/cloudinit/
index 95b064f0..06ff8e96 100644
--- a/cloudinit/
+++ b/cloudinit/
@@ -543,7 +543,11 @@ class NetworkStateInt
def _handle_
_iface = self._network_
- _iface[
+ try:
+ _iface[
+ except:
+ print("original iface name: %s\niface dict: %s\n" % (iface, _iface))
+ raise
def handle_route(self, command):
diff --git a/cloudinit/
index 84e8308a..45e99171 100644
--- a/cloudinit/
+++ b/cloudinit/
@@ -52,6 +52,7 @@ network:
eth1:
match:
+ set-name: "ens92"
Now the above test passes. A PR will be opened on Cloud-Init's GitHub repository with the above patch.
Changed in cloud-init: | |
status: | New → Confirmed |
importance: | Undecided → Medium |
Changed in cloud-init: | |
status: | Confirmed → Fix Committed |
Filed a PR to address the bug at https:/ /github. com/canonical/ cloud-init/ pull/1058