feat: implement /update in BaseAgent (git pull + systemctl restart)
- _do_self_update(): git pull, skip restart if already up to date, send result back via MQTT reply_to before restarting (2s delay) - _get_install_dir(): derive from config path - _get_service_name(): from config or install dir basename Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -511,9 +511,81 @@ class BaseAgent(ABC):
|
||||
all_agents = [a.agent_id for a in self.registry.all_agents()]
|
||||
return f"Agents en ligne : {online}\nAgents connus : {all_agents}"
|
||||
|
||||
if cmd == "update":
|
||||
return self._do_self_update(source_msg)
|
||||
|
||||
# Commandes custom de l'agent
|
||||
return self.handle_custom_command(cmd, args, source_msg)
|
||||
|
||||
# ──────────────────────────────────────────────
|
||||
# Mise à jour self
|
||||
# ──────────────────────────────────────────────
|
||||
|
||||
def _get_install_dir(self) -> str:
|
||||
"""Répertoire d'installation : parent du dossier config."""
|
||||
return os.path.dirname(os.path.dirname(os.path.abspath(self._config_path)))
|
||||
|
||||
def _get_service_name(self) -> str:
|
||||
"""Nom du service systemd : depuis config ou nom du répertoire d'install."""
|
||||
return self.config.get("service_name") or os.path.basename(self._get_install_dir())
|
||||
|
||||
def _do_self_update(self, source_msg: Optional[Message] = None) -> str:
|
||||
"""git pull → systemctl restart si des changements sont détectés."""
|
||||
import subprocess
|
||||
|
||||
install_dir = self._get_install_dir()
|
||||
service_name = self._get_service_name()
|
||||
logger.info(f"[Update] git pull dans {install_dir} (service : {service_name})")
|
||||
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["git", "pull"],
|
||||
cwd=install_dir,
|
||||
capture_output=True, text=True, timeout=60,
|
||||
)
|
||||
except Exception as e:
|
||||
msg = f"[{self.agent_id}] ❌ git pull impossible : {e}"
|
||||
self._send_update_reply(source_msg, msg)
|
||||
return msg
|
||||
|
||||
if result.returncode != 0:
|
||||
msg = f"[{self.agent_id}] ❌ git pull échoué :\n{result.stderr.strip()}"
|
||||
self._send_update_reply(source_msg, msg)
|
||||
return msg
|
||||
|
||||
stdout = result.stdout.strip()
|
||||
|
||||
if "Already up to date" in stdout:
|
||||
msg = f"[{self.agent_id}] ✓ Déjà à jour — pas de redémarrage."
|
||||
self._send_update_reply(source_msg, msg)
|
||||
return msg
|
||||
|
||||
msg = (
|
||||
f"[{self.agent_id}] ✓ Mis à jour :\n{stdout}\n"
|
||||
f"Redémarrage du service {service_name}..."
|
||||
)
|
||||
self._send_update_reply(source_msg, msg)
|
||||
|
||||
# Restart différé pour laisser le temps au message MQTT d'être envoyé
|
||||
def _restart():
|
||||
import time
|
||||
time.sleep(2)
|
||||
try:
|
||||
subprocess.run(["systemctl", "restart", service_name], timeout=30, check=True)
|
||||
except Exception as e:
|
||||
logger.error(f"[Update] Erreur restart {service_name} : {e}")
|
||||
|
||||
threading.Thread(target=_restart, daemon=True, name="update-restart").start()
|
||||
return msg
|
||||
|
||||
def _send_update_reply(self, source_msg: Optional[Message], body: str):
|
||||
"""Renvoie la réponse d'update à Nexus via MQTT si possible."""
|
||||
if source_msg and source_msg.reply_to:
|
||||
try:
|
||||
self.mqtt.reply(source_msg, body)
|
||||
except Exception as e:
|
||||
logger.debug(f"[Update] Impossible d'envoyer la réponse : {e}")
|
||||
|
||||
# ──────────────────────────────────────────────
|
||||
# Capacités
|
||||
# ──────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user