clonebox 1.1.5__py3-none-any.whl → 1.1.6__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.
- clonebox/cli.py +18 -15
- clonebox/models.py +2 -2
- clonebox/validator.py +34 -0
- {clonebox-1.1.5.dist-info → clonebox-1.1.6.dist-info}/METADATA +2 -1
- {clonebox-1.1.5.dist-info → clonebox-1.1.6.dist-info}/RECORD +9 -9
- {clonebox-1.1.5.dist-info → clonebox-1.1.6.dist-info}/WHEEL +0 -0
- {clonebox-1.1.5.dist-info → clonebox-1.1.6.dist-info}/entry_points.txt +0 -0
- {clonebox-1.1.5.dist-info → clonebox-1.1.6.dist-info}/licenses/LICENSE +0 -0
- {clonebox-1.1.5.dist-info → clonebox-1.1.6.dist-info}/top_level.txt +0 -0
clonebox/cli.py
CHANGED
|
@@ -1852,18 +1852,21 @@ def cmd_test(args):
|
|
|
1852
1852
|
all_paths.update(config.get("app_data_paths", {}))
|
|
1853
1853
|
|
|
1854
1854
|
if all_paths:
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1855
|
+
if not _qga_ping(vm_name, conn_uri):
|
|
1856
|
+
console.print("[yellow]⚠️ QEMU guest agent not connected - cannot verify mounts[/]")
|
|
1857
|
+
else:
|
|
1858
|
+
for idx, (host_path, guest_path) in enumerate(all_paths.items()):
|
|
1859
|
+
try:
|
|
1860
|
+
# Use the same QGA helper as diagnose/status
|
|
1861
|
+
is_accessible = _qga_exec(
|
|
1862
|
+
vm_name, conn_uri, f"test -d {guest_path} && echo yes || echo no", timeout=5
|
|
1863
|
+
)
|
|
1864
|
+
if is_accessible == "yes":
|
|
1865
|
+
console.print(f"[green]✅ {guest_path}[/]")
|
|
1866
|
+
else:
|
|
1867
|
+
console.print(f"[red]❌ {guest_path} (not accessible)[/]")
|
|
1868
|
+
except Exception:
|
|
1869
|
+
console.print(f"[yellow]⚠️ {guest_path} (could not check)[/]")
|
|
1867
1870
|
else:
|
|
1868
1871
|
console.print("[dim]No mount points configured[/]")
|
|
1869
1872
|
|
|
@@ -2100,7 +2103,7 @@ def generate_clonebox_yaml(
|
|
|
2100
2103
|
vm_name = f"clone-{sys_info['hostname']}"
|
|
2101
2104
|
|
|
2102
2105
|
# Calculate recommended resources
|
|
2103
|
-
ram_mb = min(
|
|
2106
|
+
ram_mb = min(8192, int(sys_info["memory_available_gb"] * 1024 * 0.5))
|
|
2104
2107
|
vcpus = max(2, sys_info["cpu_count"] // 2)
|
|
2105
2108
|
|
|
2106
2109
|
if disk_size_gb is None:
|
|
@@ -2333,8 +2336,8 @@ def create_vm_from_config(
|
|
|
2333
2336
|
|
|
2334
2337
|
vm_config = VMConfig(
|
|
2335
2338
|
name=config["vm"]["name"],
|
|
2336
|
-
ram_mb=config["vm"].get("ram_mb",
|
|
2337
|
-
vcpus=config["vm"].get("vcpus",
|
|
2339
|
+
ram_mb=config["vm"].get("ram_mb", 8192),
|
|
2340
|
+
vcpus=config["vm"].get("vcpus", 8),
|
|
2338
2341
|
disk_size_gb=config["vm"].get("disk_size_gb", 10),
|
|
2339
2342
|
gui=config["vm"].get("gui", True),
|
|
2340
2343
|
base_image=config["vm"].get("base_image"),
|
clonebox/models.py
CHANGED
|
@@ -14,8 +14,8 @@ class VMSettings(BaseModel):
|
|
|
14
14
|
"""VM-specific settings."""
|
|
15
15
|
|
|
16
16
|
name: str = Field(default="clonebox-vm", description="VM name")
|
|
17
|
-
ram_mb: int = Field(default=
|
|
18
|
-
vcpus: int = Field(default=
|
|
17
|
+
ram_mb: int = Field(default=8192, ge=512, le=131072, description="RAM in MB")
|
|
18
|
+
vcpus: int = Field(default=8, ge=1, le=128, description="Number of vCPUs")
|
|
19
19
|
disk_size_gb: int = Field(default=20, ge=1, le=2048, description="Disk size in GB")
|
|
20
20
|
gui: bool = Field(default=True, description="Enable SPICE graphics")
|
|
21
21
|
base_image: Optional[str] = Field(default=None, description="Path to base qcow2 image")
|
clonebox/validator.py
CHANGED
|
@@ -826,6 +826,26 @@ class VMValidator:
|
|
|
826
826
|
self.console.print(table)
|
|
827
827
|
return self.results["smoke"]
|
|
828
828
|
|
|
829
|
+
def _check_qga_ready(self) -> bool:
|
|
830
|
+
"""Check if QEMU guest agent is responding."""
|
|
831
|
+
try:
|
|
832
|
+
result = subprocess.run(
|
|
833
|
+
[
|
|
834
|
+
"virsh",
|
|
835
|
+
"--connect",
|
|
836
|
+
self.conn_uri,
|
|
837
|
+
"qemu-agent-command",
|
|
838
|
+
self.vm_name,
|
|
839
|
+
'{"execute":"guest-ping"}',
|
|
840
|
+
],
|
|
841
|
+
capture_output=True,
|
|
842
|
+
text=True,
|
|
843
|
+
timeout=5,
|
|
844
|
+
)
|
|
845
|
+
return result.returncode == 0
|
|
846
|
+
except Exception:
|
|
847
|
+
return False
|
|
848
|
+
|
|
829
849
|
def validate_all(self) -> Dict:
|
|
830
850
|
"""Run all validations and return comprehensive results."""
|
|
831
851
|
self.console.print("[bold cyan]🔍 Running Full Validation...[/]")
|
|
@@ -850,6 +870,20 @@ class VMValidator:
|
|
|
850
870
|
self.results["overall"] = "error"
|
|
851
871
|
return self.results
|
|
852
872
|
|
|
873
|
+
# Check QEMU Guest Agent
|
|
874
|
+
if not self._check_qga_ready():
|
|
875
|
+
self.console.print("[red]❌ QEMU Guest Agent not responding[/]")
|
|
876
|
+
self.console.print("\n[bold]🔧 Troubleshooting QGA:[/]")
|
|
877
|
+
self.console.print(" 1. The VM might still be booting. Wait 30-60 seconds.")
|
|
878
|
+
self.console.print(" 2. Ensure the agent is installed and running inside the VM:")
|
|
879
|
+
self.console.print(" [dim]virsh console " + self.vm_name + "[/]")
|
|
880
|
+
self.console.print(" [dim]sudo systemctl status qemu-guest-agent[/]")
|
|
881
|
+
self.console.print(" 3. If newly created, cloud-init might still be running.")
|
|
882
|
+
self.console.print(" 4. Check VM logs: [dim]clonebox logs " + self.vm_name + "[/]")
|
|
883
|
+
self.console.print(f"\n[yellow]⚠️ Skipping deep validation as it requires a working Guest Agent.[/]")
|
|
884
|
+
self.results["overall"] = "qga_not_ready"
|
|
885
|
+
return self.results
|
|
886
|
+
|
|
853
887
|
# Run all validations
|
|
854
888
|
self.validate_mounts()
|
|
855
889
|
self.validate_packages()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: clonebox
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.6
|
|
4
4
|
Summary: Clone your workstation environment to an isolated VM with selective apps, paths and services
|
|
5
5
|
Author: CloneBox Team
|
|
6
6
|
License: Apache-2.0
|
|
@@ -33,6 +33,7 @@ Requires-Dist: pyyaml>=6.0
|
|
|
33
33
|
Requires-Dist: pydantic>=2.0.0
|
|
34
34
|
Requires-Dist: python-dotenv>=1.0.0
|
|
35
35
|
Requires-Dist: cryptography>=42.0.0
|
|
36
|
+
Requires-Dist: structlog>=24.0.0
|
|
36
37
|
Provides-Extra: dev
|
|
37
38
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
38
39
|
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
clonebox/__init__.py,sha256=CyfHVVq6KqBr4CNERBpXk_O6Q5B35q03YpdQbokVvvI,408
|
|
2
2
|
clonebox/__main__.py,sha256=Fcoyzwwyz5-eC_sBlQk5a5RbKx8uodQz5sKJ190U0NU,135
|
|
3
|
-
clonebox/cli.py,sha256=
|
|
3
|
+
clonebox/cli.py,sha256=uVACDtbGh0bNcZY3p2s5W90aU6NQHzuTnTLelWCOlss,136330
|
|
4
4
|
clonebox/cloner.py,sha256=aH7BwmLgPITHzyHn_n_AKqtEADDm_aUXiRG-nB2rxMQ,90063
|
|
5
5
|
clonebox/container.py,sha256=tiYK1ZB-DhdD6A2FuMA0h_sRNkUI7KfYcJ0tFOcdyeM,6105
|
|
6
6
|
clonebox/dashboard.py,sha256=dMY6odvPq3j6FronhRRsX7aY3qdCwznB-aCWKEmHDNw,5768
|
|
@@ -9,7 +9,7 @@ clonebox/di.py,sha256=feFMXP5ff-7gwrIqgnoCpk1ivaiZA_lv2wcpkCSKiew,5648
|
|
|
9
9
|
clonebox/exporter.py,sha256=WIzVvmA0z_jjrpyXxvnXoLp9oaW6fKS7k0PGwzx_PIM,5629
|
|
10
10
|
clonebox/importer.py,sha256=Q9Uk1IOA41mgGhU4ynW2k-h9GEoGxRKI3c9wWE4uxcA,7097
|
|
11
11
|
clonebox/logging.py,sha256=jD_WgkHmt_h99EmX82QWK7D0OKWyxqcLwgT4UDQFp2g,3675
|
|
12
|
-
clonebox/models.py,sha256=
|
|
12
|
+
clonebox/models.py,sha256=l9e5U4ZEEcgCTt2c47GpqFwppwVeifoCoNFi57lFGFo,8307
|
|
13
13
|
clonebox/monitor.py,sha256=zlIarNf8w_i34XI8hZGxxrg5PVZK_Yxm6FQnkhLavRI,9181
|
|
14
14
|
clonebox/p2p.py,sha256=6o0JnscKqF9-BftQhW5fF1W6YY1wXshY9LEklNcHGJc,5913
|
|
15
15
|
clonebox/profiles.py,sha256=UP37fX_rhrG_O9ehNFJBUcULPmUtN1A8KsJ6cM44oK0,1986
|
|
@@ -17,7 +17,7 @@ clonebox/resource_monitor.py,sha256=lDR9KyPbVtImeeOkOBPPVP-5yCgoL5hsVFPZ_UqsY0w,
|
|
|
17
17
|
clonebox/resources.py,sha256=IkuM4OdSDV4qhyc0eIynwbAHBTv0aVSxxW-gghsnCAs,6815
|
|
18
18
|
clonebox/rollback.py,sha256=hpwO-8Ehe1pW0wHuZvJkC_qxZ6yEo9otCJRhGIUArCo,5711
|
|
19
19
|
clonebox/secrets.py,sha256=QtGMIjhTKq14qQRGy-pX0TU3vKLiZt7CMloAlF2GmzQ,10515
|
|
20
|
-
clonebox/validator.py,sha256=
|
|
20
|
+
clonebox/validator.py,sha256=2yQXDaL5bzHmxKkEP0fGJ85HV7Ax3iQl7KzSlBVLZkc,38220
|
|
21
21
|
clonebox/backends/libvirt_backend.py,sha256=sIHFIvFO1hIOXEFR_foSkOGBgIzaJVQs-njOU8GdafA,7170
|
|
22
22
|
clonebox/backends/qemu_disk.py,sha256=YsGjYX5sbEf35Y4yjTpNkZat73a4RGBxY-KTVzJhqIs,1687
|
|
23
23
|
clonebox/backends/subprocess_runner.py,sha256=c-IyaMxM1cmUu64h654oAvulm83K5Mu-VQxXJ_0BOds,1506
|
|
@@ -34,9 +34,9 @@ clonebox/snapshots/manager.py,sha256=hGzM8V6ZJPXjTqj47c4Kr8idlE-c1Q3gPUvuw1HvS1A
|
|
|
34
34
|
clonebox/snapshots/models.py,sha256=sRnn3OZE8JG9FZJlRuA3ihO-JXoPCQ3nD3SQytflAao,6206
|
|
35
35
|
clonebox/templates/profiles/ml-dev.yaml,sha256=w07MToGh31xtxpjbeXTBk9BkpAN8A3gv8HeA3ESKG9M,461
|
|
36
36
|
clonebox/templates/profiles/web-stack.yaml,sha256=EBnnGMzML5vAjXmIUbCpbTCwmRaNJiuWd3EcL43DOK8,485
|
|
37
|
-
clonebox-1.1.
|
|
38
|
-
clonebox-1.1.
|
|
39
|
-
clonebox-1.1.
|
|
40
|
-
clonebox-1.1.
|
|
41
|
-
clonebox-1.1.
|
|
42
|
-
clonebox-1.1.
|
|
37
|
+
clonebox-1.1.6.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
38
|
+
clonebox-1.1.6.dist-info/METADATA,sha256=36_PJreaPh-6Ot5Irm6NSdFjzwGkAGZGHBs4TYcB9lQ,48915
|
|
39
|
+
clonebox-1.1.6.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
40
|
+
clonebox-1.1.6.dist-info/entry_points.txt,sha256=FES95Vi3btfViLEEoHdb8nikNxTqzaooi9ehZw9ZfWI,47
|
|
41
|
+
clonebox-1.1.6.dist-info/top_level.txt,sha256=LdMo2cvCrEcRGH2M8JgQNVsCoszLV0xug6kx1JnaRjo,9
|
|
42
|
+
clonebox-1.1.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|