summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorChristian Breunig <christian@breunig.cc>2026-10-07 19:56:47 +0200
committerChristian Breunig <christian@breunig.cc>2026-10-31 09:58:29 +0000
commit0b9903a85ccbef75b653a4d4349db5710ee9638d (patch)
treefe853124478847d772207e316a3bb0eb086d65d7 /python
parent724c38de924caab6cb3e2c0b57173ef0742ffa40 (diff)
downloadvyos-1x-0b9903a85ccbef75b653a4d4349db5710ee9638d.tar.gz
vyos-1x-0b9903a85ccbef75b653a4d4349db5710ee9638d.zip
interfaces: T3871: persist interface names on the first boot of a pre-built image
The check guarding that write looked for a marker which an activation script creates only after interface naming has already run. On a deployed qcow2 the marker is absent on the first boot, so nothing was recorded and the next boot named the hardware from scratch. Removing a card then moved every name below it onto the neighbouring port, taking that interface's address with it. Only an encrypted configuration has a volume which may still be locked, so ask about that instead - everywhere else the directory is already the persistent one.
Diffstat (limited to 'python')
-rw-r--r--python/vyos/ifconfig/ifname_store.py44
1 files changed, 38 insertions, 6 deletions
diff --git a/python/vyos/ifconfig/ifname_store.py b/python/vyos/ifconfig/ifname_store.py
index e6a0876fd..9c00810db 100644
--- a/python/vyos/ifconfig/ifname_store.py
+++ b/python/vyos/ifconfig/ifname_store.py
@@ -218,15 +218,47 @@ def load_store(path: Path = None) -> dict:
'hardware': hardware}
-def config_dir_is_mounted(path: Path = None) -> bool:
- """Is the config directory the real one, or a bare rootfs overlay?
+def encrypted_config_volume() -> bool:
+ """Does this image keep its configuration on a LUKS volume?
+
+ Mirrors mount_encrypted_config() in src/init/vyos-router - a container
+ named after the running image, below the persistence path. Anything that
+ cannot be determined (no persistence, no version file, not a VyOS system
+ at all) means there is no volume waiting to be mounted over the config
+ directory.
+ """
+ try:
+ from vyos.system.image import get_running_image
+
+ code, out = rc_cmd('/opt/vyatta/sbin/vyos-persistpath')
+ if code != 0 or not out.strip():
+ return False
+ image = get_running_image()
+ return bool(image) and (Path(out.strip()) / 'luks' / image).is_file()
+ except Exception:
+ return False
- A failed TPM/LUKS unlock does not stop the boot. Writing to the overlay
- underneath would be masked once the real volume mounts, leaving two
- stores which silently diverge.
+
+def config_dir_is_mounted(path: Path = None) -> bool:
+ """Will a store written here still be there on the next boot?
+
+ Only an encrypted configuration has a volume which may still be locked:
+ a failed TPM/LUKS unlock does not stop the boot, and writing to the
+ directory underneath would be masked once the real volume mounts,
+ leaving two stores which silently diverge. Everywhere else the directory
+ is already the persistent one.
+
+ Deliberately not keyed on '.vyatta_config'. That marker is an
+ install-time hint, written by an activation script which runs *after*
+ interface naming - so on the first boot of a pre-built image it does not
+ exist yet, no store is ever written, and the next boot names the
+ hardware from scratch. Removing a card then shifts every name below it
+ onto the wrong port (T3871).
"""
path = path or store_path
- return (path.parent / '.vyatta_config').exists()
+ if not encrypted_config_volume():
+ return True
+ return os.path.ismount(path.parent)
def save_store(store: dict, path: Path = None) -> bool: