DataSourceCloudStack: get_vr_address() does not catch NoDHCPLeaseError, so the default-gateway fallback is never reached

Aperta Adatta ai principianti
#7,124 2 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@whoiskamchatka ci sta già lavorando.

Dal 1/10/2026.

  • #7127 di @whoiskamchatka — aperta

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
88/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
python
Ambito
networking

Direzione di ricerca

Inizia in cloudinit/sources/DataSourceCloudStack.py, in get_vr_address(), quindi confronta la relativa gestione dei lease DHCP con _get_domainname(). Esegui il comando di riproduzione Fedora riportato nell’issue per confermare il percorso NoDHCPLeaseError. Il lavoro è completato quando viene restituito il gateway predefinito se il client DHCP della distribuzione non dispone di alcun lease, mantenendo invariato l’ordine esistente di ricerca degli indirizzi.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

bug new

Bug report

In cloudinit/sources/DataSourceCloudStack.py, get_vr_address() tries several
sources for the virtual router address, in order:

  1. the data-server DNS entry
  2. systemd-networkd leases
  3. ISC dhclient leases
  4. the lease of the distro's DHCP client (distro.dhcp_client.get_newest_lease())
  5. the default gateway

Step 4 is guarded only against FileNotFoundError:

with suppress(FileNotFoundError):
    latest_lease = distro.dhcp_client.get_newest_lease(
        distro.fallback_interface
    )

On distributions where dhcpcd is installed but not running — because
NetworkManager handles DHCP with its internal client — dhcpcd --dumplease
exits 1 with dhcpcd is not running. Dhcpcd.get_newest_lease() catches the
resulting ProcessExecutionError and re-raises it as NoDHCPLeaseError. That
exception is not suppressed, so it escapes get_vr_address() and step 5 is
never reached. DataSourceCloudStack is then unable to determine the metadata
server address.

This is the default situation on Fedora 44 and on RHEL/Rocky Linux 10: the
cloud-init package depends on dhcpcd, but NetworkManager does not use it.

Related

The same pattern was fixed in _get_domainname(), which now uses
except (NoDHCPLeaseError, FileNotFoundError, AttributeError). RHEL
backported that fix as RHEL-159033 (cloud-init-24.4-7.el10_2.1).
get_vr_address() still uses the original suppress(FileNotFoundError),
both in 26.1 and in main.

When it is triggered

Step 4 is only reached when data-server does not resolve. On CloudStack that
name is served by dnsmasq on the virtual router, so this happens whenever the
guest does not use the router as its DNS server, for example:

  • a network offering that does not provide the Dns service through the VirtualRouter
  • the zone setting use.external.dns = true
  • DNS servers configured manually in the guest

In CloudStack isolated networks the virtual router is also the default
gateway, so the step 5 fallback would return the correct address. Today it is
never reached.

Steps to reproduce

Fedora 44 with cloud-init 26.1, on a CloudStack guest in an isolated network
whose DNS servers do not include the virtual router
(getent hosts data-server returns nothing; default gateway 192.168.1.254
is the virtual router):

sudo python3 - <<'EOF'
from cloudinit import distros, helpers
from cloudinit.sources import DataSourceCloudStack as ds
d = distros.fetch('fedora')('fedora', {}, helpers.Paths({}))
print("VR:", ds.get_vr_address(d))
EOF

Expected: the default gateway (192.168.1.254) is returned.

Actual: NoDHCPLeaseError is raised:

Traceback (most recent call last):
  File "/usr/lib/python3.14/site-packages/cloudinit/net/dhcp.py", line 864, in get_newest_lease
    subp.subp(
    ~~~~~~~~~^
        [
        ^
    ...<4 lines>...
        ],
        ^^
    ).stdout,
    ^
  File "/usr/lib/python3.14/site-packages/cloudinit/subp.py", line 291, in subp
    raise ProcessExecutionError(
        stdout=out, stderr=err, exit_code=rc, cmd=args
    )
cloudinit.subp.ProcessExecutionError: Unexpected error while running command.
Command: ['dhcpcd', '--dumplease', '--ipv4only', 'enp3s0']
Exit code: 1
Reason: -
Stdout:
Stderr: dhcpcd is not running

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
  File "/usr/lib/python3.14/site-packages/cloudinit/sources/DataSourceCloudStack.py", line 342, in get_vr_address
    latest_lease = distro.dhcp_client.get_newest_lease(
        distro.fallback_interface
    )
  File "/usr/lib/python3.14/site-packages/cloudinit/net/dhcp.py", line 882, in get_newest_lease
    raise NoDHCPLeaseError from error
cloudinit.net.dhcp.NoDHCPLeaseError

Proposed fix

-    with suppress(FileNotFoundError):
+    with suppress(FileNotFoundError, NoDHCPLeaseError):
         latest_lease = distro.dhcp_client.get_newest_lease(
             distro.fallback_interface
         )

or, for consistency with _get_domainname(),
suppress(NoDHCPLeaseError, FileNotFoundError, AttributeError).
NoDHCPLeaseError is already imported in the module.

Tested on the same guest by loading a patched copy of the module:

sudo python3 - <<'EOF'
import importlib.util
from cloudinit import distros, helpers
p = '/usr/lib/python3.14/site-packages/cloudinit/sources/DataSourceCloudStack.py'
src = open(p).read()
old = "    with suppress(FileNotFoundError):\n        latest_lease"
new = "    with suppress(FileNotFoundError, NoDHCPLeaseError):\n        latest_lease"
assert src.count(old) == 1
mod = importlib.util.module_from_spec(importlib.util.spec_from_loader("ds_patched", loader=None))
exec(compile(src.replace(old, new), "DataSourceCloudStack_patched.py", "exec"), mod.__dict__)
d = distros.fetch('fedora')('fedora', {}, helpers.Paths({}))
print("VR:", mod.get_vr_address(d))
EOF

Output:

VR: 192.168.1.254

With the fix, get_vr_address() falls back to the default gateway, which in
this isolated network is the virtual router.

Environment details

  • cloud-init: 26.1 (cloud-init-26.1-1.fc44); same code in main as of 2026-09-30
  • OS: Fedora 44 Cloud Base Generic; same code path on Rocky Linux 10
  • Platform: Apache CloudStack 4.22, KVM, isolated guest network
  • Networking: NetworkManager with its internal DHCP client; dhcpcd installed but not running
Lingua principale
Python
Stelle
3.9k
Fork
1.2k
Merge medio
2g 26m
PR unite (30g)
16

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di canonical/cloud-init

Tutte le issue di canonical/cloud-init

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.