clonebox 1.1.3__py3-none-any.whl → 1.1.5__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/backends/libvirt_backend.py +217 -0
- clonebox/backends/qemu_disk.py +52 -0
- clonebox/backends/subprocess_runner.py +56 -0
- clonebox/cli.py +343 -22
- clonebox/cloner.py +327 -189
- clonebox/di.py +176 -0
- clonebox/health/__init__.py +17 -0
- clonebox/health/manager.py +328 -0
- clonebox/health/models.py +194 -0
- clonebox/health/probes.py +337 -0
- clonebox/interfaces/disk.py +40 -0
- clonebox/interfaces/hypervisor.py +89 -0
- clonebox/interfaces/network.py +33 -0
- clonebox/interfaces/process.py +46 -0
- clonebox/logging.py +125 -0
- clonebox/monitor.py +267 -0
- clonebox/p2p.py +4 -2
- clonebox/resource_monitor.py +162 -0
- clonebox/resources.py +222 -0
- clonebox/rollback.py +172 -0
- clonebox/secrets.py +331 -0
- clonebox/snapshots/__init__.py +12 -0
- clonebox/snapshots/manager.py +349 -0
- clonebox/snapshots/models.py +183 -0
- {clonebox-1.1.3.dist-info → clonebox-1.1.5.dist-info}/METADATA +51 -2
- clonebox-1.1.5.dist-info/RECORD +42 -0
- clonebox-1.1.3.dist-info/RECORD +0 -21
- {clonebox-1.1.3.dist-info → clonebox-1.1.5.dist-info}/WHEEL +0 -0
- {clonebox-1.1.3.dist-info → clonebox-1.1.5.dist-info}/entry_points.txt +0 -0
- {clonebox-1.1.3.dist-info → clonebox-1.1.5.dist-info}/licenses/LICENSE +0 -0
- {clonebox-1.1.3.dist-info → clonebox-1.1.5.dist-info}/top_level.txt +0 -0
clonebox/cli.py
CHANGED
|
@@ -30,7 +30,10 @@ from clonebox.models import ContainerConfig
|
|
|
30
30
|
from clonebox.profiles import merge_with_profile
|
|
31
31
|
from clonebox.exporter import SecureExporter, VMExporter
|
|
32
32
|
from clonebox.importer import SecureImporter, VMImporter
|
|
33
|
+
from clonebox.monitor import ResourceMonitor, format_bytes
|
|
33
34
|
from clonebox.p2p import P2PManager
|
|
35
|
+
from clonebox.snapshots import SnapshotManager, SnapshotType
|
|
36
|
+
from clonebox.health import HealthCheckManager, ProbeConfig, ProbeType
|
|
34
37
|
|
|
35
38
|
# Custom questionary style
|
|
36
39
|
custom_style = Style(
|
|
@@ -2638,6 +2641,272 @@ def cmd_detect(args):
|
|
|
2638
2641
|
console.print(table)
|
|
2639
2642
|
|
|
2640
2643
|
|
|
2644
|
+
def cmd_monitor(args) -> None:
|
|
2645
|
+
"""Real-time resource monitoring for VMs and containers."""
|
|
2646
|
+
conn_uri = "qemu:///session" if getattr(args, "user", False) else "qemu:///system"
|
|
2647
|
+
refresh = getattr(args, "refresh", 2.0)
|
|
2648
|
+
once = getattr(args, "once", False)
|
|
2649
|
+
|
|
2650
|
+
monitor = ResourceMonitor(conn_uri)
|
|
2651
|
+
|
|
2652
|
+
try:
|
|
2653
|
+
while True:
|
|
2654
|
+
# Clear screen for live update
|
|
2655
|
+
if not once:
|
|
2656
|
+
console.clear()
|
|
2657
|
+
|
|
2658
|
+
console.print("[bold cyan]📊 CloneBox Resource Monitor[/]")
|
|
2659
|
+
console.print()
|
|
2660
|
+
|
|
2661
|
+
# VM Stats
|
|
2662
|
+
vm_stats = monitor.get_all_vm_stats()
|
|
2663
|
+
if vm_stats:
|
|
2664
|
+
table = Table(title="🖥️ Virtual Machines", border_style="cyan")
|
|
2665
|
+
table.add_column("Name", style="bold")
|
|
2666
|
+
table.add_column("State")
|
|
2667
|
+
table.add_column("CPU %")
|
|
2668
|
+
table.add_column("Memory")
|
|
2669
|
+
table.add_column("Disk")
|
|
2670
|
+
table.add_column("Network I/O")
|
|
2671
|
+
|
|
2672
|
+
for vm in vm_stats:
|
|
2673
|
+
state_color = "green" if vm.state == "running" else "yellow"
|
|
2674
|
+
cpu_color = "red" if vm.cpu_percent > 80 else "green"
|
|
2675
|
+
mem_pct = (
|
|
2676
|
+
(vm.memory_used_mb / vm.memory_total_mb * 100)
|
|
2677
|
+
if vm.memory_total_mb > 0
|
|
2678
|
+
else 0
|
|
2679
|
+
)
|
|
2680
|
+
mem_color = "red" if mem_pct > 80 else "green"
|
|
2681
|
+
|
|
2682
|
+
table.add_row(
|
|
2683
|
+
vm.name,
|
|
2684
|
+
f"[{state_color}]{vm.state}[/]",
|
|
2685
|
+
f"[{cpu_color}]{vm.cpu_percent:.1f}%[/]",
|
|
2686
|
+
f"[{mem_color}]{vm.memory_used_mb}/{vm.memory_total_mb} MB[/]",
|
|
2687
|
+
f"{vm.disk_used_gb:.1f}/{vm.disk_total_gb:.1f} GB",
|
|
2688
|
+
f"↓{format_bytes(vm.network_rx_bytes)} ↑{format_bytes(vm.network_tx_bytes)}",
|
|
2689
|
+
)
|
|
2690
|
+
console.print(table)
|
|
2691
|
+
else:
|
|
2692
|
+
console.print("[dim]No VMs found.[/]")
|
|
2693
|
+
|
|
2694
|
+
console.print()
|
|
2695
|
+
|
|
2696
|
+
# Container Stats
|
|
2697
|
+
container_stats = monitor.get_container_stats()
|
|
2698
|
+
if container_stats:
|
|
2699
|
+
table = Table(title="🐳 Containers", border_style="blue")
|
|
2700
|
+
table.add_column("Name", style="bold")
|
|
2701
|
+
table.add_column("State")
|
|
2702
|
+
table.add_column("CPU %")
|
|
2703
|
+
table.add_column("Memory")
|
|
2704
|
+
table.add_column("Network I/O")
|
|
2705
|
+
table.add_column("PIDs")
|
|
2706
|
+
|
|
2707
|
+
for c in container_stats:
|
|
2708
|
+
cpu_color = "red" if c.cpu_percent > 80 else "green"
|
|
2709
|
+
mem_pct = (
|
|
2710
|
+
(c.memory_used_mb / c.memory_limit_mb * 100) if c.memory_limit_mb > 0 else 0
|
|
2711
|
+
)
|
|
2712
|
+
mem_color = "red" if mem_pct > 80 else "green"
|
|
2713
|
+
|
|
2714
|
+
table.add_row(
|
|
2715
|
+
c.name,
|
|
2716
|
+
f"[green]{c.state}[/]",
|
|
2717
|
+
f"[{cpu_color}]{c.cpu_percent:.1f}%[/]",
|
|
2718
|
+
f"[{mem_color}]{c.memory_used_mb}/{c.memory_limit_mb} MB[/]",
|
|
2719
|
+
f"↓{format_bytes(c.network_rx_bytes)} ↑{format_bytes(c.network_tx_bytes)}",
|
|
2720
|
+
str(c.pids),
|
|
2721
|
+
)
|
|
2722
|
+
console.print(table)
|
|
2723
|
+
else:
|
|
2724
|
+
console.print("[dim]No containers running.[/]")
|
|
2725
|
+
|
|
2726
|
+
if once:
|
|
2727
|
+
break
|
|
2728
|
+
|
|
2729
|
+
console.print(f"\n[dim]Refreshing every {refresh}s. Press Ctrl+C to exit.[/]")
|
|
2730
|
+
time.sleep(refresh)
|
|
2731
|
+
|
|
2732
|
+
except KeyboardInterrupt:
|
|
2733
|
+
console.print("\n[yellow]Monitoring stopped.[/]")
|
|
2734
|
+
finally:
|
|
2735
|
+
monitor.close()
|
|
2736
|
+
|
|
2737
|
+
|
|
2738
|
+
def cmd_exec(args) -> None:
|
|
2739
|
+
"""Execute command in VM via QEMU Guest Agent."""
|
|
2740
|
+
vm_name, config_file = _resolve_vm_name_and_config_file(args.name)
|
|
2741
|
+
conn_uri = "qemu:///session" if getattr(args, "user", False) else "qemu:///system"
|
|
2742
|
+
command = args.command
|
|
2743
|
+
timeout = getattr(args, "timeout", 30)
|
|
2744
|
+
|
|
2745
|
+
if not _qga_ping(vm_name, conn_uri):
|
|
2746
|
+
console.print(f"[red]❌ Cannot connect to VM '{vm_name}' via QEMU Guest Agent[/]")
|
|
2747
|
+
console.print("[dim]Make sure the VM is running and qemu-guest-agent is installed.[/]")
|
|
2748
|
+
return
|
|
2749
|
+
|
|
2750
|
+
console.print(f"[cyan]▶ Executing in {vm_name}:[/] {command}")
|
|
2751
|
+
|
|
2752
|
+
result = _qga_exec(vm_name, conn_uri, command, timeout=timeout)
|
|
2753
|
+
|
|
2754
|
+
if result is None:
|
|
2755
|
+
console.print("[red]❌ Command execution failed or timed out[/]")
|
|
2756
|
+
elif result == "":
|
|
2757
|
+
console.print("[dim](no output)[/]")
|
|
2758
|
+
else:
|
|
2759
|
+
console.print(result)
|
|
2760
|
+
|
|
2761
|
+
|
|
2762
|
+
def cmd_snapshot_create(args) -> None:
|
|
2763
|
+
"""Create VM snapshot."""
|
|
2764
|
+
vm_name, config_file = _resolve_vm_name_and_config_file(args.vm_name)
|
|
2765
|
+
conn_uri = "qemu:///session" if getattr(args, "user", False) else "qemu:///system"
|
|
2766
|
+
|
|
2767
|
+
snap_name = args.name or f"snap-{datetime.now().strftime('%Y%m%d-%H%M%S')}"
|
|
2768
|
+
description = getattr(args, "description", None)
|
|
2769
|
+
|
|
2770
|
+
console.print(f"[cyan]📸 Creating snapshot: {snap_name}[/]")
|
|
2771
|
+
|
|
2772
|
+
try:
|
|
2773
|
+
manager = SnapshotManager(conn_uri)
|
|
2774
|
+
snapshot = manager.create(
|
|
2775
|
+
vm_name=vm_name,
|
|
2776
|
+
name=snap_name,
|
|
2777
|
+
description=description,
|
|
2778
|
+
snapshot_type=SnapshotType.DISK_ONLY,
|
|
2779
|
+
)
|
|
2780
|
+
console.print(f"[green]✅ Snapshot created: {snapshot.name}[/]")
|
|
2781
|
+
except Exception as e:
|
|
2782
|
+
console.print(f"[red]❌ Failed to create snapshot: {e}[/]")
|
|
2783
|
+
finally:
|
|
2784
|
+
manager.close()
|
|
2785
|
+
|
|
2786
|
+
|
|
2787
|
+
def cmd_snapshot_list(args) -> None:
|
|
2788
|
+
"""List VM snapshots."""
|
|
2789
|
+
vm_name, config_file = _resolve_vm_name_and_config_file(args.vm_name)
|
|
2790
|
+
conn_uri = "qemu:///session" if getattr(args, "user", False) else "qemu:///system"
|
|
2791
|
+
|
|
2792
|
+
try:
|
|
2793
|
+
manager = SnapshotManager(conn_uri)
|
|
2794
|
+
snapshots = manager.list(vm_name)
|
|
2795
|
+
|
|
2796
|
+
if not snapshots:
|
|
2797
|
+
console.print("[dim]No snapshots found.[/]")
|
|
2798
|
+
return
|
|
2799
|
+
|
|
2800
|
+
table = Table(title=f"📸 Snapshots for {vm_name}", border_style="cyan")
|
|
2801
|
+
table.add_column("Name", style="bold")
|
|
2802
|
+
table.add_column("Created")
|
|
2803
|
+
table.add_column("Type")
|
|
2804
|
+
table.add_column("Description")
|
|
2805
|
+
|
|
2806
|
+
for snap in snapshots:
|
|
2807
|
+
table.add_row(
|
|
2808
|
+
snap.name,
|
|
2809
|
+
snap.created_at.strftime("%Y-%m-%d %H:%M"),
|
|
2810
|
+
snap.snapshot_type.value,
|
|
2811
|
+
snap.description or "-",
|
|
2812
|
+
)
|
|
2813
|
+
|
|
2814
|
+
console.print(table)
|
|
2815
|
+
except Exception as e:
|
|
2816
|
+
console.print(f"[red]❌ Error: {e}[/]")
|
|
2817
|
+
finally:
|
|
2818
|
+
manager.close()
|
|
2819
|
+
|
|
2820
|
+
|
|
2821
|
+
def cmd_snapshot_restore(args) -> None:
|
|
2822
|
+
"""Restore VM to snapshot."""
|
|
2823
|
+
vm_name, config_file = _resolve_vm_name_and_config_file(args.vm_name)
|
|
2824
|
+
conn_uri = "qemu:///session" if getattr(args, "user", False) else "qemu:///system"
|
|
2825
|
+
|
|
2826
|
+
console.print(f"[cyan]🔄 Restoring snapshot: {args.name}[/]")
|
|
2827
|
+
|
|
2828
|
+
try:
|
|
2829
|
+
manager = SnapshotManager(conn_uri)
|
|
2830
|
+
manager.restore(vm_name, args.name, force=getattr(args, "force", False))
|
|
2831
|
+
console.print(f"[green]✅ Restored to snapshot: {args.name}[/]")
|
|
2832
|
+
except Exception as e:
|
|
2833
|
+
console.print(f"[red]❌ Failed to restore: {e}[/]")
|
|
2834
|
+
finally:
|
|
2835
|
+
manager.close()
|
|
2836
|
+
|
|
2837
|
+
|
|
2838
|
+
def cmd_snapshot_delete(args) -> None:
|
|
2839
|
+
"""Delete VM snapshot."""
|
|
2840
|
+
vm_name, config_file = _resolve_vm_name_and_config_file(args.vm_name)
|
|
2841
|
+
conn_uri = "qemu:///session" if getattr(args, "user", False) else "qemu:///system"
|
|
2842
|
+
|
|
2843
|
+
console.print(f"[cyan]🗑️ Deleting snapshot: {args.name}[/]")
|
|
2844
|
+
|
|
2845
|
+
try:
|
|
2846
|
+
manager = SnapshotManager(conn_uri)
|
|
2847
|
+
manager.delete(vm_name, args.name)
|
|
2848
|
+
console.print(f"[green]✅ Snapshot deleted: {args.name}[/]")
|
|
2849
|
+
except Exception as e:
|
|
2850
|
+
console.print(f"[red]❌ Failed to delete: {e}[/]")
|
|
2851
|
+
finally:
|
|
2852
|
+
manager.close()
|
|
2853
|
+
|
|
2854
|
+
|
|
2855
|
+
def cmd_health(args) -> None:
|
|
2856
|
+
"""Run health checks for VM."""
|
|
2857
|
+
vm_name, config_file = _resolve_vm_name_and_config_file(args.name)
|
|
2858
|
+
|
|
2859
|
+
console.print(f"[cyan]🏥 Running health checks for: {vm_name}[/]")
|
|
2860
|
+
|
|
2861
|
+
manager = HealthCheckManager()
|
|
2862
|
+
|
|
2863
|
+
# Load probes from config or use defaults
|
|
2864
|
+
probes = []
|
|
2865
|
+
if config_file and config_file.exists():
|
|
2866
|
+
import yaml
|
|
2867
|
+
|
|
2868
|
+
config = yaml.safe_load(config_file.read_text())
|
|
2869
|
+
health_checks = config.get("health_checks", [])
|
|
2870
|
+
for hc in health_checks:
|
|
2871
|
+
probes.append(ProbeConfig.from_dict(hc))
|
|
2872
|
+
|
|
2873
|
+
# Also create probes for services
|
|
2874
|
+
services = config.get("services", [])
|
|
2875
|
+
if services:
|
|
2876
|
+
probes.extend(manager.create_default_probes(services))
|
|
2877
|
+
|
|
2878
|
+
if not probes:
|
|
2879
|
+
console.print(
|
|
2880
|
+
"[yellow]No health checks configured. Add 'health_checks' to .clonebox.yaml[/]"
|
|
2881
|
+
)
|
|
2882
|
+
return
|
|
2883
|
+
|
|
2884
|
+
state = manager.check(vm_name, probes)
|
|
2885
|
+
|
|
2886
|
+
# Display results
|
|
2887
|
+
status_color = "green" if state.overall_status.value == "healthy" else "red"
|
|
2888
|
+
console.print(
|
|
2889
|
+
f"\n[bold]Overall Status:[/] [{status_color}]{state.overall_status.value.upper()}[/]"
|
|
2890
|
+
)
|
|
2891
|
+
|
|
2892
|
+
table = Table(title="Health Check Results", border_style="cyan")
|
|
2893
|
+
table.add_column("Probe", style="bold")
|
|
2894
|
+
table.add_column("Status")
|
|
2895
|
+
table.add_column("Duration")
|
|
2896
|
+
table.add_column("Message")
|
|
2897
|
+
|
|
2898
|
+
for result in state.check_results:
|
|
2899
|
+
status_color = "green" if result.is_healthy else "red"
|
|
2900
|
+
table.add_row(
|
|
2901
|
+
result.probe_name,
|
|
2902
|
+
f"[{status_color}]{result.status.value}[/]",
|
|
2903
|
+
f"{result.duration_ms:.0f}ms",
|
|
2904
|
+
result.message or result.error or "-",
|
|
2905
|
+
)
|
|
2906
|
+
|
|
2907
|
+
console.print(table)
|
|
2908
|
+
|
|
2909
|
+
|
|
2641
2910
|
def cmd_keygen(args) -> None:
|
|
2642
2911
|
"""Generate encryption key for secure P2P transfers."""
|
|
2643
2912
|
key_path = SecureExporter.generate_key()
|
|
@@ -3198,10 +3467,76 @@ def main():
|
|
|
3198
3467
|
)
|
|
3199
3468
|
test_parser.set_defaults(func=cmd_test)
|
|
3200
3469
|
|
|
3470
|
+
# Monitor command - real-time resource monitoring
|
|
3471
|
+
monitor_parser = subparsers.add_parser("monitor", help="Real-time resource monitoring")
|
|
3472
|
+
monitor_parser.add_argument(
|
|
3473
|
+
"-u", "--user", action="store_true", help="Use user session (qemu:///session)"
|
|
3474
|
+
)
|
|
3475
|
+
monitor_parser.add_argument(
|
|
3476
|
+
"--refresh", "-r", type=float, default=2.0, help="Refresh interval in seconds (default: 2)"
|
|
3477
|
+
)
|
|
3478
|
+
monitor_parser.add_argument("--once", action="store_true", help="Show stats once and exit")
|
|
3479
|
+
monitor_parser.set_defaults(func=cmd_monitor)
|
|
3480
|
+
|
|
3481
|
+
# Exec command - execute command in VM
|
|
3482
|
+
exec_parser = subparsers.add_parser("exec", help="Execute command in VM via QEMU Guest Agent")
|
|
3483
|
+
exec_parser.add_argument(
|
|
3484
|
+
"name", nargs="?", default=None, help="VM name or '.' to use .clonebox.yaml"
|
|
3485
|
+
)
|
|
3486
|
+
exec_parser.add_argument("command", help="Command to execute in VM")
|
|
3487
|
+
exec_parser.add_argument(
|
|
3488
|
+
"-u", "--user", action="store_true", help="Use user session (qemu:///session)"
|
|
3489
|
+
)
|
|
3490
|
+
exec_parser.add_argument(
|
|
3491
|
+
"--timeout", "-t", type=int, default=30, help="Command timeout in seconds (default: 30)"
|
|
3492
|
+
)
|
|
3493
|
+
exec_parser.set_defaults(func=cmd_exec)
|
|
3494
|
+
|
|
3495
|
+
# === Snapshot Commands ===
|
|
3496
|
+
snapshot_parser = subparsers.add_parser("snapshot", help="Manage VM snapshots")
|
|
3497
|
+
snapshot_sub = snapshot_parser.add_subparsers(dest="snapshot_command", help="Snapshot commands")
|
|
3498
|
+
|
|
3499
|
+
snap_create = snapshot_sub.add_parser("create", help="Create snapshot")
|
|
3500
|
+
snap_create.add_argument("vm_name", help="VM name or '.' to use .clonebox.yaml")
|
|
3501
|
+
snap_create.add_argument("--name", "-n", help="Snapshot name (auto-generated if not provided)")
|
|
3502
|
+
snap_create.add_argument("--description", "-d", help="Snapshot description")
|
|
3503
|
+
snap_create.add_argument("-u", "--user", action="store_true", help="Use user session")
|
|
3504
|
+
snap_create.set_defaults(func=cmd_snapshot_create)
|
|
3505
|
+
|
|
3506
|
+
snap_list = snapshot_sub.add_parser("list", aliases=["ls"], help="List snapshots")
|
|
3507
|
+
snap_list.add_argument("vm_name", help="VM name or '.' to use .clonebox.yaml")
|
|
3508
|
+
snap_list.add_argument("-u", "--user", action="store_true", help="Use user session")
|
|
3509
|
+
snap_list.set_defaults(func=cmd_snapshot_list)
|
|
3510
|
+
|
|
3511
|
+
snap_restore = snapshot_sub.add_parser("restore", help="Restore to snapshot")
|
|
3512
|
+
snap_restore.add_argument("vm_name", help="VM name or '.' to use .clonebox.yaml")
|
|
3513
|
+
snap_restore.add_argument("--name", "-n", required=True, help="Snapshot name to restore")
|
|
3514
|
+
snap_restore.add_argument("-u", "--user", action="store_true", help="Use user session")
|
|
3515
|
+
snap_restore.add_argument(
|
|
3516
|
+
"-f", "--force", action="store_true", help="Force restore even if running"
|
|
3517
|
+
)
|
|
3518
|
+
snap_restore.set_defaults(func=cmd_snapshot_restore)
|
|
3519
|
+
|
|
3520
|
+
snap_delete = snapshot_sub.add_parser("delete", aliases=["rm"], help="Delete snapshot")
|
|
3521
|
+
snap_delete.add_argument("vm_name", help="VM name or '.' to use .clonebox.yaml")
|
|
3522
|
+
snap_delete.add_argument("--name", "-n", required=True, help="Snapshot name to delete")
|
|
3523
|
+
snap_delete.add_argument("-u", "--user", action="store_true", help="Use user session")
|
|
3524
|
+
snap_delete.set_defaults(func=cmd_snapshot_delete)
|
|
3525
|
+
|
|
3526
|
+
# === Health Check Commands ===
|
|
3527
|
+
health_parser = subparsers.add_parser("health", help="Run health checks for VM")
|
|
3528
|
+
health_parser.add_argument(
|
|
3529
|
+
"name", nargs="?", default=None, help="VM name or '.' to use .clonebox.yaml"
|
|
3530
|
+
)
|
|
3531
|
+
health_parser.add_argument("-u", "--user", action="store_true", help="Use user session")
|
|
3532
|
+
health_parser.set_defaults(func=cmd_health)
|
|
3533
|
+
|
|
3201
3534
|
# === P2P Secure Transfer Commands ===
|
|
3202
3535
|
|
|
3203
3536
|
# Keygen command - generate encryption key
|
|
3204
|
-
keygen_parser = subparsers.add_parser(
|
|
3537
|
+
keygen_parser = subparsers.add_parser(
|
|
3538
|
+
"keygen", help="Generate encryption key for secure transfers"
|
|
3539
|
+
)
|
|
3205
3540
|
keygen_parser.set_defaults(func=cmd_keygen)
|
|
3206
3541
|
|
|
3207
3542
|
# Export-encrypted command
|
|
@@ -3214,9 +3549,7 @@ def main():
|
|
|
3214
3549
|
export_enc_parser.add_argument(
|
|
3215
3550
|
"-u", "--user", action="store_true", help="Use user session (qemu:///session)"
|
|
3216
3551
|
)
|
|
3217
|
-
export_enc_parser.add_argument(
|
|
3218
|
-
"-o", "--output", help="Output file (default: <vmname>.enc)"
|
|
3219
|
-
)
|
|
3552
|
+
export_enc_parser.add_argument("-o", "--output", help="Output file (default: <vmname>.enc)")
|
|
3220
3553
|
export_enc_parser.add_argument(
|
|
3221
3554
|
"--user-data", action="store_true", help="Include user data (SSH keys, configs)"
|
|
3222
3555
|
)
|
|
@@ -3234,9 +3567,7 @@ def main():
|
|
|
3234
3567
|
"-u", "--user", action="store_true", help="Use user session (qemu:///session)"
|
|
3235
3568
|
)
|
|
3236
3569
|
import_enc_parser.add_argument("--name", "-n", help="New name for imported VM")
|
|
3237
|
-
import_enc_parser.add_argument(
|
|
3238
|
-
"--user-data", action="store_true", help="Import user data"
|
|
3239
|
-
)
|
|
3570
|
+
import_enc_parser.add_argument("--user-data", action="store_true", help="Import user data")
|
|
3240
3571
|
import_enc_parser.add_argument(
|
|
3241
3572
|
"--include-data", "-d", action="store_true", help="Import app data"
|
|
3242
3573
|
)
|
|
@@ -3248,15 +3579,11 @@ def main():
|
|
|
3248
3579
|
)
|
|
3249
3580
|
export_remote_parser.add_argument("host", help="Remote host (user@hostname)")
|
|
3250
3581
|
export_remote_parser.add_argument("vm_name", help="VM name on remote host")
|
|
3251
|
-
export_remote_parser.add_argument(
|
|
3252
|
-
"-o", "--output", required=True, help="Local output file"
|
|
3253
|
-
)
|
|
3582
|
+
export_remote_parser.add_argument("-o", "--output", required=True, help="Local output file")
|
|
3254
3583
|
export_remote_parser.add_argument(
|
|
3255
3584
|
"--encrypted", "-e", action="store_true", help="Use encrypted export"
|
|
3256
3585
|
)
|
|
3257
|
-
export_remote_parser.add_argument(
|
|
3258
|
-
"--user-data", action="store_true", help="Include user data"
|
|
3259
|
-
)
|
|
3586
|
+
export_remote_parser.add_argument("--user-data", action="store_true", help="Include user data")
|
|
3260
3587
|
export_remote_parser.add_argument(
|
|
3261
3588
|
"--include-data", "-d", action="store_true", help="Include app data"
|
|
3262
3589
|
)
|
|
@@ -3272,22 +3599,16 @@ def main():
|
|
|
3272
3599
|
import_remote_parser.add_argument(
|
|
3273
3600
|
"--encrypted", "-e", action="store_true", help="Use encrypted import"
|
|
3274
3601
|
)
|
|
3275
|
-
import_remote_parser.add_argument(
|
|
3276
|
-
"--user-data", action="store_true", help="Import user data"
|
|
3277
|
-
)
|
|
3602
|
+
import_remote_parser.add_argument("--user-data", action="store_true", help="Import user data")
|
|
3278
3603
|
import_remote_parser.set_defaults(func=cmd_import_remote)
|
|
3279
3604
|
|
|
3280
3605
|
# Sync-key command
|
|
3281
|
-
sync_key_parser = subparsers.add_parser(
|
|
3282
|
-
"sync-key", help="Sync encryption key to remote host"
|
|
3283
|
-
)
|
|
3606
|
+
sync_key_parser = subparsers.add_parser("sync-key", help="Sync encryption key to remote host")
|
|
3284
3607
|
sync_key_parser.add_argument("host", help="Remote host (user@hostname)")
|
|
3285
3608
|
sync_key_parser.set_defaults(func=cmd_sync_key)
|
|
3286
3609
|
|
|
3287
3610
|
# List-remote command
|
|
3288
|
-
list_remote_parser = subparsers.add_parser(
|
|
3289
|
-
"list-remote", help="List VMs on remote host"
|
|
3290
|
-
)
|
|
3611
|
+
list_remote_parser = subparsers.add_parser("list-remote", help="List VMs on remote host")
|
|
3291
3612
|
list_remote_parser.add_argument("host", help="Remote host (user@hostname)")
|
|
3292
3613
|
list_remote_parser.set_defaults(func=cmd_list_remote)
|
|
3293
3614
|
|