clonebox 0.1.17__tar.gz → 0.1.18__tar.gz
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-0.1.17/src/clonebox.egg-info → clonebox-0.1.18}/PKG-INFO +1 -1
- {clonebox-0.1.17 → clonebox-0.1.18}/pyproject.toml +1 -1
- {clonebox-0.1.17 → clonebox-0.1.18}/src/clonebox/cli.py +71 -74
- {clonebox-0.1.17 → clonebox-0.1.18/src/clonebox.egg-info}/PKG-INFO +1 -1
- {clonebox-0.1.17 → clonebox-0.1.18}/LICENSE +0 -0
- {clonebox-0.1.17 → clonebox-0.1.18}/README.md +0 -0
- {clonebox-0.1.17 → clonebox-0.1.18}/setup.cfg +0 -0
- {clonebox-0.1.17 → clonebox-0.1.18}/src/clonebox/__init__.py +0 -0
- {clonebox-0.1.17 → clonebox-0.1.18}/src/clonebox/__main__.py +0 -0
- {clonebox-0.1.17 → clonebox-0.1.18}/src/clonebox/cloner.py +0 -0
- {clonebox-0.1.17 → clonebox-0.1.18}/src/clonebox/container.py +0 -0
- {clonebox-0.1.17 → clonebox-0.1.18}/src/clonebox/detector.py +0 -0
- {clonebox-0.1.17 → clonebox-0.1.18}/src/clonebox/models.py +0 -0
- {clonebox-0.1.17 → clonebox-0.1.18}/src/clonebox/validator.py +0 -0
- {clonebox-0.1.17 → clonebox-0.1.18}/src/clonebox.egg-info/SOURCES.txt +0 -0
- {clonebox-0.1.17 → clonebox-0.1.18}/src/clonebox.egg-info/dependency_links.txt +0 -0
- {clonebox-0.1.17 → clonebox-0.1.18}/src/clonebox.egg-info/entry_points.txt +0 -0
- {clonebox-0.1.17 → clonebox-0.1.18}/src/clonebox.egg-info/requires.txt +0 -0
- {clonebox-0.1.17 → clonebox-0.1.18}/src/clonebox.egg-info/top_level.txt +0 -0
- {clonebox-0.1.17 → clonebox-0.1.18}/tests/test_cli.py +0 -0
- {clonebox-0.1.17 → clonebox-0.1.18}/tests/test_cloner.py +0 -0
- {clonebox-0.1.17 → clonebox-0.1.18}/tests/test_detector.py +0 -0
- {clonebox-0.1.17 → clonebox-0.1.18}/tests/test_models.py +0 -0
- {clonebox-0.1.17 → clonebox-0.1.18}/tests/test_network.py +0 -0
- {clonebox-0.1.17 → clonebox-0.1.18}/tests/test_validator.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "clonebox"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.18"
|
|
8
8
|
description = "Clone your workstation environment to an isolated VM with selective apps, paths and services"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "Apache-2.0"}
|
|
@@ -80,98 +80,95 @@ def _resolve_vm_name_and_config_file(name: Optional[str]) -> tuple[str, Optional
|
|
|
80
80
|
|
|
81
81
|
|
|
82
82
|
def _qga_ping(vm_name: str, conn_uri: str) -> bool:
|
|
83
|
-
|
|
84
|
-
try:
|
|
85
|
-
result = subprocess.run(
|
|
86
|
-
[
|
|
87
|
-
"virsh",
|
|
88
|
-
"--connect",
|
|
89
|
-
conn_uri,
|
|
90
|
-
"qemu-agent-command",
|
|
91
|
-
vm_name,
|
|
92
|
-
json.dumps({"execute": "guest-ping"}),
|
|
93
|
-
],
|
|
94
|
-
capture_output=True,
|
|
95
|
-
text=True,
|
|
96
|
-
timeout=5,
|
|
97
|
-
)
|
|
98
|
-
return result.returncode == 0
|
|
99
|
-
except Exception:
|
|
100
|
-
return False
|
|
83
|
+
import subprocess
|
|
101
84
|
|
|
102
|
-
|
|
85
|
+
try:
|
|
86
|
+
result = subprocess.run(
|
|
87
|
+
[
|
|
88
|
+
"virsh",
|
|
89
|
+
"--connect",
|
|
90
|
+
conn_uri,
|
|
91
|
+
"qemu-agent-command",
|
|
92
|
+
vm_name,
|
|
93
|
+
json.dumps({"execute": "guest-ping"}),
|
|
94
|
+
],
|
|
95
|
+
capture_output=True,
|
|
96
|
+
text=True,
|
|
97
|
+
timeout=5,
|
|
98
|
+
)
|
|
99
|
+
return result.returncode == 0
|
|
100
|
+
except Exception:
|
|
101
|
+
return False
|
|
103
102
|
|
|
104
103
|
|
|
105
104
|
def _qga_exec(vm_name: str, conn_uri: str, command: str, timeout: int = 10) -> Optional[str]:
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
105
|
+
import subprocess
|
|
106
|
+
import base64
|
|
107
|
+
import time
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
payload = {
|
|
111
|
+
"execute": "guest-exec",
|
|
112
|
+
"arguments": {
|
|
113
|
+
"path": "/bin/sh",
|
|
114
|
+
"arg": ["-c", command],
|
|
115
|
+
"capture-output": True,
|
|
116
|
+
},
|
|
117
|
+
}
|
|
118
|
+
exec_result = subprocess.run(
|
|
119
|
+
[
|
|
120
|
+
"virsh",
|
|
121
|
+
"--connect",
|
|
122
|
+
conn_uri,
|
|
123
|
+
"qemu-agent-command",
|
|
124
|
+
vm_name,
|
|
125
|
+
json.dumps(payload),
|
|
126
|
+
],
|
|
127
|
+
capture_output=True,
|
|
128
|
+
text=True,
|
|
129
|
+
timeout=timeout,
|
|
130
|
+
)
|
|
131
|
+
if exec_result.returncode != 0:
|
|
132
|
+
return None
|
|
133
|
+
|
|
134
|
+
resp = json.loads(exec_result.stdout)
|
|
135
|
+
pid = resp.get("return", {}).get("pid")
|
|
136
|
+
if not pid:
|
|
137
|
+
return None
|
|
138
|
+
|
|
139
|
+
deadline = time.time() + timeout
|
|
140
|
+
while time.time() < deadline:
|
|
141
|
+
status_payload = {"execute": "guest-exec-status", "arguments": {"pid": pid}}
|
|
142
|
+
status_result = subprocess.run(
|
|
117
143
|
[
|
|
118
144
|
"virsh",
|
|
119
145
|
"--connect",
|
|
120
146
|
conn_uri,
|
|
121
147
|
"qemu-agent-command",
|
|
122
148
|
vm_name,
|
|
123
|
-
json.dumps(
|
|
149
|
+
json.dumps(status_payload),
|
|
124
150
|
],
|
|
125
151
|
capture_output=True,
|
|
126
152
|
text=True,
|
|
127
|
-
timeout=
|
|
153
|
+
timeout=5,
|
|
128
154
|
)
|
|
129
|
-
if
|
|
130
|
-
return None
|
|
131
|
-
|
|
132
|
-
resp = json.loads(exec_result.stdout)
|
|
133
|
-
pid = resp.get("return", {}).get("pid")
|
|
134
|
-
if not pid:
|
|
155
|
+
if status_result.returncode != 0:
|
|
135
156
|
return None
|
|
136
157
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
status_payload = {"execute": "guest-exec-status", "arguments": {"pid": pid}}
|
|
143
|
-
status_result = subprocess.run(
|
|
144
|
-
[
|
|
145
|
-
"virsh",
|
|
146
|
-
"--connect",
|
|
147
|
-
conn_uri,
|
|
148
|
-
"qemu-agent-command",
|
|
149
|
-
vm_name,
|
|
150
|
-
json.dumps(status_payload),
|
|
151
|
-
],
|
|
152
|
-
capture_output=True,
|
|
153
|
-
text=True,
|
|
154
|
-
timeout=5,
|
|
155
|
-
)
|
|
156
|
-
if status_result.returncode != 0:
|
|
157
|
-
return None
|
|
158
|
-
|
|
159
|
-
status_resp = json.loads(status_result.stdout)
|
|
160
|
-
ret = status_resp.get("return", {})
|
|
161
|
-
if not ret.get("exited", False):
|
|
162
|
-
time.sleep(0.3)
|
|
163
|
-
continue
|
|
164
|
-
|
|
165
|
-
out_data = ret.get("out-data")
|
|
166
|
-
if out_data:
|
|
167
|
-
return base64.b64decode(out_data).decode().strip()
|
|
168
|
-
return ""
|
|
158
|
+
status_resp = json.loads(status_result.stdout)
|
|
159
|
+
ret = status_resp.get("return", {})
|
|
160
|
+
if not ret.get("exited", False):
|
|
161
|
+
time.sleep(0.3)
|
|
162
|
+
continue
|
|
169
163
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
164
|
+
out_data = ret.get("out-data")
|
|
165
|
+
if out_data:
|
|
166
|
+
return base64.b64decode(out_data).decode().strip()
|
|
167
|
+
return ""
|
|
173
168
|
|
|
174
|
-
|
|
169
|
+
return None
|
|
170
|
+
except Exception:
|
|
171
|
+
return None
|
|
175
172
|
|
|
176
173
|
|
|
177
174
|
def run_vm_diagnostics(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|