clonebox 0.1.1__py3-none-any.whl → 0.1.3__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/cloner.py CHANGED
@@ -31,6 +31,8 @@ class VMConfig:
31
31
  paths: dict = field(default_factory=dict)
32
32
  packages: list = field(default_factory=list)
33
33
  services: list = field(default_factory=list)
34
+ user_session: bool = False # Use qemu:///session instead of qemu:///system
35
+ network_mode: str = "auto" # auto|default|user
34
36
 
35
37
  def to_dict(self) -> dict:
36
38
  return {
@@ -46,8 +48,16 @@ class SelectiveVMCloner:
46
48
  Uses bind mounts instead of full disk cloning.
47
49
  """
48
50
 
49
- def __init__(self, conn_uri: str = "qemu:///system"):
50
- self.conn_uri = conn_uri
51
+ # Default images directories
52
+ SYSTEM_IMAGES_DIR = Path("/var/lib/libvirt/images")
53
+ USER_IMAGES_DIR = Path.home() / ".local/share/libvirt/images"
54
+
55
+ def __init__(self, conn_uri: str = None, user_session: bool = False):
56
+ self.user_session = user_session
57
+ if conn_uri:
58
+ self.conn_uri = conn_uri
59
+ else:
60
+ self.conn_uri = "qemu:///session" if user_session else "qemu:///system"
51
61
  self.conn = None
52
62
  self._connect()
53
63
 
@@ -59,17 +69,59 @@ class SelectiveVMCloner:
59
69
  "Also ensure libvirt is installed: sudo apt install libvirt-daemon-system"
60
70
  )
61
71
 
62
- self.conn = libvirt.open(self.conn_uri)
72
+ try:
73
+ self.conn = libvirt.open(self.conn_uri)
74
+ except libvirt.libvirtError as e:
75
+ raise ConnectionError(
76
+ f"Cannot connect to {self.conn_uri}\n"
77
+ f"Error: {e}\n\n"
78
+ f"Troubleshooting:\n"
79
+ f" 1. Check if libvirtd is running: sudo systemctl status libvirtd\n"
80
+ f" 2. Start libvirtd: sudo systemctl start libvirtd\n"
81
+ f" 3. Add user to libvirt group: sudo usermod -aG libvirt $USER\n"
82
+ f" 4. Re-login or run: newgrp libvirt\n"
83
+ f" 5. For user session (no sudo): use --user flag"
84
+ )
85
+
63
86
  if self.conn is None:
64
87
  raise ConnectionError(f"Cannot connect to {self.conn_uri}")
65
88
 
89
+ def get_images_dir(self) -> Path:
90
+ """Get the appropriate images directory based on session type."""
91
+ if self.user_session:
92
+ return self.USER_IMAGES_DIR
93
+ return self.SYSTEM_IMAGES_DIR
94
+
95
+ def _default_network_active(self) -> bool:
96
+ """Check if libvirt default network is active."""
97
+ try:
98
+ net = self.conn.networkLookupByName("default")
99
+ return net.isActive() == 1
100
+ except libvirt.libvirtError:
101
+ return False
102
+
103
+ def resolve_network_mode(self, config: VMConfig) -> str:
104
+ """Resolve network mode based on config and session type."""
105
+ mode = (config.network_mode or "auto").lower()
106
+ if mode == "auto":
107
+ if self.user_session and not self._default_network_active():
108
+ return "user"
109
+ return "default"
110
+ if mode in {"default", "user"}:
111
+ return mode
112
+ return "default"
113
+
66
114
  def check_prerequisites(self) -> dict:
67
115
  """Check system prerequisites for VM creation."""
116
+ images_dir = self.get_images_dir()
117
+
68
118
  checks = {
69
119
  "libvirt_connected": False,
70
120
  "kvm_available": False,
71
121
  "default_network": False,
72
122
  "images_dir_writable": False,
123
+ "images_dir": str(images_dir),
124
+ "session_type": "user" if self.user_session else "system",
73
125
  }
74
126
 
75
127
  # Check libvirt connection
@@ -77,18 +129,48 @@ class SelectiveVMCloner:
77
129
  checks["libvirt_connected"] = True
78
130
 
79
131
  # Check KVM
80
- checks["kvm_available"] = Path("/dev/kvm").exists()
132
+ kvm_path = Path("/dev/kvm")
133
+ checks["kvm_available"] = kvm_path.exists()
134
+ if not checks["kvm_available"]:
135
+ checks["kvm_error"] = "KVM not available. Enable virtualization in BIOS."
136
+ elif not os.access(kvm_path, os.R_OK | os.W_OK):
137
+ checks["kvm_error"] = f"No access to /dev/kvm. Add user to kvm group: sudo usermod -aG kvm $USER"
81
138
 
82
139
  # Check default network
83
140
  try:
84
141
  net = self.conn.networkLookupByName("default")
85
142
  checks["default_network"] = net.isActive() == 1
86
143
  except libvirt.libvirtError:
87
- pass
144
+ checks["network_error"] = (
145
+ "Default network not found or inactive.\n"
146
+ " For user session, CloneBox can use user-mode networking (slirp) automatically.\n"
147
+ " Or create a user network:\n"
148
+ " virsh --connect qemu:///session net-define /tmp/default-network.xml\n"
149
+ " virsh --connect qemu:///session net-start default\n"
150
+ " Or use system session: clonebox clone . (without --user)\n"
151
+ )
88
152
 
89
153
  # Check images directory
90
- images_dir = Path("/var/lib/libvirt/images")
91
- checks["images_dir_writable"] = images_dir.exists() and os.access(images_dir, os.W_OK)
154
+ if images_dir.exists():
155
+ checks["images_dir_writable"] = os.access(images_dir, os.W_OK)
156
+ if not checks["images_dir_writable"]:
157
+ checks["images_dir_error"] = (
158
+ f"Cannot write to {images_dir}\n"
159
+ f" Option 1: Run with sudo\n"
160
+ f" Option 2: Use --user flag for user session (no root needed)\n"
161
+ f" Option 3: Fix permissions: sudo chown -R $USER:libvirt {images_dir}"
162
+ )
163
+ else:
164
+ # Try to create it
165
+ try:
166
+ images_dir.mkdir(parents=True, exist_ok=True)
167
+ checks["images_dir_writable"] = True
168
+ except PermissionError:
169
+ checks["images_dir_writable"] = False
170
+ checks["images_dir_error"] = (
171
+ f"Cannot create {images_dir}\n"
172
+ f" Use --user flag for user session (stores in ~/.local/share/libvirt/images/)"
173
+ )
92
174
 
93
175
  return checks
94
176
 
@@ -109,8 +191,25 @@ class SelectiveVMCloner:
109
191
  else:
110
192
  print(msg)
111
193
 
112
- vm_dir = Path(f"/var/lib/libvirt/images/{config.name}")
113
- vm_dir.mkdir(parents=True, exist_ok=True)
194
+ # Determine images directory
195
+ images_dir = self.get_images_dir()
196
+ vm_dir = images_dir / config.name
197
+
198
+ try:
199
+ vm_dir.mkdir(parents=True, exist_ok=True)
200
+ except PermissionError as e:
201
+ raise PermissionError(
202
+ f"Cannot create VM directory: {vm_dir}\n\n"
203
+ f"🔧 Solutions:\n"
204
+ f" 1. Use --user flag to run in user session (recommended):\n"
205
+ f" clonebox clone . --user\n\n"
206
+ f" 2. Run with sudo (not recommended):\n"
207
+ f" sudo clonebox clone .\n\n"
208
+ f" 3. Fix directory permissions:\n"
209
+ f" sudo mkdir -p {images_dir}\n"
210
+ f" sudo chown -R $USER:libvirt {images_dir}\n\n"
211
+ f"Original error: {e}"
212
+ ) from e
114
213
 
115
214
  # Create root disk
116
215
  root_disk = vm_dir / "root.qcow2"
@@ -139,6 +238,13 @@ class SelectiveVMCloner:
139
238
  cloudinit_iso = self._create_cloudinit_iso(vm_dir, config)
140
239
  log(f"[cyan]☁️ Created cloud-init ISO with {len(config.packages)} packages[/]")
141
240
 
241
+ # Resolve network mode
242
+ network_mode = self.resolve_network_mode(config)
243
+ if network_mode == "user":
244
+ log("[yellow]⚠️ Using user-mode networking (slirp) because default libvirt network is unavailable[/]")
245
+ else:
246
+ log(f"[dim]Network mode: {network_mode}[/]")
247
+
142
248
  # Generate VM XML
143
249
  vm_xml = self._generate_vm_xml(config, root_disk, cloudinit_iso)
144
250
 
@@ -212,9 +318,14 @@ class SelectiveVMCloner:
212
318
  ET.SubElement(fs, "target", dir=tag)
213
319
 
214
320
  # Network interface
215
- iface = ET.SubElement(devices, "interface", type="network")
216
- ET.SubElement(iface, "source", network="default")
217
- ET.SubElement(iface, "model", type="virtio")
321
+ network_mode = self.resolve_network_mode(config)
322
+ if network_mode == "user":
323
+ iface = ET.SubElement(devices, "interface", type="user")
324
+ ET.SubElement(iface, "model", type="virtio")
325
+ else:
326
+ iface = ET.SubElement(devices, "interface", type="network")
327
+ ET.SubElement(iface, "source", network="default")
328
+ ET.SubElement(iface, "model", type="virtio")
218
329
 
219
330
  # Serial console
220
331
  serial = ET.SubElement(devices, "serial", type="pty")
clonebox/detector.py CHANGED
@@ -276,6 +276,8 @@ class SystemDetector:
276
276
  def _get_dir_size(self, path: Path, max_depth: int = 2) -> int:
277
277
  """Get approximate directory size in bytes."""
278
278
  total = 0
279
+ if not path.exists():
280
+ return 0
279
281
  try:
280
282
  for item in path.iterdir():
281
283
  if item.is_file():
@@ -285,7 +287,7 @@ class SystemDetector:
285
287
  pass
286
288
  elif item.is_dir() and max_depth > 0 and not item.is_symlink():
287
289
  total += self._get_dir_size(item, max_depth - 1)
288
- except PermissionError:
290
+ except (PermissionError, FileNotFoundError, OSError):
289
291
  pass
290
292
  return total
291
293
 
@@ -0,0 +1,379 @@
1
+ Metadata-Version: 2.4
2
+ Name: clonebox
3
+ Version: 0.1.3
4
+ Summary: Clone your workstation environment to an isolated VM with selective apps, paths and services
5
+ Author: CloneBox Team
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/wronai/clonebox
8
+ Project-URL: Repository, https://github.com/wronai/clonebox
9
+ Project-URL: Issues, https://github.com/wronai/clonebox/issues
10
+ Keywords: vm,virtualization,libvirt,clone,workstation,qemu,kvm
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: System Administrators
15
+ Classifier: License :: OSI Approved :: Apache Software License
16
+ Classifier: Operating System :: POSIX :: Linux
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.8
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Topic :: System :: Systems Administration
24
+ Classifier: Topic :: Utilities
25
+ Requires-Python: >=3.8
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Requires-Dist: libvirt-python>=9.0.0
29
+ Requires-Dist: rich>=13.0.0
30
+ Requires-Dist: questionary>=2.0.0
31
+ Requires-Dist: psutil>=5.9.0
32
+ Requires-Dist: pyyaml>=6.0
33
+ Provides-Extra: dev
34
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
35
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
36
+ Requires-Dist: black>=23.0.0; extra == "dev"
37
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
38
+ Dynamic: license-file
39
+
40
+ # CloneBox 📦
41
+
42
+ ```commandline
43
+ ╔═══════════════════════════════════════════════════════╗
44
+ ║ ____ _ ____ ║
45
+ ║ / ___|| | ___ _ __ ___| _ \ ___ __ __ ║
46
+ ║ | | | | / _ \ | '_ \ / _ \ |_) |/ _ \\ \/ / ║
47
+ ║ | |___ | || (_) || | | | __/ _ <| (_) |> < ║
48
+ ║ \____||_| \___/ |_| |_|\___|_| \_\\___//_/\_\ ║
49
+ ║ ║
50
+ ║ Clone your workstation to an isolated VM ║
51
+ ╚═══════════════════════════════════════════════════════╝
52
+ ```
53
+ **Clone your workstation environment to an isolated VM with selective apps, paths and services.**
54
+
55
+ CloneBox lets you create isolated virtual machines with only the applications, directories and services you need - using bind mounts instead of full disk cloning. Perfect for development, testing, or creating reproducible environments.
56
+
57
+ ## Features
58
+
59
+ - 🎯 **Selective cloning** - Choose exactly which paths, services and apps to include
60
+ - 🔍 **Auto-detection** - Automatically detects running services, applications, and project directories
61
+ - 🔗 **Bind mounts** - Share directories with the VM without copying data
62
+ - ☁️ **Cloud-init** - Automatic package installation and service setup
63
+ - 🖥️ **GUI support** - SPICE graphics with virt-viewer integration
64
+ - ⚡ **Fast creation** - No full disk cloning, VMs are ready in seconds
65
+
66
+ ## Installation
67
+
68
+ ### Quick Setup (Recommended)
69
+
70
+ Run the setup script to automatically install dependencies and configure the environment:
71
+
72
+ ```bash
73
+ # Clone the repository
74
+ git clone https://github.com/wronai/clonebox.git
75
+ cd clonebox
76
+
77
+ # Run the setup script
78
+ ./setup.sh
79
+ ```
80
+
81
+ The setup script will:
82
+ - Install all required packages (QEMU, libvirt, Python, etc.)
83
+ - Add your user to the necessary groups
84
+ - Configure libvirt networks
85
+ - Install clonebox in development mode
86
+
87
+ ### Manual Installation
88
+
89
+ #### Prerequisites
90
+
91
+ ```bash
92
+ # Install libvirt and QEMU/KVM
93
+ sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virt-manager virt-viewer
94
+
95
+ # Enable and start libvirtd
96
+ sudo systemctl enable --now libvirtd
97
+
98
+ # Add user to libvirt group
99
+ sudo usermod -aG libvirt $USER
100
+ newgrp libvirt
101
+
102
+ # Install genisoimage for cloud-init
103
+ sudo apt install genisoimage
104
+ ```
105
+
106
+ #### Install CloneBox
107
+
108
+ ```bash
109
+ # From source
110
+ git clone https://github.com/wronai/clonebox.git
111
+ cd clonebox
112
+ pip install -e .
113
+
114
+ # Or directly
115
+ pip install clonebox
116
+ ```
117
+ lub
118
+ ```bash
119
+ # Aktywuj venv
120
+ source .venv/bin/activate
121
+
122
+ # Interaktywny tryb (wizard)
123
+ clonebox
124
+
125
+ # Lub poszczególne komendy
126
+ clonebox detect # Pokaż wykryte usługi/apps/ścieżki
127
+ clonebox list # Lista VM
128
+ clonebox create --config ... # Utwórz VM z JSON config
129
+ clonebox start <name> # Uruchom VM
130
+ clonebox stop <name> # Zatrzymaj VM
131
+ clonebox delete <name> # Usuń VM
132
+ ```
133
+
134
+ ## Quick Start
135
+
136
+ ### Interactive Mode (Recommended)
137
+
138
+ Simply run `clonebox` to start the interactive wizard:
139
+
140
+ ```bash
141
+ clonebox
142
+ ```
143
+
144
+ The wizard will:
145
+ 1. Detect running services (Docker, PostgreSQL, nginx, etc.)
146
+ 2. Detect running applications and their working directories
147
+ 3. Detect project directories and config files
148
+ 4. Let you select what to include in the VM
149
+ 5. Create and optionally start the VM
150
+
151
+ ### Command Line
152
+
153
+ ```bash
154
+ # Create VM with specific config
155
+ clonebox create --name my-dev-vm --config '{
156
+ "paths": {
157
+ "/home/user/projects": "/mnt/projects",
158
+ "/home/user/.config": "/mnt/config"
159
+ },
160
+ "packages": ["python3", "nodejs", "docker.io"],
161
+ "services": ["docker"]
162
+ }' --ram 4096 --vcpus 4 --start
163
+
164
+ # List VMs
165
+ clonebox list
166
+
167
+ # Start/Stop VM
168
+ clonebox start my-dev-vm
169
+ clonebox stop my-dev-vm
170
+
171
+ # Delete VM
172
+ clonebox delete my-dev-vm
173
+
174
+ # Detect system state (useful for scripting)
175
+ clonebox detect --json
176
+ ```
177
+
178
+ ## Usage Examples
179
+
180
+ ### Python Development Environment
181
+
182
+ ```bash
183
+ clonebox create --name python-dev --config '{
184
+ "paths": {
185
+ "/home/user/my-python-project": "/workspace",
186
+ "/home/user/.pyenv": "/root/.pyenv"
187
+ },
188
+ "packages": ["python3", "python3-pip", "python3-venv", "build-essential"],
189
+ "services": []
190
+ }' --ram 2048 --start
191
+ ```
192
+
193
+ ### Docker Development
194
+
195
+ ```bash
196
+ clonebox create --name docker-dev --config '{
197
+ "paths": {
198
+ "/home/user/docker-projects": "/projects",
199
+ "/var/run/docker.sock": "/var/run/docker.sock"
200
+ },
201
+ "packages": ["docker.io", "docker-compose"],
202
+ "services": ["docker"]
203
+ }' --ram 4096 --start
204
+ ```
205
+
206
+ ### Full Stack (Node.js + PostgreSQL)
207
+
208
+ ```bash
209
+ clonebox create --name fullstack --config '{
210
+ "paths": {
211
+ "/home/user/my-app": "/app",
212
+ "/home/user/pgdata": "/var/lib/postgresql/data"
213
+ },
214
+ "packages": ["nodejs", "npm", "postgresql"],
215
+ "services": ["postgresql"]
216
+ }' --ram 4096 --vcpus 4 --start
217
+ ```
218
+
219
+ ## Inside the VM
220
+
221
+ After the VM boots, mount shared directories:
222
+
223
+ ```bash
224
+ # Mount shared paths (9p filesystem)
225
+ sudo mkdir -p /mnt/projects
226
+ sudo mount -t 9p -o trans=virtio,version=9p2000.L mount0 /mnt/projects
227
+
228
+ # Or add to /etc/fstab for permanent mount
229
+ echo "mount0 /mnt/projects 9p trans=virtio,version=9p2000.L 0 0" | sudo tee -a /etc/fstab
230
+ ```
231
+
232
+ ## Architecture
233
+
234
+ ```
235
+ ┌────────────────────────────────────────────────────────┐
236
+ │ HOST SYSTEM │
237
+ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
238
+ │ │ /home/user/ │ │ /var/www/ │ │ Docker │ │
239
+ │ │ projects/ │ │ html/ │ │ Socket │ │
240
+ │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
241
+ │ │ │ │ │
242
+ │ │ 9p/virtio │ │ │
243
+ │ │ bind mounts │ │ │
244
+ │ ┌──────▼─────────────────▼─────────────────▼───────┐ │
245
+ │ │ CloneBox VM │ │
246
+ │ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │
247
+ │ │ │ /mnt/proj │ │ /mnt/www │ │ /var/run/ │ │ │
248
+ │ │ │ │ │ │ │ docker.sock│ │ │
249
+ │ │ └────────────┘ └────────────┘ └────────────┘ │ │
250
+ │ │ │ │
251
+ │ │ cloud-init installed packages & services │ │
252
+ │ └──────────────────────────────────────────────────┘ │
253
+ └────────────────────────────────────────────────────────┘
254
+ ```
255
+
256
+ ## Quick Clone (Recommended)
257
+
258
+ The fastest way to clone your current working directory:
259
+
260
+ ```bash
261
+ # Clone current directory - generates .clonebox.yaml and asks to create VM
262
+ clonebox clone .
263
+
264
+ # Clone specific path
265
+ clonebox clone ~/projects/my-app
266
+
267
+ # Clone with custom name and auto-start
268
+ clonebox clone ~/projects/my-app --name my-dev-vm --run
269
+
270
+ # Clone and edit config before creating
271
+ clonebox clone . --edit
272
+ ```
273
+
274
+ Later, start the VM from any directory with `.clonebox.yaml`:
275
+
276
+ ```bash
277
+ # Start VM from config in current directory
278
+ clonebox start .
279
+
280
+ # Start VM from specific path
281
+ clonebox start ~/projects/my-app
282
+ ```
283
+
284
+ ### Export YAML Config
285
+
286
+ ```bash
287
+ # Export detected state as YAML (with deduplication)
288
+ clonebox detect --yaml --dedupe
289
+
290
+ # Save to file
291
+ clonebox detect --yaml --dedupe -o my-config.yaml
292
+ ```
293
+
294
+ ## Commands Reference
295
+
296
+ | Command | Description |
297
+ |---------|-------------|
298
+ | `clonebox` | Interactive VM creation wizard |
299
+ | `clonebox clone <path>` | Generate `.clonebox.yaml` from path + running processes |
300
+ | `clonebox clone . --run` | Clone and immediately start VM |
301
+ | `clonebox clone . --edit` | Clone, edit config, then create |
302
+ | `clonebox start .` | Start VM from `.clonebox.yaml` in current dir |
303
+ | `clonebox start <name>` | Start existing VM by name |
304
+ | `clonebox stop <name>` | Stop a VM (graceful shutdown) |
305
+ | `clonebox stop -f <name>` | Force stop a VM |
306
+ | `clonebox delete <name>` | Delete VM and storage |
307
+ | `clonebox list` | List all VMs |
308
+ | `clonebox detect` | Show detected services/apps/paths |
309
+ | `clonebox detect --yaml` | Output as YAML config |
310
+ | `clonebox detect --yaml --dedupe` | YAML with duplicates removed |
311
+ | `clonebox detect --json` | Output as JSON |
312
+
313
+ ## Requirements
314
+
315
+ - Linux with KVM support (`/dev/kvm`)
316
+ - libvirt daemon running
317
+ - Python 3.8+
318
+ - User in `libvirt` group
319
+
320
+ ## Troubleshooting
321
+
322
+ ### Network Issues
323
+
324
+ If you encounter "Network not found" or "network 'default' is not active" errors:
325
+
326
+ ```bash
327
+ # Run the network fix script
328
+ ./fix-network.sh
329
+
330
+ # Or manually fix:
331
+ virsh --connect qemu:///session net-destroy default 2>/dev/null
332
+ virsh --connect qemu:///session net-undefine default 2>/dev/null
333
+ virsh --connect qemu:///session net-define /tmp/default-network.xml
334
+ virsh --connect qemu:///session net-start default
335
+ ```
336
+
337
+ ### Permission Issues
338
+
339
+ If you get permission errors:
340
+
341
+ ```bash
342
+ # Ensure user is in libvirt and kvm groups
343
+ sudo usermod -aG libvirt $USER
344
+ sudo usermod -aG kvm $USER
345
+
346
+ # Log out and log back in for groups to take effect
347
+ ```
348
+
349
+ ### VM Already Exists
350
+
351
+ If you get "domain already exists" error:
352
+
353
+ ```bash
354
+ # List VMs
355
+ clonebox list
356
+
357
+ # Stop and delete the existing VM
358
+ clonebox delete <vm-name>
359
+
360
+ # Or use virsh directly
361
+ virsh --connect qemu:///session destroy <vm-name>
362
+ virsh --connect qemu:///session undefine <vm-name>
363
+ ```
364
+
365
+ ### virt-viewer not found
366
+
367
+ If GUI doesn't open:
368
+
369
+ ```bash
370
+ # Install virt-viewer
371
+ sudo apt install virt-viewer
372
+
373
+ # Then connect manually
374
+ virt-viewer --connect qemu:///session <vm-name>
375
+ ```
376
+
377
+ ## License
378
+
379
+ MIT License - see [LICENSE](LICENSE) file.
@@ -0,0 +1,10 @@
1
+ clonebox/__init__.py,sha256=IOk7G0DiSQ33EGbFC0xbnnFB9aou_6yuyFxvycQEvA0,407
2
+ clonebox/cli.py,sha256=tg_tinIH3D6Q1xAjhXu7P4msl2XcxLo8XUHMDxkOFis,31996
3
+ clonebox/cloner.py,sha256=bB37BFYY7_xlfOSdk05zrUsrw7ewItRBMb7EJkYFA_0,19671
4
+ clonebox/detector.py,sha256=Umg4CRJU61yV3a1AvR_0tOfjBMCCIbiQdDAAhlrOL5k,11916
5
+ clonebox-0.1.3.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
6
+ clonebox-0.1.3.dist-info/METADATA,sha256=W6d_Km3nbulNWpl5Z6KctOHciT1o14o4OnAELJMAfbc,11996
7
+ clonebox-0.1.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
8
+ clonebox-0.1.3.dist-info/entry_points.txt,sha256=FES95Vi3btfViLEEoHdb8nikNxTqzaooi9ehZw9ZfWI,47
9
+ clonebox-0.1.3.dist-info/top_level.txt,sha256=LdMo2cvCrEcRGH2M8JgQNVsCoszLV0xug6kx1JnaRjo,9
10
+ clonebox-0.1.3.dist-info/RECORD,,
@@ -1,40 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: clonebox
3
- Version: 0.1.1
4
- Summary: Clone your workstation environment to an isolated VM with selective apps, paths and services
5
- Author: CloneBox Team
6
- License: MIT
7
- Project-URL: Homepage, https://github.com/wronai/clonebox
8
- Project-URL: Repository, https://github.com/wronai/clonebox
9
- Project-URL: Issues, https://github.com/wronai/clonebox/issues
10
- Keywords: vm,virtualization,libvirt,clone,workstation,qemu,kvm
11
- Classifier: Development Status :: 4 - Beta
12
- Classifier: Environment :: Console
13
- Classifier: Intended Audience :: Developers
14
- Classifier: Intended Audience :: System Administrators
15
- Classifier: License :: OSI Approved :: MIT License
16
- Classifier: Operating System :: POSIX :: Linux
17
- Classifier: Programming Language :: Python :: 3
18
- Classifier: Programming Language :: Python :: 3.8
19
- Classifier: Programming Language :: Python :: 3.9
20
- Classifier: Programming Language :: Python :: 3.10
21
- Classifier: Programming Language :: Python :: 3.11
22
- Classifier: Programming Language :: Python :: 3.12
23
- Classifier: Topic :: System :: Systems Administration
24
- Classifier: Topic :: Utilities
25
- Requires-Python: >=3.8
26
- Description-Content-Type: text/markdown
27
- License-File: LICENSE
28
- Requires-Dist: libvirt-python>=9.0.0
29
- Requires-Dist: rich>=13.0.0
30
- Requires-Dist: questionary>=2.0.0
31
- Requires-Dist: psutil>=5.9.0
32
- Requires-Dist: pyyaml>=6.0
33
- Provides-Extra: dev
34
- Requires-Dist: pytest>=7.0.0; extra == "dev"
35
- Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
36
- Requires-Dist: black>=23.0.0; extra == "dev"
37
- Requires-Dist: ruff>=0.1.0; extra == "dev"
38
- Dynamic: license-file
39
-
40
- # clonebox
@@ -1,9 +0,0 @@
1
- clonebox/__init__.py,sha256=IOk7G0DiSQ33EGbFC0xbnnFB9aou_6yuyFxvycQEvA0,407
2
- clonebox/cloner.py,sha256=SamhrCJoJ-k_u4b-yvpNCmr_IHpSrVjlo826lq4fD2M,14523
3
- clonebox/detector.py,sha256=dwtMg2FybGR79c3xce5PXNfrQgMpH4HK-nEsNfucPms,11835
4
- clonebox-0.1.1.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
5
- clonebox-0.1.1.dist-info/METADATA,sha256=NQWcmpWvadnOr-UC3Ge3yYMD5vo7ClIcYUFiAXagxuA,1570
6
- clonebox-0.1.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
7
- clonebox-0.1.1.dist-info/entry_points.txt,sha256=FES95Vi3btfViLEEoHdb8nikNxTqzaooi9ehZw9ZfWI,47
8
- clonebox-0.1.1.dist-info/top_level.txt,sha256=LdMo2cvCrEcRGH2M8JgQNVsCoszLV0xug6kx1JnaRjo,9
9
- clonebox-0.1.1.dist-info/RECORD,,