cyclo-manager 0.2.0.dev1__tar.gz → 0.2.0.dev2__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.
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/PKG-INFO +1 -1
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/cyclo_host_agent/routers/repos.py +14 -13
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/cyclo_host_agent/routers/update.py +18 -56
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/cyclo_manager.egg-info/PKG-INFO +1 -1
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/cyclo_manager_cli/cli.py +15 -1
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/pyproject.toml +1 -1
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/setup.cfg +1 -1
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/README.md +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/cyclo_host_agent/__init__.py +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/cyclo_host_agent/main.py +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/cyclo_host_agent/models.py +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/cyclo_host_agent/routers/__init__.py +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/cyclo_manager.egg-info/SOURCES.txt +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/cyclo_manager.egg-info/dependency_links.txt +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/cyclo_manager.egg-info/entry_points.txt +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/cyclo_manager.egg-info/requires.txt +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/cyclo_manager.egg-info/top_level.txt +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/cyclo_manager_cli/__init__.py +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/cyclo_manager_cli/config/config.yml +0 -0
- {cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/cyclo_manager_cli/docker/docker-compose.yml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cyclo-manager
|
|
3
|
-
Version: 0.2.0.
|
|
3
|
+
Version: 0.2.0.dev2
|
|
4
4
|
Summary: cyclo_manager CLI: pip-installable launcher for cyclo_manager server and UI containers. Run 'cyclo_manager up' to start Docker stack.
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -283,24 +283,25 @@ async def _update_reset(repo_path: Path, preserve_files: list[str]) -> UpdateRes
|
|
|
283
283
|
|
|
284
284
|
# ── container helper ───────────────────────────────────────────────────────────
|
|
285
285
|
|
|
286
|
-
|
|
286
|
+
def _run_container_sh_sync(repo_path: Path, action: str) -> tuple[bool, str]:
|
|
287
287
|
script = repo_path / 'docker' / 'container.sh'
|
|
288
288
|
if not script.exists():
|
|
289
289
|
return False, f'container.sh not found at {script}'
|
|
290
|
-
proc = await asyncio.create_subprocess_exec(
|
|
291
|
-
'bash', str(script), action,
|
|
292
|
-
cwd=str(repo_path / 'docker'),
|
|
293
|
-
stdin=asyncio.subprocess.PIPE,
|
|
294
|
-
stdout=asyncio.subprocess.PIPE,
|
|
295
|
-
stderr=asyncio.subprocess.PIPE,
|
|
296
|
-
)
|
|
297
290
|
try:
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
291
|
+
result = subprocess.run(
|
|
292
|
+
['bash', str(script), action],
|
|
293
|
+
cwd=str(repo_path / 'docker'),
|
|
294
|
+
input=b'y\n',
|
|
295
|
+
capture_output=True,
|
|
296
|
+
timeout=300.0,
|
|
297
|
+
)
|
|
298
|
+
return result.returncode == 0, (result.stdout.decode() + result.stderr.decode()).strip()
|
|
299
|
+
except subprocess.TimeoutExpired:
|
|
302
300
|
return False, 'Timeout waiting for container.sh'
|
|
303
|
-
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
async def _run_container_sh(repo_path: Path, action: str) -> tuple[bool, str]:
|
|
304
|
+
return await asyncio.to_thread(_run_container_sh_sync, repo_path, action)
|
|
304
305
|
|
|
305
306
|
|
|
306
307
|
# ── endpoints ──────────────────────────────────────────────────────────────────
|
|
@@ -42,16 +42,15 @@ def _fmt(cmd: str, out: str) -> str:
|
|
|
42
42
|
return f'$ {cmd}\n{out.strip()}' if out.strip() else f'$ {cmd}'
|
|
43
43
|
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
time.sleep(2)
|
|
45
|
+
|
|
46
|
+
def _run_cmd(args: list[str], timeout: float) -> tuple[int, str]:
|
|
48
47
|
try:
|
|
49
|
-
subprocess.run(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
result = subprocess.run(args, capture_output=True, timeout=timeout)
|
|
49
|
+
return result.returncode, (result.stdout.decode() + result.stderr.decode()).strip()
|
|
50
|
+
except subprocess.TimeoutExpired:
|
|
51
|
+
return 1, 'timed out'
|
|
53
52
|
except Exception as e:
|
|
54
|
-
|
|
53
|
+
return 1, str(e)
|
|
55
54
|
|
|
56
55
|
|
|
57
56
|
async def _run_install_and_up(cyclo_exe: str, pip_exe: str) -> None:
|
|
@@ -60,50 +59,24 @@ async def _run_install_and_up(cyclo_exe: str, pip_exe: str) -> None:
|
|
|
60
59
|
|
|
61
60
|
# pip install -U
|
|
62
61
|
_update_status['phase'] = 'installing'
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
stdout=asyncio.subprocess.PIPE,
|
|
67
|
-
stderr=asyncio.subprocess.PIPE,
|
|
68
|
-
)
|
|
69
|
-
stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=120)
|
|
70
|
-
out = (stdout.decode() + stderr.decode()).strip()
|
|
71
|
-
_update_status['install_output'] = _fmt(f'pip install -U {PYPI_PACKAGE}', out)
|
|
72
|
-
if proc.returncode != 0:
|
|
73
|
-
_update_status['phase'] = 'error'
|
|
74
|
-
_update_status['error'] = f'pip install failed (exit {proc.returncode})'
|
|
75
|
-
return
|
|
76
|
-
except asyncio.TimeoutError:
|
|
62
|
+
rc, out = await asyncio.to_thread(_run_cmd, [pip_exe, 'install', '-U', PYPI_PACKAGE], 120)
|
|
63
|
+
_update_status['install_output'] = _fmt(f'pip install -U {PYPI_PACKAGE}', out)
|
|
64
|
+
if rc != 0:
|
|
77
65
|
_update_status['phase'] = 'error'
|
|
78
|
-
_update_status['error'] = 'pip install
|
|
66
|
+
_update_status['error'] = f'pip install failed (exit {rc})'
|
|
79
67
|
return
|
|
80
68
|
|
|
81
69
|
# cyclo up
|
|
82
70
|
_update_status['phase'] = 'starting'
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
stdout=asyncio.subprocess.PIPE,
|
|
87
|
-
stderr=asyncio.subprocess.PIPE,
|
|
88
|
-
)
|
|
89
|
-
stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=300)
|
|
90
|
-
out = (stdout.decode() + stderr.decode()).strip()
|
|
91
|
-
_update_status['up_output'] = _fmt('cyclo_manager up', out)
|
|
92
|
-
if proc.returncode != 0:
|
|
93
|
-
_update_status['phase'] = 'error'
|
|
94
|
-
_update_status['error'] = f'cyclo_manager up failed (exit {proc.returncode})'
|
|
95
|
-
return
|
|
96
|
-
except asyncio.TimeoutError:
|
|
71
|
+
rc, out = await asyncio.to_thread(_run_cmd, [cyclo_exe, 'up'], 300)
|
|
72
|
+
_update_status['up_output'] = _fmt('cyclo_manager up', out)
|
|
73
|
+
if rc != 0:
|
|
97
74
|
_update_status['phase'] = 'error'
|
|
98
|
-
_update_status['error'] = 'cyclo_manager up
|
|
75
|
+
_update_status['error'] = f'cyclo_manager up failed (exit {rc})'
|
|
99
76
|
return
|
|
100
77
|
|
|
101
78
|
_update_status['phase'] = 'done'
|
|
102
79
|
|
|
103
|
-
# Restart self so new binary takes effect
|
|
104
|
-
loop = asyncio.get_event_loop()
|
|
105
|
-
await loop.run_in_executor(None, _restart_self)
|
|
106
|
-
|
|
107
80
|
|
|
108
81
|
@router.post('/update')
|
|
109
82
|
async def start_update() -> dict:
|
|
@@ -127,20 +100,9 @@ async def start_update() -> dict:
|
|
|
127
100
|
|
|
128
101
|
_update_status = {'phase': 'stopping', 'install_output': '', 'up_output': '', 'error': ''}
|
|
129
102
|
|
|
130
|
-
# cyclo down
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
proc = await asyncio.create_subprocess_exec(
|
|
134
|
-
cyclo_exe, 'down',
|
|
135
|
-
stdout=asyncio.subprocess.PIPE,
|
|
136
|
-
stderr=asyncio.subprocess.PIPE,
|
|
137
|
-
)
|
|
138
|
-
stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=30)
|
|
139
|
-
down_output = _fmt('cyclo_manager down', (stdout.decode() + stderr.decode()))
|
|
140
|
-
except asyncio.TimeoutError:
|
|
141
|
-
down_output = '$ cyclo_manager down\n(timed out)'
|
|
142
|
-
except Exception as e:
|
|
143
|
-
down_output = f'$ cyclo_manager down\n(error: {e})'
|
|
103
|
+
# cyclo down
|
|
104
|
+
rc, out = await asyncio.to_thread(_run_cmd, [cyclo_exe, 'down'], 30)
|
|
105
|
+
down_output = _fmt('cyclo_manager down', out)
|
|
144
106
|
|
|
145
107
|
# Continue install + up in background
|
|
146
108
|
asyncio.create_task(_run_install_and_up(cyclo_exe, pip_exe))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cyclo-manager
|
|
3
|
-
Version: 0.2.0.
|
|
3
|
+
Version: 0.2.0.dev2
|
|
4
4
|
Summary: cyclo_manager CLI: pip-installable launcher for cyclo_manager server and UI containers. Run 'cyclo_manager up' to start Docker stack.
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -123,7 +123,12 @@ WantedBy=multi-user.target
|
|
|
123
123
|
|
|
124
124
|
def cmd_up(args: argparse.Namespace) -> int:
|
|
125
125
|
"""Start API + UI; create zenoh and noVNC containers without starting them."""
|
|
126
|
-
if
|
|
126
|
+
if _check_host_agent():
|
|
127
|
+
try:
|
|
128
|
+
subprocess.run(['sudo', 'systemctl', 'restart', f'{HOST_AGENT_SERVICE}.service'], check=True)
|
|
129
|
+
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
130
|
+
print('Warning: Failed to restart host agent service.', file=sys.stderr)
|
|
131
|
+
else:
|
|
127
132
|
if _create_host_agent() != 0:
|
|
128
133
|
print('Warning: Failed to install host agent service.')
|
|
129
134
|
|
|
@@ -232,6 +237,15 @@ def cmd_update(args: argparse.Namespace) -> int:
|
|
|
232
237
|
except subprocess.CalledProcessError as e:
|
|
233
238
|
return e.returncode
|
|
234
239
|
|
|
240
|
+
print('Restarting host agent...')
|
|
241
|
+
try:
|
|
242
|
+
subprocess.run(
|
|
243
|
+
['sudo', 'systemctl', 'restart', f'{HOST_AGENT_SERVICE}.service'],
|
|
244
|
+
check=True,
|
|
245
|
+
)
|
|
246
|
+
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
247
|
+
print('Warning: Failed to restart host agent service.', file=sys.stderr)
|
|
248
|
+
|
|
235
249
|
print('cyclo_manager update completed.')
|
|
236
250
|
return 0
|
|
237
251
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "cyclo-manager"
|
|
7
|
-
version = "0.2.0.
|
|
7
|
+
version = "0.2.0.dev2"
|
|
8
8
|
description = "cyclo_manager CLI: pip-installable launcher for cyclo_manager server and UI containers. Run 'cyclo_manager up' to start Docker stack."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/cyclo_manager.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/cyclo_manager.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cyclo_manager-0.2.0.dev1 → cyclo_manager-0.2.0.dev2}/cyclo_manager_cli/docker/docker-compose.yml
RENAMED
|
File without changes
|