cyclo-manager 0.2.0.dev8__tar.gz → 0.2.0.dev10__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.dev8 → cyclo_manager-0.2.0.dev10}/PKG-INFO +1 -1
- {cyclo_manager-0.2.0.dev8 → cyclo_manager-0.2.0.dev10}/cyclo_host_agent/routers/update.py +2 -2
- {cyclo_manager-0.2.0.dev8 → cyclo_manager-0.2.0.dev10}/cyclo_manager.egg-info/PKG-INFO +1 -1
- {cyclo_manager-0.2.0.dev8 → cyclo_manager-0.2.0.dev10}/cyclo_manager_cli/cli.py +42 -9
- {cyclo_manager-0.2.0.dev8 → cyclo_manager-0.2.0.dev10}/pyproject.toml +1 -1
- {cyclo_manager-0.2.0.dev8 → cyclo_manager-0.2.0.dev10}/README.md +0 -0
- {cyclo_manager-0.2.0.dev8 → cyclo_manager-0.2.0.dev10}/cyclo_host_agent/__init__.py +0 -0
- {cyclo_manager-0.2.0.dev8 → cyclo_manager-0.2.0.dev10}/cyclo_host_agent/main.py +0 -0
- {cyclo_manager-0.2.0.dev8 → cyclo_manager-0.2.0.dev10}/cyclo_host_agent/models.py +0 -0
- {cyclo_manager-0.2.0.dev8 → cyclo_manager-0.2.0.dev10}/cyclo_host_agent/routers/__init__.py +0 -0
- {cyclo_manager-0.2.0.dev8 → cyclo_manager-0.2.0.dev10}/cyclo_host_agent/routers/repos.py +0 -0
- {cyclo_manager-0.2.0.dev8 → cyclo_manager-0.2.0.dev10}/cyclo_manager.egg-info/SOURCES.txt +0 -0
- {cyclo_manager-0.2.0.dev8 → cyclo_manager-0.2.0.dev10}/cyclo_manager.egg-info/dependency_links.txt +0 -0
- {cyclo_manager-0.2.0.dev8 → cyclo_manager-0.2.0.dev10}/cyclo_manager.egg-info/entry_points.txt +0 -0
- {cyclo_manager-0.2.0.dev8 → cyclo_manager-0.2.0.dev10}/cyclo_manager.egg-info/requires.txt +0 -0
- {cyclo_manager-0.2.0.dev8 → cyclo_manager-0.2.0.dev10}/cyclo_manager.egg-info/top_level.txt +0 -0
- {cyclo_manager-0.2.0.dev8 → cyclo_manager-0.2.0.dev10}/cyclo_manager_cli/__init__.py +0 -0
- {cyclo_manager-0.2.0.dev8 → cyclo_manager-0.2.0.dev10}/cyclo_manager_cli/config/config.yml +0 -0
- {cyclo_manager-0.2.0.dev8 → cyclo_manager-0.2.0.dev10}/cyclo_manager_cli/docker/docker-compose.yml +0 -0
- {cyclo_manager-0.2.0.dev8 → cyclo_manager-0.2.0.dev10}/setup.cfg +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.dev10
|
|
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
|
|
@@ -84,7 +84,7 @@ def _delayed_exec(cmd: list[str], delay: float = 2.0) -> None:
|
|
|
84
84
|
async def reboot_host() -> dict:
|
|
85
85
|
"""Reboot the host machine after returning a response."""
|
|
86
86
|
loop = asyncio.get_event_loop()
|
|
87
|
-
loop.run_in_executor(None, _delayed_exec, ['sudo', 'reboot'])
|
|
87
|
+
loop.run_in_executor(None, _delayed_exec, ['sudo', '/usr/sbin/reboot'])
|
|
88
88
|
return {'status': 'rebooting'}
|
|
89
89
|
|
|
90
90
|
|
|
@@ -92,5 +92,5 @@ async def reboot_host() -> dict:
|
|
|
92
92
|
async def shutdown_host() -> dict:
|
|
93
93
|
"""Shut down the host machine after returning a response."""
|
|
94
94
|
loop = asyncio.get_event_loop()
|
|
95
|
-
loop.run_in_executor(None, _delayed_exec, ['sudo', 'poweroff'])
|
|
95
|
+
loop.run_in_executor(None, _delayed_exec, ['sudo', '/usr/sbin/poweroff'])
|
|
96
96
|
return {'status': 'shutting_down'}
|
|
@@ -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.dev10
|
|
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
|
|
@@ -27,6 +27,7 @@ import argparse
|
|
|
27
27
|
import os
|
|
28
28
|
from pathlib import Path
|
|
29
29
|
import shutil
|
|
30
|
+
import socket
|
|
30
31
|
import subprocess
|
|
31
32
|
import sys
|
|
32
33
|
|
|
@@ -81,17 +82,20 @@ def _setup_socket_dir(user: str) -> bool:
|
|
|
81
82
|
Only host/ is chowned so other agent sockets under agent_sockets/ are untouched.
|
|
82
83
|
Removes a stale socket file (e.g. left by a previous root-owned service).
|
|
83
84
|
"""
|
|
85
|
+
print(f' [1/3] Creating socket directory {HOST_AGENT_SOCKET_DIR}...')
|
|
84
86
|
try:
|
|
85
87
|
subprocess.run(
|
|
86
88
|
['sudo', 'mkdir', '-p', HOST_AGENT_SOCKET_DIR],
|
|
87
89
|
check=True,
|
|
88
90
|
capture_output=True,
|
|
89
91
|
)
|
|
92
|
+
print(f' [2/3] Setting ownership to {user}:{user}...')
|
|
90
93
|
subprocess.run(
|
|
91
94
|
['sudo', 'chown', f'{user}:{user}', HOST_AGENT_SOCKET_DIR],
|
|
92
95
|
check=True,
|
|
93
96
|
capture_output=True,
|
|
94
97
|
)
|
|
98
|
+
print(f' [3/3] Removing stale socket file (if any)...')
|
|
95
99
|
subprocess.run(
|
|
96
100
|
['sudo', 'rm', '-f', HOST_AGENT_SOCKET],
|
|
97
101
|
check=True,
|
|
@@ -108,10 +112,13 @@ def _install_sudoers(user: str) -> bool:
|
|
|
108
112
|
Write /etc/sudoers.d/cyclo_manager granting NOPASSWD for udev operations
|
|
109
113
|
needed by container.sh (cp to /etc/udev/rules.d/, udevadm control/trigger).
|
|
110
114
|
"""
|
|
115
|
+
print(' Installing sudoers rules (cp, udevadm, reboot, poweroff)...')
|
|
111
116
|
sudoers_content = (
|
|
112
117
|
f'{user} ALL=(ALL) NOPASSWD: /usr/bin/cp, '
|
|
113
118
|
f'/usr/bin/udevadm control --reload-rules, '
|
|
114
|
-
f'/usr/bin/udevadm trigger
|
|
119
|
+
f'/usr/bin/udevadm trigger, '
|
|
120
|
+
f'/usr/sbin/reboot, '
|
|
121
|
+
f'/usr/sbin/poweroff\n'
|
|
115
122
|
)
|
|
116
123
|
sudoers_file = '/etc/sudoers.d/cyclo_manager'
|
|
117
124
|
try:
|
|
@@ -179,18 +186,30 @@ WantedBy=multi-user.target
|
|
|
179
186
|
|
|
180
187
|
service_file = f'/etc/systemd/system/{HOST_AGENT_SERVICE}.service'
|
|
181
188
|
|
|
182
|
-
print(f'
|
|
189
|
+
print(f'Setting up {HOST_AGENT_SERVICE} systemd service (user={user})...')
|
|
183
190
|
try:
|
|
191
|
+
print(f' Writing unit file to {service_file}...')
|
|
184
192
|
subprocess.run(
|
|
185
193
|
['sudo', 'tee', service_file],
|
|
186
194
|
input=service_content.encode(),
|
|
187
195
|
capture_output=True,
|
|
188
196
|
check=True,
|
|
189
197
|
)
|
|
190
|
-
|
|
191
|
-
subprocess.run(['sudo', 'systemctl', '
|
|
192
|
-
|
|
193
|
-
|
|
198
|
+
print(' Running systemctl daemon-reload...')
|
|
199
|
+
subprocess.run(['sudo', 'systemctl', 'daemon-reload'], check=True, capture_output=True)
|
|
200
|
+
print(f' Enabling {HOST_AGENT_SERVICE}...')
|
|
201
|
+
subprocess.run(
|
|
202
|
+
['sudo', 'systemctl', 'enable', f'{HOST_AGENT_SERVICE}.service'],
|
|
203
|
+
check=True,
|
|
204
|
+
capture_output=True,
|
|
205
|
+
)
|
|
206
|
+
print(f' Starting {HOST_AGENT_SERVICE}...')
|
|
207
|
+
subprocess.run(
|
|
208
|
+
['sudo', 'systemctl', 'restart', f'{HOST_AGENT_SERVICE}.service'],
|
|
209
|
+
check=True,
|
|
210
|
+
capture_output=True,
|
|
211
|
+
)
|
|
212
|
+
print(f' {HOST_AGENT_SERVICE} is running.')
|
|
194
213
|
return 0
|
|
195
214
|
except subprocess.CalledProcessError as e:
|
|
196
215
|
print(f'Failed to install host agent service: {e}', file=sys.stderr)
|
|
@@ -202,6 +221,9 @@ WantedBy=multi-user.target
|
|
|
202
221
|
|
|
203
222
|
def cmd_up(args: argparse.Namespace) -> int:
|
|
204
223
|
"""Start API + UI; create zenoh and noVNC containers without starting them."""
|
|
224
|
+
print('--- cyclo_manager up ---')
|
|
225
|
+
|
|
226
|
+
print('[1/3] Setting up host agent...')
|
|
205
227
|
if _ensure_host_agent() != 0:
|
|
206
228
|
print('Warning: Failed to install host agent service.', file=sys.stderr)
|
|
207
229
|
|
|
@@ -215,11 +237,15 @@ def cmd_up(args: argparse.Namespace) -> int:
|
|
|
215
237
|
return 1
|
|
216
238
|
env = os.environ.copy()
|
|
217
239
|
env['CYCLO_MANAGER_CONFIG_FILE'] = str(config_path)
|
|
240
|
+
env.setdefault('HOSTNAME', socket.gethostname())
|
|
218
241
|
base = ['docker', 'compose', '-f', str(compose_path)]
|
|
219
242
|
try:
|
|
220
243
|
if args.pull:
|
|
244
|
+
print('[2/3] Pulling latest images...')
|
|
221
245
|
subprocess.run([*base, 'pull'], env=env, check=True)
|
|
246
|
+
print(f'[2/3] Starting containers: {", ".join(COMPOSE_SERVICES_UP)}...')
|
|
222
247
|
subprocess.run([*base, 'up', '-d', *COMPOSE_SERVICES_UP], env=env, check=True)
|
|
248
|
+
print(f'[3/3] Creating (not starting): {", ".join(COMPOSE_SERVICES_CREATE_ONLY)}...')
|
|
223
249
|
subprocess.run(
|
|
224
250
|
[*base, 'create', '--no-recreate', *COMPOSE_SERVICES_CREATE_ONLY],
|
|
225
251
|
env=env,
|
|
@@ -242,23 +268,27 @@ def cmd_up(args: argparse.Namespace) -> int:
|
|
|
242
268
|
|
|
243
269
|
def _teardown_host_agent() -> None:
|
|
244
270
|
"""Stop and remove the host agent service, unit file, sudoers, and socket dir."""
|
|
271
|
+
print(f'Tearing down {HOST_AGENT_SERVICE}...')
|
|
245
272
|
steps = [
|
|
246
273
|
(['sudo', 'systemctl', 'stop', f'{HOST_AGENT_SERVICE}.service'], 'stop service'),
|
|
247
274
|
(['sudo', 'systemctl', 'disable', f'{HOST_AGENT_SERVICE}.service'], 'disable service'),
|
|
248
275
|
(['sudo', 'rm', '-f', f'/etc/systemd/system/{HOST_AGENT_SERVICE}.service'], 'remove unit file'),
|
|
249
|
-
(['sudo', 'systemctl', 'daemon-reload'], 'reload
|
|
276
|
+
(['sudo', 'systemctl', 'daemon-reload'], 'daemon-reload'),
|
|
250
277
|
(['sudo', 'rm', '-f', '/etc/sudoers.d/cyclo_manager'], 'remove sudoers'),
|
|
251
278
|
(['sudo', 'rm', '-rf', HOST_AGENT_SOCKET_DIR], 'remove socket dir'),
|
|
252
279
|
]
|
|
253
280
|
for cmd, desc in steps:
|
|
281
|
+
print(f' {desc}...')
|
|
254
282
|
try:
|
|
255
283
|
subprocess.run(cmd, check=True, capture_output=True)
|
|
256
284
|
except subprocess.CalledProcessError:
|
|
257
|
-
print(f'Warning: failed to {desc}.', file=sys.stderr)
|
|
285
|
+
print(f' Warning: failed to {desc}.', file=sys.stderr)
|
|
258
286
|
|
|
259
287
|
|
|
260
288
|
def cmd_down(args: argparse.Namespace) -> int:
|
|
261
289
|
"""Stop cyclo_manager server, cyclo_manager_ui, and zenoh daemon (docker compose down)."""
|
|
290
|
+
print('--- cyclo_manager down ---')
|
|
291
|
+
|
|
262
292
|
_teardown_host_agent()
|
|
263
293
|
|
|
264
294
|
compose_path = _docker_dir() / 'docker-compose.yml'
|
|
@@ -267,6 +297,7 @@ def cmd_down(args: argparse.Namespace) -> int:
|
|
|
267
297
|
return 1
|
|
268
298
|
env = os.environ.copy()
|
|
269
299
|
env['CYCLO_MANAGER_CONFIG_FILE'] = str(_packaged_config_path())
|
|
300
|
+
env.setdefault('HOSTNAME', socket.gethostname())
|
|
270
301
|
cmd = [
|
|
271
302
|
'docker',
|
|
272
303
|
'compose',
|
|
@@ -274,6 +305,7 @@ def cmd_down(args: argparse.Namespace) -> int:
|
|
|
274
305
|
str(compose_path),
|
|
275
306
|
'down',
|
|
276
307
|
]
|
|
308
|
+
print('Stopping Docker containers (docker compose down)...')
|
|
277
309
|
try:
|
|
278
310
|
subprocess.run(cmd, env=env, check=True)
|
|
279
311
|
except subprocess.CalledProcessError as e:
|
|
@@ -285,7 +317,7 @@ def cmd_down(args: argparse.Namespace) -> int:
|
|
|
285
317
|
)
|
|
286
318
|
return 1
|
|
287
319
|
|
|
288
|
-
print('cyclo_manager
|
|
320
|
+
print('cyclo_manager is down.')
|
|
289
321
|
return 0
|
|
290
322
|
|
|
291
323
|
|
|
@@ -302,6 +334,7 @@ def cmd_update(args: argparse.Namespace) -> int:
|
|
|
302
334
|
return 1
|
|
303
335
|
env = os.environ.copy()
|
|
304
336
|
env['CYCLO_MANAGER_CONFIG_FILE'] = str(_packaged_config_path())
|
|
337
|
+
env.setdefault('HOSTNAME', socket.gethostname())
|
|
305
338
|
base = ['docker', 'compose', '-f', str(compose_path)]
|
|
306
339
|
|
|
307
340
|
print('Stopping containers...')
|
|
@@ -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.dev10"
|
|
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
|
|
File without changes
|
{cyclo_manager-0.2.0.dev8 → cyclo_manager-0.2.0.dev10}/cyclo_manager.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{cyclo_manager-0.2.0.dev8 → cyclo_manager-0.2.0.dev10}/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.dev8 → cyclo_manager-0.2.0.dev10}/cyclo_manager_cli/docker/docker-compose.yml
RENAMED
|
File without changes
|
|
File without changes
|