Skip to content

Commit 913743a

Browse files
committed
fix: PBS namespace selector, LXC IP fallback, docs v0.9.6
- PBS namespace dropdown now wired up — passes ns param to snapshots/groups API (#301) - LXC IP fetch: fallback to /config static IP when /interfaces returns empty (#300) - Docs updated to v0.9.6 with Predictive LB, ISO Sync, Push Notifications sections - Docs changelog for v0.9.6
1 parent eb3c17a commit 913743a

3 files changed

Lines changed: 69 additions & 30 deletions

File tree

pegaprox/core/manager.py

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,29 +1163,48 @@ def _fetch_qemu_ips(self, node: str, vmid: int) -> list:
11631163
return []
11641164

11651165
def _fetch_lxc_ips(self, node: str, vmid: int) -> list:
1166-
"""Fetch IP addresses for a running LXC container via /interfaces endpoint.
1167-
Returns IPv4 addresses first, then IPv6. Returns [] on any error."""
1166+
"""Fetch IP addresses for a running LXC container.
1167+
MK: Apr 2026 — tries /interfaces first, falls back to config + status (#300)
1168+
"""
11681169
try:
1170+
# method 1: /interfaces — preferred, returns all IPs
11691171
url = f"https://{self.host}:8006/api2/json/nodes/{node}/lxc/{vmid}/interfaces"
11701172
resp = self._create_session().get(url, timeout=8)
1171-
if resp.status_code != 200:
1172-
return []
1173-
interfaces = resp.json().get('data', [])
1174-
ipv4s, ipv6s = [], []
1175-
for iface in interfaces:
1176-
if iface.get('name') == 'lo':
1177-
continue
1178-
inet = iface.get('inet', '')
1179-
if inet:
1180-
ip = inet.split('/')[0]
1181-
if not ip.startswith('127.'):
1182-
ipv4s.append(ip)
1183-
inet6 = iface.get('inet6', '')
1184-
if inet6:
1185-
ip = inet6.split('/')[0]
1186-
if ip != '::1' and not ip.lower().startswith('fe80:'):
1187-
ipv6s.append(ip)
1188-
return ipv4s + ipv6s
1173+
if resp.status_code == 200:
1174+
interfaces = resp.json().get('data', [])
1175+
ipv4s, ipv6s = [], []
1176+
for iface in interfaces:
1177+
if iface.get('name') == 'lo':
1178+
continue
1179+
inet = iface.get('inet', '')
1180+
if inet:
1181+
ip = inet.split('/')[0]
1182+
if not ip.startswith('127.'):
1183+
ipv4s.append(ip)
1184+
inet6 = iface.get('inet6', '')
1185+
if inet6:
1186+
ip = inet6.split('/')[0]
1187+
if ip != '::1' and not ip.lower().startswith('fe80:'):
1188+
ipv6s.append(ip)
1189+
if ipv4s or ipv6s:
1190+
return ipv4s + ipv6s
1191+
1192+
# method 2: /config — extract static IPs from net0..net9
1193+
cfg_url = f"https://{self.host}:8006/api2/json/nodes/{node}/lxc/{vmid}/config"
1194+
cfg_resp = self._create_session().get(cfg_url, timeout=5)
1195+
if cfg_resp.status_code == 200:
1196+
cfg = cfg_resp.json().get('data', {})
1197+
import re
1198+
for key in sorted(cfg.keys()):
1199+
if not key.startswith('net'):
1200+
continue
1201+
val = cfg[key]
1202+
# format: name=eth0,bridge=vmbr0,ip=10.0.0.5/24,...
1203+
m = re.search(r'ip=(\d+\.\d+\.\d+\.\d+)', str(val))
1204+
if m:
1205+
return [m.group(1)]
1206+
1207+
return []
11891208
except Exception:
11901209
return []
11911210

0 commit comments

Comments
 (0)