portacode 1.4.16.dev7__py3-none-any.whl → 1.4.16.dev9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- portacode/_version.py +2 -2
- portacode/connection/handlers/proxmox_infra.py +153 -4
- {portacode-1.4.16.dev7.dist-info → portacode-1.4.16.dev9.dist-info}/METADATA +1 -1
- {portacode-1.4.16.dev7.dist-info → portacode-1.4.16.dev9.dist-info}/RECORD +8 -8
- {portacode-1.4.16.dev7.dist-info → portacode-1.4.16.dev9.dist-info}/WHEEL +0 -0
- {portacode-1.4.16.dev7.dist-info → portacode-1.4.16.dev9.dist-info}/entry_points.txt +0 -0
- {portacode-1.4.16.dev7.dist-info → portacode-1.4.16.dev9.dist-info}/licenses/LICENSE +0 -0
- {portacode-1.4.16.dev7.dist-info → portacode-1.4.16.dev9.dist-info}/top_level.txt +0 -0
portacode/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '1.4.16.
|
|
32
|
-
__version_tuple__ = version_tuple = (1, 4, 16, '
|
|
31
|
+
__version__ = version = '1.4.16.dev9'
|
|
32
|
+
__version_tuple__ = version_tuple = (1, 4, 16, 'dev9')
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -259,6 +259,153 @@ def _bytes_to_gib(value: Any) -> int:
|
|
|
259
259
|
return int(round(_normalize_bytes(value) / (1024**3)))
|
|
260
260
|
|
|
261
261
|
|
|
262
|
+
def _extract_storage(value: Any) -> str:
|
|
263
|
+
if not value:
|
|
264
|
+
return "unknown"
|
|
265
|
+
text = str(value).strip()
|
|
266
|
+
if not text:
|
|
267
|
+
return "unknown"
|
|
268
|
+
primary = text.split(",", 1)[0]
|
|
269
|
+
storage = primary.split(":", 1)[0].strip()
|
|
270
|
+
return storage or "unknown"
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def _size_token_to_gib(token: str) -> float:
|
|
274
|
+
match = re.match(r"^\s*([0-9]+(?:\.[0-9]+)?)\s*([KMGTP])?([iI]?[bB])?\s*$", token)
|
|
275
|
+
if not match:
|
|
276
|
+
return 0.0
|
|
277
|
+
number = float(match.group(1))
|
|
278
|
+
unit = (match.group(2) or "").upper()
|
|
279
|
+
scale = {
|
|
280
|
+
"": 1,
|
|
281
|
+
"K": 1024**1,
|
|
282
|
+
"M": 1024**2,
|
|
283
|
+
"G": 1024**3,
|
|
284
|
+
"T": 1024**4,
|
|
285
|
+
"P": 1024**5,
|
|
286
|
+
}.get(unit, 1)
|
|
287
|
+
return (number * scale) / 1024**3
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def _extract_size_gib(value: Any) -> float:
|
|
291
|
+
if not value:
|
|
292
|
+
return 0.0
|
|
293
|
+
text = str(value)
|
|
294
|
+
for part in text.split(","):
|
|
295
|
+
if "size=" in part:
|
|
296
|
+
token = part.split("=", 1)[1]
|
|
297
|
+
return _size_token_to_gib(token)
|
|
298
|
+
return _size_token_to_gib(text)
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def _storage_from_lxc(cfg: Dict[str, Any], entry: Dict[str, Any]) -> str:
|
|
302
|
+
rootfs = cfg.get("rootfs") or entry.get("rootfs")
|
|
303
|
+
storage = _extract_storage(rootfs)
|
|
304
|
+
if storage != "unknown":
|
|
305
|
+
return storage
|
|
306
|
+
for idx in range(0, 10):
|
|
307
|
+
mp_value = cfg.get(f"mp{idx}")
|
|
308
|
+
storage = _extract_storage(mp_value)
|
|
309
|
+
if storage != "unknown":
|
|
310
|
+
return storage
|
|
311
|
+
return "unknown"
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def _storage_from_qemu(cfg: Dict[str, Any]) -> str:
|
|
315
|
+
preferred_keys = []
|
|
316
|
+
for prefix in ("scsi", "virtio", "sata", "ide"):
|
|
317
|
+
preferred_keys.extend(f"{prefix}{idx}" for idx in range(0, 6))
|
|
318
|
+
seen = set()
|
|
319
|
+
for key in preferred_keys:
|
|
320
|
+
value = cfg.get(key)
|
|
321
|
+
if value is None:
|
|
322
|
+
continue
|
|
323
|
+
seen.add(key)
|
|
324
|
+
text = str(value)
|
|
325
|
+
if "media=cdrom" in text or "cloudinit" in text:
|
|
326
|
+
continue
|
|
327
|
+
storage = _extract_storage(text)
|
|
328
|
+
if storage != "unknown":
|
|
329
|
+
return storage
|
|
330
|
+
for key in sorted(cfg.keys()):
|
|
331
|
+
if key in seen:
|
|
332
|
+
continue
|
|
333
|
+
if not any(key.startswith(prefix) for prefix in ("scsi", "virtio", "sata", "ide")):
|
|
334
|
+
continue
|
|
335
|
+
value = cfg.get(key)
|
|
336
|
+
if value is None:
|
|
337
|
+
continue
|
|
338
|
+
text = str(value)
|
|
339
|
+
if "media=cdrom" in text or "cloudinit" in text:
|
|
340
|
+
continue
|
|
341
|
+
storage = _extract_storage(text)
|
|
342
|
+
if storage != "unknown":
|
|
343
|
+
return storage
|
|
344
|
+
for key in ("efidisk0", "tpmstate0"):
|
|
345
|
+
storage = _extract_storage(cfg.get(key))
|
|
346
|
+
if storage != "unknown":
|
|
347
|
+
return storage
|
|
348
|
+
return "unknown"
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
def _primary_lxc_disk(cfg: Dict[str, Any], entry: Dict[str, Any]) -> str:
|
|
352
|
+
return str(cfg.get("rootfs") or entry.get("rootfs") or "")
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def _primary_qemu_disk(cfg: Dict[str, Any]) -> str:
|
|
356
|
+
preferred_keys = []
|
|
357
|
+
for prefix in ("scsi", "virtio", "sata", "ide"):
|
|
358
|
+
preferred_keys.extend(f"{prefix}{idx}" for idx in range(0, 6))
|
|
359
|
+
seen = set()
|
|
360
|
+
for key in preferred_keys:
|
|
361
|
+
value = cfg.get(key)
|
|
362
|
+
if value is None:
|
|
363
|
+
continue
|
|
364
|
+
seen.add(key)
|
|
365
|
+
text = str(value)
|
|
366
|
+
if "media=cdrom" in text or "cloudinit" in text:
|
|
367
|
+
continue
|
|
368
|
+
return text
|
|
369
|
+
for key in sorted(cfg.keys()):
|
|
370
|
+
if key in seen:
|
|
371
|
+
continue
|
|
372
|
+
if not any(key.startswith(prefix) for prefix in ("scsi", "virtio", "sata", "ide")):
|
|
373
|
+
continue
|
|
374
|
+
value = cfg.get(key)
|
|
375
|
+
if value is None:
|
|
376
|
+
continue
|
|
377
|
+
text = str(value)
|
|
378
|
+
if "media=cdrom" in text or "cloudinit" in text:
|
|
379
|
+
continue
|
|
380
|
+
return text
|
|
381
|
+
return ""
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
def _pick_storage(kind: str, cfg: Dict[str, Any], entry: Dict[str, Any]) -> str:
|
|
385
|
+
storage = _extract_storage(cfg.get("storage") or entry.get("storage"))
|
|
386
|
+
if storage != "unknown":
|
|
387
|
+
return storage
|
|
388
|
+
if kind == "lxc":
|
|
389
|
+
return _storage_from_lxc(cfg, entry)
|
|
390
|
+
return _storage_from_qemu(cfg)
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def _pick_disk_gib(kind: str, cfg: Dict[str, Any], entry: Dict[str, Any]) -> float:
|
|
394
|
+
if kind == "lxc":
|
|
395
|
+
size = _extract_size_gib(_primary_lxc_disk(cfg, entry))
|
|
396
|
+
if size:
|
|
397
|
+
return size
|
|
398
|
+
else:
|
|
399
|
+
size = _extract_size_gib(_primary_qemu_disk(cfg))
|
|
400
|
+
if size:
|
|
401
|
+
return size
|
|
402
|
+
for candidate in (entry.get("maxdisk"), entry.get("disk"), cfg.get("disk")):
|
|
403
|
+
if candidate in (None, 0):
|
|
404
|
+
continue
|
|
405
|
+
return _bytes_to_gib(candidate)
|
|
406
|
+
return 0.0
|
|
407
|
+
|
|
408
|
+
|
|
262
409
|
def _normalize_storage_name(name: Any) -> str:
|
|
263
410
|
if not name:
|
|
264
411
|
return ""
|
|
@@ -500,7 +647,7 @@ def _build_unmanaged_container_entry(
|
|
|
500
647
|
entry_type: str = "lxc",
|
|
501
648
|
) -> Dict[str, Any]:
|
|
502
649
|
ram_mib = _to_int(cfg.get("memory")) or _bytes_to_mib(ct.get("maxmem"))
|
|
503
|
-
disk_gib = disk_gib_override if disk_gib_override is not None else
|
|
650
|
+
disk_gib = disk_gib_override if disk_gib_override is not None else _pick_disk_gib(entry_type, cfg, ct)
|
|
504
651
|
cpu_share = _to_float(
|
|
505
652
|
cfg.get("cpulimit")
|
|
506
653
|
or cfg.get("cpus")
|
|
@@ -509,7 +656,7 @@ def _build_unmanaged_container_entry(
|
|
|
509
656
|
or ct.get("cpu")
|
|
510
657
|
)
|
|
511
658
|
hostname = ct.get("name") or cfg.get("hostname") or f"ct{vmid}"
|
|
512
|
-
storage = storage_override or
|
|
659
|
+
storage = storage_override or _pick_storage(entry_type, cfg, ct)
|
|
513
660
|
status = (ct.get("status") or "unknown").lower()
|
|
514
661
|
reserved = _parse_bool_flag(cfg.get("onboot"))
|
|
515
662
|
storage_matches_default = _storage_matches_default(storage, default_storage)
|
|
@@ -571,8 +718,10 @@ def _extract_qemu_disk_info(cfg: Dict[str, Any]) -> Tuple[str | None, int]:
|
|
|
571
718
|
|
|
572
719
|
def _storage_matches_default(storage_name: Any, default_storage: str | None) -> bool:
|
|
573
720
|
if not default_storage:
|
|
574
|
-
return
|
|
575
|
-
|
|
721
|
+
return False
|
|
722
|
+
storage = _extract_storage(storage_name)
|
|
723
|
+
default = str(default_storage).strip()
|
|
724
|
+
return storage.lower() == default.lower()
|
|
576
725
|
|
|
577
726
|
|
|
578
727
|
def _build_managed_containers_summary(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
portacode/README.md,sha256=4dKtpvR8LNgZPVz37GmkQCMWIr_u25Ao63iW56s7Ke4,775
|
|
2
2
|
portacode/__init__.py,sha256=oB3sV1wXr-um-RXio73UG8E5Xx6cF2ZVJveqjNmC-vQ,1086
|
|
3
3
|
portacode/__main__.py,sha256=jmHTGC1hzmo9iKJLv-SSYe9BSIbPPZ2IOpecI03PlTs,296
|
|
4
|
-
portacode/_version.py,sha256=
|
|
4
|
+
portacode/_version.py,sha256=MiVkLaI5JqUCo1IS8Z-ZuJxS2iDsMOn2RV8qQYxQ5kE,719
|
|
5
5
|
portacode/cli.py,sha256=mGLKoZ-T2FBF7IA9wUq0zyG0X9__-A1ao7gajjcVRH8,21828
|
|
6
6
|
portacode/data.py,sha256=5-s291bv8J354myaHm1Y7CQZTZyRzMU3TGe5U4hb-FA,1591
|
|
7
7
|
portacode/keypair.py,sha256=0OO4vHDcF1XMxCDqce61xFTlFwlTcmqe5HyGsXFEt7s,5838
|
|
@@ -22,7 +22,7 @@ portacode/connection/handlers/diff_handlers.py,sha256=iYTIRCcpEQ03vIPKZCsMTE5aZb
|
|
|
22
22
|
portacode/connection/handlers/file_handlers.py,sha256=nAJH8nXnX07xxD28ngLpgIUzcTuRwZBNpEGEKdRqohw,39507
|
|
23
23
|
portacode/connection/handlers/project_aware_file_handlers.py,sha256=AqgMnDqX2893T2NsrvUSCwjN5VKj4Pb2TN0S_SuboOE,9803
|
|
24
24
|
portacode/connection/handlers/project_state_handlers.py,sha256=v6ZefGW9i7n1aZLq2jOGumJIjYb6aHlPI4m1jkYewm8,1686
|
|
25
|
-
portacode/connection/handlers/proxmox_infra.py,sha256=
|
|
25
|
+
portacode/connection/handlers/proxmox_infra.py,sha256=CcPTFTM5TMJ9uX4-Ndrfao6Xx_8zdMMPlvze08SHWgU,88344
|
|
26
26
|
portacode/connection/handlers/registry.py,sha256=qXGE60sYEWg6ZtVQzFcZ5YI2XWR6lMgw4hAL9x5qR1I,6181
|
|
27
27
|
portacode/connection/handlers/session.py,sha256=uNGfiO_1B9-_yjJKkpvmbiJhIl6b-UXlT86UTfd6WYE,42219
|
|
28
28
|
portacode/connection/handlers/system_handlers.py,sha256=fr12QpOr_Z8KYGUU-AYrTQwRPAcrLK85hvj3SEq1Kw8,14757
|
|
@@ -65,7 +65,7 @@ portacode/utils/__init__.py,sha256=NgBlWTuNJESfIYJzP_3adI1yJQJR0XJLRpSdVNaBAN0,3
|
|
|
65
65
|
portacode/utils/diff_apply.py,sha256=4Oi7ft3VUCKmiUE4VM-OeqO7Gk6H7PF3WnN4WHXtjxI,15157
|
|
66
66
|
portacode/utils/diff_renderer.py,sha256=S76StnQ2DLfsz4Gg0m07UwPfRp8270PuzbNaQq-rmYk,13850
|
|
67
67
|
portacode/utils/ntp_clock.py,sha256=VqCnWCTehCufE43W23oB-WUdAZGeCcLxkmIOPwInYHc,2499
|
|
68
|
-
portacode-1.4.16.
|
|
68
|
+
portacode-1.4.16.dev9.dist-info/licenses/LICENSE,sha256=2FGbCnUDgRYuQTkB1O1dUUpu5CVAjK1j4_p6ack9Z54,1066
|
|
69
69
|
test_modules/README.md,sha256=Do_agkm9WhSzueXjRAkV_xEj6Emy5zB3N3VKY5Roce8,9274
|
|
70
70
|
test_modules/__init__.py,sha256=1LcbHodIHsB0g-g4NGjSn6AMuCoGbymvXPYLOb6Z7F0,53
|
|
71
71
|
test_modules/test_device_online.py,sha256=QtYq0Dq9vME8Gp2O4fGSheqVf8LUtpsSKosXXk56gGM,1654
|
|
@@ -91,8 +91,8 @@ testing_framework/core/playwright_manager.py,sha256=Tw46qwxIhOFkS48C2IWIQHHNpEe-
|
|
|
91
91
|
testing_framework/core/runner.py,sha256=j2QwNJmAxVBmJvcbVS7DgPJUKPNzqfLmt_4NNdaKmZU,19297
|
|
92
92
|
testing_framework/core/shared_cli_manager.py,sha256=BESSNtyQb7BOlaOvZmm04T8Uezjms4KCBs2MzTxvzYQ,8790
|
|
93
93
|
testing_framework/core/test_discovery.py,sha256=2FZ9fJ8Dp5dloA-fkgXoJ_gCMC_nYPBnA3Hs2xlagzM,4928
|
|
94
|
-
portacode-1.4.16.
|
|
95
|
-
portacode-1.4.16.
|
|
96
|
-
portacode-1.4.16.
|
|
97
|
-
portacode-1.4.16.
|
|
98
|
-
portacode-1.4.16.
|
|
94
|
+
portacode-1.4.16.dev9.dist-info/METADATA,sha256=IwtVePxyAtqCsSSOTisxusWv8gBIvL1DSCoT96cNDj0,13051
|
|
95
|
+
portacode-1.4.16.dev9.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
96
|
+
portacode-1.4.16.dev9.dist-info/entry_points.txt,sha256=lLUUL-BM6_wwe44Xv0__5NQ1BnAz6jWjSMFvZdWW3zU,48
|
|
97
|
+
portacode-1.4.16.dev9.dist-info/top_level.txt,sha256=TGhTYUxfW8SyVZc_zGgzjzc24gGT7nSw8Qf73liVRKM,41
|
|
98
|
+
portacode-1.4.16.dev9.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|