clonebox 1.1.4__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/backends/libvirt_backend.py +217 -0
- clonebox/backends/qemu_disk.py +52 -0
- clonebox/backends/subprocess_runner.py +56 -0
- clonebox/cli.py +227 -45
- clonebox/cloner.py +327 -189
- clonebox/di.py +176 -0
- clonebox/health/__init__.py +2 -1
- clonebox/health/manager.py +328 -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/models.py +2 -2
- clonebox/monitor.py +1 -3
- 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/manager.py +3 -9
- clonebox/snapshots/models.py +2 -6
- clonebox/validator.py +34 -0
- {clonebox-1.1.4.dist-info → clonebox-1.1.6.dist-info}/METADATA +52 -2
- clonebox-1.1.6.dist-info/RECORD +42 -0
- clonebox-1.1.4.dist-info/RECORD +0 -27
- {clonebox-1.1.4.dist-info → clonebox-1.1.6.dist-info}/WHEEL +0 -0
- {clonebox-1.1.4.dist-info → clonebox-1.1.6.dist-info}/entry_points.txt +0 -0
- {clonebox-1.1.4.dist-info → clonebox-1.1.6.dist-info}/licenses/LICENSE +0 -0
- {clonebox-1.1.4.dist-info → clonebox-1.1.6.dist-info}/top_level.txt +0 -0
clonebox/cli.py
CHANGED
|
@@ -32,6 +32,8 @@ from clonebox.exporter import SecureExporter, VMExporter
|
|
|
32
32
|
from clonebox.importer import SecureImporter, VMImporter
|
|
33
33
|
from clonebox.monitor import ResourceMonitor, format_bytes
|
|
34
34
|
from clonebox.p2p import P2PManager
|
|
35
|
+
from clonebox.snapshots import SnapshotManager, SnapshotType
|
|
36
|
+
from clonebox.health import HealthCheckManager, ProbeConfig, ProbeType
|
|
35
37
|
|
|
36
38
|
# Custom questionary style
|
|
37
39
|
custom_style = Style(
|
|
@@ -1850,18 +1852,21 @@ def cmd_test(args):
|
|
|
1850
1852
|
all_paths.update(config.get("app_data_paths", {}))
|
|
1851
1853
|
|
|
1852
1854
|
if all_paths:
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
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)[/]")
|
|
1865
1870
|
else:
|
|
1866
1871
|
console.print("[dim]No mount points configured[/]")
|
|
1867
1872
|
|
|
@@ -2098,7 +2103,7 @@ def generate_clonebox_yaml(
|
|
|
2098
2103
|
vm_name = f"clone-{sys_info['hostname']}"
|
|
2099
2104
|
|
|
2100
2105
|
# Calculate recommended resources
|
|
2101
|
-
ram_mb = min(
|
|
2106
|
+
ram_mb = min(8192, int(sys_info["memory_available_gb"] * 1024 * 0.5))
|
|
2102
2107
|
vcpus = max(2, sys_info["cpu_count"] // 2)
|
|
2103
2108
|
|
|
2104
2109
|
if disk_size_gb is None:
|
|
@@ -2331,8 +2336,8 @@ def create_vm_from_config(
|
|
|
2331
2336
|
|
|
2332
2337
|
vm_config = VMConfig(
|
|
2333
2338
|
name=config["vm"]["name"],
|
|
2334
|
-
ram_mb=config["vm"].get("ram_mb",
|
|
2335
|
-
vcpus=config["vm"].get("vcpus",
|
|
2339
|
+
ram_mb=config["vm"].get("ram_mb", 8192),
|
|
2340
|
+
vcpus=config["vm"].get("vcpus", 8),
|
|
2336
2341
|
disk_size_gb=config["vm"].get("disk_size_gb", 10),
|
|
2337
2342
|
gui=config["vm"].get("gui", True),
|
|
2338
2343
|
base_image=config["vm"].get("base_image"),
|
|
@@ -2670,7 +2675,11 @@ def cmd_monitor(args) -> None:
|
|
|
2670
2675
|
for vm in vm_stats:
|
|
2671
2676
|
state_color = "green" if vm.state == "running" else "yellow"
|
|
2672
2677
|
cpu_color = "red" if vm.cpu_percent > 80 else "green"
|
|
2673
|
-
mem_pct = (
|
|
2678
|
+
mem_pct = (
|
|
2679
|
+
(vm.memory_used_mb / vm.memory_total_mb * 100)
|
|
2680
|
+
if vm.memory_total_mb > 0
|
|
2681
|
+
else 0
|
|
2682
|
+
)
|
|
2674
2683
|
mem_color = "red" if mem_pct > 80 else "green"
|
|
2675
2684
|
|
|
2676
2685
|
table.add_row(
|
|
@@ -2700,7 +2709,9 @@ def cmd_monitor(args) -> None:
|
|
|
2700
2709
|
|
|
2701
2710
|
for c in container_stats:
|
|
2702
2711
|
cpu_color = "red" if c.cpu_percent > 80 else "green"
|
|
2703
|
-
mem_pct = (
|
|
2712
|
+
mem_pct = (
|
|
2713
|
+
(c.memory_used_mb / c.memory_limit_mb * 100) if c.memory_limit_mb > 0 else 0
|
|
2714
|
+
)
|
|
2704
2715
|
mem_color = "red" if mem_pct > 80 else "green"
|
|
2705
2716
|
|
|
2706
2717
|
table.add_row(
|
|
@@ -2751,6 +2762,154 @@ def cmd_exec(args) -> None:
|
|
|
2751
2762
|
console.print(result)
|
|
2752
2763
|
|
|
2753
2764
|
|
|
2765
|
+
def cmd_snapshot_create(args) -> None:
|
|
2766
|
+
"""Create VM snapshot."""
|
|
2767
|
+
vm_name, config_file = _resolve_vm_name_and_config_file(args.vm_name)
|
|
2768
|
+
conn_uri = "qemu:///session" if getattr(args, "user", False) else "qemu:///system"
|
|
2769
|
+
|
|
2770
|
+
snap_name = args.name or f"snap-{datetime.now().strftime('%Y%m%d-%H%M%S')}"
|
|
2771
|
+
description = getattr(args, "description", None)
|
|
2772
|
+
|
|
2773
|
+
console.print(f"[cyan]📸 Creating snapshot: {snap_name}[/]")
|
|
2774
|
+
|
|
2775
|
+
try:
|
|
2776
|
+
manager = SnapshotManager(conn_uri)
|
|
2777
|
+
snapshot = manager.create(
|
|
2778
|
+
vm_name=vm_name,
|
|
2779
|
+
name=snap_name,
|
|
2780
|
+
description=description,
|
|
2781
|
+
snapshot_type=SnapshotType.DISK_ONLY,
|
|
2782
|
+
)
|
|
2783
|
+
console.print(f"[green]✅ Snapshot created: {snapshot.name}[/]")
|
|
2784
|
+
except Exception as e:
|
|
2785
|
+
console.print(f"[red]❌ Failed to create snapshot: {e}[/]")
|
|
2786
|
+
finally:
|
|
2787
|
+
manager.close()
|
|
2788
|
+
|
|
2789
|
+
|
|
2790
|
+
def cmd_snapshot_list(args) -> None:
|
|
2791
|
+
"""List VM snapshots."""
|
|
2792
|
+
vm_name, config_file = _resolve_vm_name_and_config_file(args.vm_name)
|
|
2793
|
+
conn_uri = "qemu:///session" if getattr(args, "user", False) else "qemu:///system"
|
|
2794
|
+
|
|
2795
|
+
try:
|
|
2796
|
+
manager = SnapshotManager(conn_uri)
|
|
2797
|
+
snapshots = manager.list(vm_name)
|
|
2798
|
+
|
|
2799
|
+
if not snapshots:
|
|
2800
|
+
console.print("[dim]No snapshots found.[/]")
|
|
2801
|
+
return
|
|
2802
|
+
|
|
2803
|
+
table = Table(title=f"📸 Snapshots for {vm_name}", border_style="cyan")
|
|
2804
|
+
table.add_column("Name", style="bold")
|
|
2805
|
+
table.add_column("Created")
|
|
2806
|
+
table.add_column("Type")
|
|
2807
|
+
table.add_column("Description")
|
|
2808
|
+
|
|
2809
|
+
for snap in snapshots:
|
|
2810
|
+
table.add_row(
|
|
2811
|
+
snap.name,
|
|
2812
|
+
snap.created_at.strftime("%Y-%m-%d %H:%M"),
|
|
2813
|
+
snap.snapshot_type.value,
|
|
2814
|
+
snap.description or "-",
|
|
2815
|
+
)
|
|
2816
|
+
|
|
2817
|
+
console.print(table)
|
|
2818
|
+
except Exception as e:
|
|
2819
|
+
console.print(f"[red]❌ Error: {e}[/]")
|
|
2820
|
+
finally:
|
|
2821
|
+
manager.close()
|
|
2822
|
+
|
|
2823
|
+
|
|
2824
|
+
def cmd_snapshot_restore(args) -> None:
|
|
2825
|
+
"""Restore VM to snapshot."""
|
|
2826
|
+
vm_name, config_file = _resolve_vm_name_and_config_file(args.vm_name)
|
|
2827
|
+
conn_uri = "qemu:///session" if getattr(args, "user", False) else "qemu:///system"
|
|
2828
|
+
|
|
2829
|
+
console.print(f"[cyan]🔄 Restoring snapshot: {args.name}[/]")
|
|
2830
|
+
|
|
2831
|
+
try:
|
|
2832
|
+
manager = SnapshotManager(conn_uri)
|
|
2833
|
+
manager.restore(vm_name, args.name, force=getattr(args, "force", False))
|
|
2834
|
+
console.print(f"[green]✅ Restored to snapshot: {args.name}[/]")
|
|
2835
|
+
except Exception as e:
|
|
2836
|
+
console.print(f"[red]❌ Failed to restore: {e}[/]")
|
|
2837
|
+
finally:
|
|
2838
|
+
manager.close()
|
|
2839
|
+
|
|
2840
|
+
|
|
2841
|
+
def cmd_snapshot_delete(args) -> None:
|
|
2842
|
+
"""Delete VM snapshot."""
|
|
2843
|
+
vm_name, config_file = _resolve_vm_name_and_config_file(args.vm_name)
|
|
2844
|
+
conn_uri = "qemu:///session" if getattr(args, "user", False) else "qemu:///system"
|
|
2845
|
+
|
|
2846
|
+
console.print(f"[cyan]🗑️ Deleting snapshot: {args.name}[/]")
|
|
2847
|
+
|
|
2848
|
+
try:
|
|
2849
|
+
manager = SnapshotManager(conn_uri)
|
|
2850
|
+
manager.delete(vm_name, args.name)
|
|
2851
|
+
console.print(f"[green]✅ Snapshot deleted: {args.name}[/]")
|
|
2852
|
+
except Exception as e:
|
|
2853
|
+
console.print(f"[red]❌ Failed to delete: {e}[/]")
|
|
2854
|
+
finally:
|
|
2855
|
+
manager.close()
|
|
2856
|
+
|
|
2857
|
+
|
|
2858
|
+
def cmd_health(args) -> None:
|
|
2859
|
+
"""Run health checks for VM."""
|
|
2860
|
+
vm_name, config_file = _resolve_vm_name_and_config_file(args.name)
|
|
2861
|
+
|
|
2862
|
+
console.print(f"[cyan]🏥 Running health checks for: {vm_name}[/]")
|
|
2863
|
+
|
|
2864
|
+
manager = HealthCheckManager()
|
|
2865
|
+
|
|
2866
|
+
# Load probes from config or use defaults
|
|
2867
|
+
probes = []
|
|
2868
|
+
if config_file and config_file.exists():
|
|
2869
|
+
import yaml
|
|
2870
|
+
|
|
2871
|
+
config = yaml.safe_load(config_file.read_text())
|
|
2872
|
+
health_checks = config.get("health_checks", [])
|
|
2873
|
+
for hc in health_checks:
|
|
2874
|
+
probes.append(ProbeConfig.from_dict(hc))
|
|
2875
|
+
|
|
2876
|
+
# Also create probes for services
|
|
2877
|
+
services = config.get("services", [])
|
|
2878
|
+
if services:
|
|
2879
|
+
probes.extend(manager.create_default_probes(services))
|
|
2880
|
+
|
|
2881
|
+
if not probes:
|
|
2882
|
+
console.print(
|
|
2883
|
+
"[yellow]No health checks configured. Add 'health_checks' to .clonebox.yaml[/]"
|
|
2884
|
+
)
|
|
2885
|
+
return
|
|
2886
|
+
|
|
2887
|
+
state = manager.check(vm_name, probes)
|
|
2888
|
+
|
|
2889
|
+
# Display results
|
|
2890
|
+
status_color = "green" if state.overall_status.value == "healthy" else "red"
|
|
2891
|
+
console.print(
|
|
2892
|
+
f"\n[bold]Overall Status:[/] [{status_color}]{state.overall_status.value.upper()}[/]"
|
|
2893
|
+
)
|
|
2894
|
+
|
|
2895
|
+
table = Table(title="Health Check Results", border_style="cyan")
|
|
2896
|
+
table.add_column("Probe", style="bold")
|
|
2897
|
+
table.add_column("Status")
|
|
2898
|
+
table.add_column("Duration")
|
|
2899
|
+
table.add_column("Message")
|
|
2900
|
+
|
|
2901
|
+
for result in state.check_results:
|
|
2902
|
+
status_color = "green" if result.is_healthy else "red"
|
|
2903
|
+
table.add_row(
|
|
2904
|
+
result.probe_name,
|
|
2905
|
+
f"[{status_color}]{result.status.value}[/]",
|
|
2906
|
+
f"{result.duration_ms:.0f}ms",
|
|
2907
|
+
result.message or result.error or "-",
|
|
2908
|
+
)
|
|
2909
|
+
|
|
2910
|
+
console.print(table)
|
|
2911
|
+
|
|
2912
|
+
|
|
2754
2913
|
def cmd_keygen(args) -> None:
|
|
2755
2914
|
"""Generate encryption key for secure P2P transfers."""
|
|
2756
2915
|
key_path = SecureExporter.generate_key()
|
|
@@ -3319,9 +3478,7 @@ def main():
|
|
|
3319
3478
|
monitor_parser.add_argument(
|
|
3320
3479
|
"--refresh", "-r", type=float, default=2.0, help="Refresh interval in seconds (default: 2)"
|
|
3321
3480
|
)
|
|
3322
|
-
monitor_parser.add_argument(
|
|
3323
|
-
"--once", action="store_true", help="Show stats once and exit"
|
|
3324
|
-
)
|
|
3481
|
+
monitor_parser.add_argument("--once", action="store_true", help="Show stats once and exit")
|
|
3325
3482
|
monitor_parser.set_defaults(func=cmd_monitor)
|
|
3326
3483
|
|
|
3327
3484
|
# Exec command - execute command in VM
|
|
@@ -3329,9 +3486,7 @@ def main():
|
|
|
3329
3486
|
exec_parser.add_argument(
|
|
3330
3487
|
"name", nargs="?", default=None, help="VM name or '.' to use .clonebox.yaml"
|
|
3331
3488
|
)
|
|
3332
|
-
exec_parser.add_argument(
|
|
3333
|
-
"command", help="Command to execute in VM"
|
|
3334
|
-
)
|
|
3489
|
+
exec_parser.add_argument("command", help="Command to execute in VM")
|
|
3335
3490
|
exec_parser.add_argument(
|
|
3336
3491
|
"-u", "--user", action="store_true", help="Use user session (qemu:///session)"
|
|
3337
3492
|
)
|
|
@@ -3340,10 +3495,51 @@ def main():
|
|
|
3340
3495
|
)
|
|
3341
3496
|
exec_parser.set_defaults(func=cmd_exec)
|
|
3342
3497
|
|
|
3498
|
+
# === Snapshot Commands ===
|
|
3499
|
+
snapshot_parser = subparsers.add_parser("snapshot", help="Manage VM snapshots")
|
|
3500
|
+
snapshot_sub = snapshot_parser.add_subparsers(dest="snapshot_command", help="Snapshot commands")
|
|
3501
|
+
|
|
3502
|
+
snap_create = snapshot_sub.add_parser("create", help="Create snapshot")
|
|
3503
|
+
snap_create.add_argument("vm_name", help="VM name or '.' to use .clonebox.yaml")
|
|
3504
|
+
snap_create.add_argument("--name", "-n", help="Snapshot name (auto-generated if not provided)")
|
|
3505
|
+
snap_create.add_argument("--description", "-d", help="Snapshot description")
|
|
3506
|
+
snap_create.add_argument("-u", "--user", action="store_true", help="Use user session")
|
|
3507
|
+
snap_create.set_defaults(func=cmd_snapshot_create)
|
|
3508
|
+
|
|
3509
|
+
snap_list = snapshot_sub.add_parser("list", aliases=["ls"], help="List snapshots")
|
|
3510
|
+
snap_list.add_argument("vm_name", help="VM name or '.' to use .clonebox.yaml")
|
|
3511
|
+
snap_list.add_argument("-u", "--user", action="store_true", help="Use user session")
|
|
3512
|
+
snap_list.set_defaults(func=cmd_snapshot_list)
|
|
3513
|
+
|
|
3514
|
+
snap_restore = snapshot_sub.add_parser("restore", help="Restore to snapshot")
|
|
3515
|
+
snap_restore.add_argument("vm_name", help="VM name or '.' to use .clonebox.yaml")
|
|
3516
|
+
snap_restore.add_argument("--name", "-n", required=True, help="Snapshot name to restore")
|
|
3517
|
+
snap_restore.add_argument("-u", "--user", action="store_true", help="Use user session")
|
|
3518
|
+
snap_restore.add_argument(
|
|
3519
|
+
"-f", "--force", action="store_true", help="Force restore even if running"
|
|
3520
|
+
)
|
|
3521
|
+
snap_restore.set_defaults(func=cmd_snapshot_restore)
|
|
3522
|
+
|
|
3523
|
+
snap_delete = snapshot_sub.add_parser("delete", aliases=["rm"], help="Delete snapshot")
|
|
3524
|
+
snap_delete.add_argument("vm_name", help="VM name or '.' to use .clonebox.yaml")
|
|
3525
|
+
snap_delete.add_argument("--name", "-n", required=True, help="Snapshot name to delete")
|
|
3526
|
+
snap_delete.add_argument("-u", "--user", action="store_true", help="Use user session")
|
|
3527
|
+
snap_delete.set_defaults(func=cmd_snapshot_delete)
|
|
3528
|
+
|
|
3529
|
+
# === Health Check Commands ===
|
|
3530
|
+
health_parser = subparsers.add_parser("health", help="Run health checks for VM")
|
|
3531
|
+
health_parser.add_argument(
|
|
3532
|
+
"name", nargs="?", default=None, help="VM name or '.' to use .clonebox.yaml"
|
|
3533
|
+
)
|
|
3534
|
+
health_parser.add_argument("-u", "--user", action="store_true", help="Use user session")
|
|
3535
|
+
health_parser.set_defaults(func=cmd_health)
|
|
3536
|
+
|
|
3343
3537
|
# === P2P Secure Transfer Commands ===
|
|
3344
3538
|
|
|
3345
3539
|
# Keygen command - generate encryption key
|
|
3346
|
-
keygen_parser = subparsers.add_parser(
|
|
3540
|
+
keygen_parser = subparsers.add_parser(
|
|
3541
|
+
"keygen", help="Generate encryption key for secure transfers"
|
|
3542
|
+
)
|
|
3347
3543
|
keygen_parser.set_defaults(func=cmd_keygen)
|
|
3348
3544
|
|
|
3349
3545
|
# Export-encrypted command
|
|
@@ -3356,9 +3552,7 @@ def main():
|
|
|
3356
3552
|
export_enc_parser.add_argument(
|
|
3357
3553
|
"-u", "--user", action="store_true", help="Use user session (qemu:///session)"
|
|
3358
3554
|
)
|
|
3359
|
-
export_enc_parser.add_argument(
|
|
3360
|
-
"-o", "--output", help="Output file (default: <vmname>.enc)"
|
|
3361
|
-
)
|
|
3555
|
+
export_enc_parser.add_argument("-o", "--output", help="Output file (default: <vmname>.enc)")
|
|
3362
3556
|
export_enc_parser.add_argument(
|
|
3363
3557
|
"--user-data", action="store_true", help="Include user data (SSH keys, configs)"
|
|
3364
3558
|
)
|
|
@@ -3376,9 +3570,7 @@ def main():
|
|
|
3376
3570
|
"-u", "--user", action="store_true", help="Use user session (qemu:///session)"
|
|
3377
3571
|
)
|
|
3378
3572
|
import_enc_parser.add_argument("--name", "-n", help="New name for imported VM")
|
|
3379
|
-
import_enc_parser.add_argument(
|
|
3380
|
-
"--user-data", action="store_true", help="Import user data"
|
|
3381
|
-
)
|
|
3573
|
+
import_enc_parser.add_argument("--user-data", action="store_true", help="Import user data")
|
|
3382
3574
|
import_enc_parser.add_argument(
|
|
3383
3575
|
"--include-data", "-d", action="store_true", help="Import app data"
|
|
3384
3576
|
)
|
|
@@ -3390,15 +3582,11 @@ def main():
|
|
|
3390
3582
|
)
|
|
3391
3583
|
export_remote_parser.add_argument("host", help="Remote host (user@hostname)")
|
|
3392
3584
|
export_remote_parser.add_argument("vm_name", help="VM name on remote host")
|
|
3393
|
-
export_remote_parser.add_argument(
|
|
3394
|
-
"-o", "--output", required=True, help="Local output file"
|
|
3395
|
-
)
|
|
3585
|
+
export_remote_parser.add_argument("-o", "--output", required=True, help="Local output file")
|
|
3396
3586
|
export_remote_parser.add_argument(
|
|
3397
3587
|
"--encrypted", "-e", action="store_true", help="Use encrypted export"
|
|
3398
3588
|
)
|
|
3399
|
-
export_remote_parser.add_argument(
|
|
3400
|
-
"--user-data", action="store_true", help="Include user data"
|
|
3401
|
-
)
|
|
3589
|
+
export_remote_parser.add_argument("--user-data", action="store_true", help="Include user data")
|
|
3402
3590
|
export_remote_parser.add_argument(
|
|
3403
3591
|
"--include-data", "-d", action="store_true", help="Include app data"
|
|
3404
3592
|
)
|
|
@@ -3414,22 +3602,16 @@ def main():
|
|
|
3414
3602
|
import_remote_parser.add_argument(
|
|
3415
3603
|
"--encrypted", "-e", action="store_true", help="Use encrypted import"
|
|
3416
3604
|
)
|
|
3417
|
-
import_remote_parser.add_argument(
|
|
3418
|
-
"--user-data", action="store_true", help="Import user data"
|
|
3419
|
-
)
|
|
3605
|
+
import_remote_parser.add_argument("--user-data", action="store_true", help="Import user data")
|
|
3420
3606
|
import_remote_parser.set_defaults(func=cmd_import_remote)
|
|
3421
3607
|
|
|
3422
3608
|
# Sync-key command
|
|
3423
|
-
sync_key_parser = subparsers.add_parser(
|
|
3424
|
-
"sync-key", help="Sync encryption key to remote host"
|
|
3425
|
-
)
|
|
3609
|
+
sync_key_parser = subparsers.add_parser("sync-key", help="Sync encryption key to remote host")
|
|
3426
3610
|
sync_key_parser.add_argument("host", help="Remote host (user@hostname)")
|
|
3427
3611
|
sync_key_parser.set_defaults(func=cmd_sync_key)
|
|
3428
3612
|
|
|
3429
3613
|
# List-remote command
|
|
3430
|
-
list_remote_parser = subparsers.add_parser(
|
|
3431
|
-
"list-remote", help="List VMs on remote host"
|
|
3432
|
-
)
|
|
3614
|
+
list_remote_parser = subparsers.add_parser("list-remote", help="List VMs on remote host")
|
|
3433
3615
|
list_remote_parser.add_argument("host", help="Remote host (user@hostname)")
|
|
3434
3616
|
list_remote_parser.set_defaults(func=cmd_list_remote)
|
|
3435
3617
|
|