cloud-init fails with KeyError when nameserver config and matching interface are present
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
cloud-init |
Fix Released
|
High
|
Brett Holman |
Bug Description
cloud-init fails to parse network configuration with a KeyError if:
- The configuration has a `nameservers` configuration, and
- The configuration matches an existing interface on the machine, and
- The configuration name does not match that interfaces name.
Consider the following network config:
```
version: 2
ethernets:
eth:
match:
macaddress: '00:11:22:33:44:55'
addresses: [10.0.0.2/24]
gateway4: 10.0.0.1
nameservers:
addresses: [10.0.0.1]
```
Now, if a device is present with the mac address 00:11:22:33:44:55, parsing will fail with the following stack trace:
```
2022-06-25 10:26:43,657 - util.py[WARNING]: failed stage init-local
2022-06-25 10:26:43,657 - util.py[DEBUG]: failed stage init-local
Traceback (most recent call last):
File "/usr/lib/
ret = functor(name, args)
File "/usr/lib/
init.
File "/usr/lib/
return self.distro.
File "/usr/lib/
network_state = parse_net_
File "/usr/lib/
nsi.
File "/usr/lib/
self.
File "/usr/lib/
self.
File "/usr/lib/
self.
File "/usr/lib/
return func(self, command, *args, **kwargs)
File "/usr/lib/
_iface[
KeyError: 'eth'
```
I've investigated the issue myself and created a test case:
```
from unittest import mock
from cloudinit import safeyaml
from cloudinit.net import network_state
class TestNetDns:
@mock.
def test_networkd_
version: 2
ethernets:
eth:
match:
macaddress: '00:11:22:33:44:55'
addresses: [10.0.0.2/24]
gateway4: 10.0.0.1
nameservers:
addresses: [10.0.0.1]
"""))
```
This test case will fail with the KeyError.
The reason for this bug is that `handle_ethernets` will take the interface name from the system because no set-name setting is present. It will then add the network state under that interface name, not the configured key 'eth'. Later, _handle_
A quick bisect shows that this test case starts failing with commit bf94945fb855c40
As a workaround, you can give an explicit set-name statement, or change the key of the network config to match the physical device name.
Changed in cloud-init: | |
status: | New → Confirmed |
Changed in cloud-init: | |
importance: | Undecided → High |
Changed in cloud-init: | |
status: | Confirmed → Fix Committed |
assignee: | nobody → Brett Holman (holmanb) |
Wow, really appreciate the effort tracking this down and providing a workaround, bisected commit, and test case!
Are you interested in contributing this test case to the project on Github? I think this test would be a welcome addition.
I'm working on a fix now.