Skip to content

Commit

Permalink
net/dhcp: raise InvalidDHCPLeaseFileError on error parsing dhcpcd lease
Browse files Browse the repository at this point in the history
Seeing a fairly large number of lease parsing failures on Azure similar
to:
```
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/cloudinit/sources/DataSourceAzure.py", line 851, in _get_data
    crawled_data = util.log_time(
                   ^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/cloudinit/util.py", line 2828, in log_time
    ret = func(*args, **kwargs)
          ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/cloudinit/sources/helpers/azure.py", line 45, in impl
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/cloudinit/sources/DataSourceAzure.py", line 660, in crawl_metadata
    self._wait_for_pps_savable_reuse()
  File "/usr/lib/python3/dist-packages/cloudinit/sources/helpers/azure.py", line 45, in impl
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/cloudinit/sources/DataSourceAzure.py", line 1236, in _wait_for_pps_savable_reuse
    self._wait_for_hot_attached_primary_nic(nl_sock)
  File "/usr/lib/python3/dist-packages/cloudinit/sources/helpers/azure.py", line 45, in impl
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/cloudinit/sources/DataSourceAzure.py", line 1142, in _wait_for_hot_attached_primary_nic
    primary_nic_found = self._setup_ephemeral_networking(
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/cloudinit/sources/helpers/azure.py", line 45, in impl
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/cloudinit/sources/DataSourceAzure.py", line 440, in _setup_ephemeral_networking
    lease = self._ephemeral_dhcp_ctx.obtain_lease()
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/cloudinit/net/ephemeral.py", line 293, in obtain_lease
    self.lease = maybe_perform_dhcp_discovery(
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/cloudinit/net/dhcp.py", line 103, in maybe_perform_dhcp_discovery
    return distro.dhcp_client.dhcp_discovery(interface, dhcp_log_func, distro)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/cloudinit/net/dhcp.py", line 656, in dhcp_discovery
    lease = self.get_newest_lease(interface)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/cloudinit/net/dhcp.py", line 829, in get_newest_lease
    return self.parse_dhcpcd_lease(
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/cloudinit/net/dhcp.py", line 787, in parse_dhcpcd_lease
    lease = dict(
            ^^^^^
ValueError: dictionary update sequence element #0 has length 1; 2 is required
```

Catch this error in parse_dhcpcd_lease() and raise
InvalidDHCPLeaseFileError after logging an error.

Signed-off-by: Chris Patterson <cpatterson@microsoft.com>
  • Loading branch information
cjp256 committed Apr 2, 2024
1 parent 372e80f commit 9a2fa5c
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 6 deletions.
19 changes: 13 additions & 6 deletions cloudinit/net/dhcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -783,14 +783,21 @@ def parse_dhcpcd_lease(lease_dump: str, interface: str) -> Dict:
subnet_cidr='20'
subnet_mask='255.255.240.0'
"""
LOG.debug(
"Parsing dhcpcd lease for interface %s: %r", interface, lease_dump
)

# create a dict from dhcpcd dump output - remove single quotes
lease = dict(
[
a.split("=")
for a in lease_dump.strip().replace("'", "").split("\n")
]
)
try:
lease = dict(
[
a.split("=")
for a in lease_dump.strip().replace("'", "").split("\n")
]
)
except ValueError as error:
LOG.error("Error parsing dhcpcd lease: %r", error)
raise InvalidDHCPLeaseFileError from error

# this is expected by cloud-init's code
lease["interface"] = interface
Expand Down
11 changes: 11 additions & 0 deletions tests/unittests/net/test_dhcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -1199,6 +1199,17 @@ def test_parse_lease_dump(self):
assert "255.255.240.0" == parsed_lease["subnet-mask"]
assert "192.168.0.1" == parsed_lease["routers"]

def test_parse_lease_dump_fails(self):
lease = dedent(
"""
fail
"""
)

with pytest.raises(InvalidDHCPLeaseFileError):
with mock.patch("cloudinit.net.dhcp.util.load_binary_file"):
Dhcpcd.parse_dhcpcd_lease(lease, "eth0")

@pytest.mark.parametrize(
"lease_file, option_245",
(
Expand Down

0 comments on commit 9a2fa5c

Please sign in to comment.