-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinit_sys.py
More file actions
224 lines (186 loc) · 5.99 KB
/
Copy pathinit_sys.py
File metadata and controls
224 lines (186 loc) · 5.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
#!/usr/bin/env python3
# init_sys.py
"""
Módulo de Inicialización y Provisionamiento del Sistema.
Este script configura el entorno de ejecución del sensor, creando la estructura
de directorios necesaria, limpiando estados previos (Cron y SHM) y generando
los archivos de configuración para systemd.
"""
import sys
import argparse
import getpass
import cfg
from functions import CronSchedulerCampaign, ShmStore
log = cfg.set_logger()
DAEMONS_DIR = cfg.PROJECT_ROOT / "daemons"
# --- DEFINICIONES DE DAEMONS ---
RF_APP_DAEMON = f"""
[Unit]
Description=RF service ANE2
After=network.target
[Service]
User=__USER__
WorkingDirectory={str(cfg.PROJECT_ROOT)}
# flock asegura instancia única usando un archivo lock temporal
ExecStart=/usr/bin/flock -n /tmp/rf_app.lock {str(cfg.PROJECT_ROOT)}/rf_app
Restart=always
RestartSec=5
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=rf-ane2
[Install]
WantedBy=multi-user.target
"""
LTEGPS_DAEMON = f"""
[Unit]
Description=LTE/GPS Service
After=network.target
[Service]
User=__USER__
WorkingDirectory={str(cfg.PROJECT_ROOT)}
ExecStart=/usr/bin/flock -n /tmp/ltegps_app.lock {str(cfg.PROJECT_ROOT)}/ltegps_app
Restart=always
RestartSec=5
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=ltegps-ane2
[Install]
WantedBy=multi-user.target
"""
ORCHESTRATOR_DAEMON = f"""
[Unit]
Description=Orchestrator Service ANE2
Wants=network-online.target
After=network-online.target
[Service]
User=__USER__
Restart=always
RestartSec=5
WorkingDirectory={str(cfg.PROJECT_ROOT)}
ExecStartPre=/usr/bin/ping -c 1 -w 5 google.com
ExecStart=/usr/bin/flock -n /tmp/orchestrator.lock {cfg.PYTHON_ENV_STR} orchestrator.py
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=orchestrator-ane2
[Install]
WantedBy=multi-user.target
"""
STATUS_DAEMON = f"""
[Unit]
Description=Status Service ANE2
Wants=network-online.target
After=network-online.target
[Service]
User=__USER__
Type=oneshot
WorkingDirectory={str(cfg.PROJECT_ROOT)}
ExecStartPre=/usr/bin/ping -c 1 -w 5 google.com
ExecStart=/usr/bin/flock -n /tmp/status.lock {cfg.PYTHON_ENV_STR} status.py
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=status-ane2
[Install]
WantedBy=multi-user.target
"""
STATUS_DAEMON_TIMER = f"""
[Unit]
Description=Timer Status Service ANE2
[Timer]
OnBootSec=1min
OnUnitInactiveSec={cfg.INTERVAL_STATUS_S}s
AccuracySec=1s
[Install]
WantedBy=timers.target
"""
QUEUE_DAEMON = f"""
[Unit]
Description=Retry Queue Service ANE2
Wants=network-online.target
After=network-online.target
[Service]
User=__USER__
Type=oneshot
WorkingDirectory={str(cfg.PROJECT_ROOT)}
ExecStartPre=/usr/bin/ping -c 1 -w 5 google.com
ExecStart=/usr/bin/flock -n /tmp/retry_queue.lock {cfg.PYTHON_ENV_STR} retry_queue.py
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=retry-queue-ane2
[Install]
WantedBy=multi-user.target
"""
QUEUE_DAEMON_TIMER = f"""
[Unit]
Description=Timer Retry Queue Service ANE2
[Timer]
OnBootSec=1min
OnUnitInactiveSec={cfg.INTERVAL_RETRY_QUEUE_S}s
AccuracySec=1s
[Install]
WantedBy=timers.target
"""
def save_daemon_file(filename: str, content: str, daemon_user: str = "anepi"):
"""
Escribe el contenido de un archivo de unidad systemd en el directorio de daemons.
Args:
filename (str): Nombre del archivo (ej. 'rf-ane2.service').
content (str): Texto plano con la configuración del servicio.
daemon_user (str): Usuario del sistema para los servicios.
"""
file_path = DAEMONS_DIR / filename
content = content.replace("__USER__", daemon_user)
try:
with open(file_path, "w") as f:
f.write(content.strip() + "\n")
log.info(f"Generated daemon file: {file_path}")
except Exception as e:
log.error(f"Failed to write {filename}: {e}")
def main() -> int:
"""
Flujo principal de inicialización.
1. Crea directorios de trabajo (logs, queue, etc.).
2. Limpia las campañas antiguas del Crontab del usuario.
3. Reinicia la memoria compartida persistente.
4. Genera los archivos .service y .timer basados en las plantillas
definidas y las rutas del archivo `cfg`.
Returns:
int: 0 si la inicialización fue exitosa, 1 si ocurrió un error crítico.
"""
parser = argparse.ArgumentParser(description="Systemd init for SDR Sensor")
parser.add_argument("--user", default=getpass.getuser(),
help="System user for daemon services (default: current user)")
args = parser.parse_args()
daemon_user = args.user
log.info(f"Starting System Initialization (daemon user: {daemon_user})...")
for p in [cfg.QUEUE_DIR, cfg.LOGS_DIR, cfg.HISTORIC_DIR, DAEMONS_DIR]:
p.mkdir(parents=True, exist_ok=True)
try:
init_scheduler = CronSchedulerCampaign(
poll_interval_s=cfg.INTERVAL_REQUEST_CAMPAIGNS_S,
python_env=cfg.PYTHON_ENV_STR,
cmd=str((cfg.PROJECT_ROOT / "campaign_runner.py").absolute()),
logger=log
)
init_scheduler.cron.remove_all(comment=lambda c: c.startswith("CAMPAIGN_"))
init_scheduler.cron.write()
log.info("Crontab cleaned successfully.")
except Exception as e:
log.error(f"Error cleaning Crontab: {e}")
try:
store = ShmStore()
store.clear_persistent()
log.info("Shared memory cleared.")
except Exception as e:
log.error(f"Error clearing Shared Memory: {e}")
save_daemon_file("rf-ane2.service", RF_APP_DAEMON, daemon_user)
save_daemon_file("ltegps-ane2.service", LTEGPS_DAEMON, daemon_user)
save_daemon_file("orchestrator-ane2.service", ORCHESTRATOR_DAEMON, daemon_user)
save_daemon_file("retry-queue-ane2.service", QUEUE_DAEMON, daemon_user)
save_daemon_file("retry-queue-ane2.timer", QUEUE_DAEMON_TIMER, daemon_user)
save_daemon_file("status-ane2.service", STATUS_DAEMON, daemon_user)
save_daemon_file("status-ane2.timer", STATUS_DAEMON_TIMER, daemon_user)
log.info("System Initialization Complete.")
return 0
if __name__ == "__main__":
rc = cfg.run_and_capture(main)
sys.exit(rc)