Nom libre pour l'agent déployé : étape enter_name + JID suggéré automatiquement
- state machine : nouvelle étape enter_name après choose_agent
- XMPP JID suggéré par défaut : {nom}@xmpp.ovh (modifiable)
- MQTT inbox/service/install_path basés sur le nom libre
- notify_agent1 publie sur agents/register avec le bon format JSON
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+45
-21
@@ -60,16 +60,18 @@ def register_to_agent1():
|
|||||||
mqtt_publish("agents/register", payload)
|
mqtt_publish("agents/register", payload)
|
||||||
print("[REGISTER] Déclaration envoyée à agent1.")
|
print("[REGISTER] Déclaration envoyée à agent1.")
|
||||||
|
|
||||||
def notify_agent1(agent_type: str, host: str, xmpp_jid: str, mqtt_inbox: str):
|
def notify_agent1(agent_name: str, agent_type: str, host: str, xmpp_jid: str, speciality: str):
|
||||||
"""Informe agent1 du nouveau déploiement."""
|
"""Publie sur agents/register pour que agent1 enregistre le nouvel agent."""
|
||||||
msg = (
|
import json as _json
|
||||||
"[DEPLOY] Nouvel agent déployé.\n"
|
payload = _json.dumps({
|
||||||
" Type : {}\n"
|
"agent" : agent_name,
|
||||||
" Hôte : {}\n"
|
"jid" : xmpp_jid,
|
||||||
" XMPP JID : {}\n"
|
"mqtt_inbox": "agents/{}/inbox".format(agent_name),
|
||||||
" MQTT : {}"
|
"speciality": speciality,
|
||||||
).format(agent_type, host, xmpp_jid, mqtt_inbox)
|
"host" : host,
|
||||||
mqtt_publish(AGENT1_INBOX, msg)
|
"type" : agent_type,
|
||||||
|
})
|
||||||
|
mqtt_publish("agents/register", payload)
|
||||||
|
|
||||||
# ── MACHINE À ÉTATS ───────────────────────────────────────────────────────
|
# ── MACHINE À ÉTATS ───────────────────────────────────────────────────────
|
||||||
# sessions[jid] = dict avec toutes les infos collectées + état courant
|
# sessions[jid] = dict avec toutes les infos collectées + état courant
|
||||||
@@ -102,6 +104,7 @@ def start_session(jid: str) -> str:
|
|||||||
sessions[jid] = {
|
sessions[jid] = {
|
||||||
"state" : "choose_agent",
|
"state" : "choose_agent",
|
||||||
"agent_type" : None,
|
"agent_type" : None,
|
||||||
|
"agent_name" : None, # nom libre choisi par l'utilisateur (ex: trouducul)
|
||||||
"target_ip" : None,
|
"target_ip" : None,
|
||||||
"ssh_user" : None,
|
"ssh_user" : None,
|
||||||
"auth_type" : None, # "password" ou "key"
|
"auth_type" : None, # "password" ou "key"
|
||||||
@@ -146,8 +149,24 @@ def handle_session(jid: str, text: str) -> str | None:
|
|||||||
session["agent_type"] = text
|
session["agent_type"] = text
|
||||||
else:
|
else:
|
||||||
return "Agent inconnu. Tapez le numéro ou le nom exact.\n\n" + list_agents()
|
return "Agent inconnu. Tapez le numéro ou le nom exact.\n\n" + list_agents()
|
||||||
|
session["state"] = "enter_name"
|
||||||
|
return (
|
||||||
|
"Agent choisi : {}.\n\n"
|
||||||
|
"Quel nom donner à cet agent ?\n"
|
||||||
|
"Ce nom sera utilisé dans vos commandes (ex: \"mets à jour trouducul\"),\n"
|
||||||
|
"comme nom du service systemd et comme identifiant MQTT.\n"
|
||||||
|
"Lettres, chiffres, tirets et underscores uniquement."
|
||||||
|
).format(session["agent_type"])
|
||||||
|
|
||||||
|
# ── enter_name ────────────────────────────────────────────────────────
|
||||||
|
elif state == "enter_name":
|
||||||
|
import re
|
||||||
|
name = text.strip().lower()
|
||||||
|
if not name or not re.match(r'^[a-z0-9_-]+$', name):
|
||||||
|
return "Nom invalide. Utilisez uniquement des lettres, chiffres, tirets ou underscores."
|
||||||
|
session["agent_name"] = name
|
||||||
session["state"] = "enter_ip"
|
session["state"] = "enter_ip"
|
||||||
return "Agent choisi : {}.\n\nAdresse IP de la machine cible ?".format(session["agent_type"])
|
return "Nom choisi : {}.\n\nAdresse IP de la machine cible ?".format(name)
|
||||||
|
|
||||||
# ── enter_ip ──────────────────────────────────────────────────────────
|
# ── enter_ip ──────────────────────────────────────────────────────────
|
||||||
elif state == "enter_ip":
|
elif state == "enter_ip":
|
||||||
@@ -186,17 +205,18 @@ def handle_session(jid: str, text: str) -> str | None:
|
|||||||
else:
|
else:
|
||||||
session["ssh_key_path"] = text
|
session["ssh_key_path"] = text
|
||||||
session["state"] = "enter_xmpp_jid"
|
session["state"] = "enter_xmpp_jid"
|
||||||
agent_type = session["agent_type"]
|
default_jid = "{}@xmpp.ovh".format(session["agent_name"])
|
||||||
return (
|
return (
|
||||||
"JID XMPP pour cet agent sur la machine distante ?\n"
|
"Adresse XMPP (JID) pour cet agent ?\n"
|
||||||
"(ex: {}@xmpp.ovh)".format(agent_type)
|
"(entrée vide = {})".format(default_jid)
|
||||||
)
|
)
|
||||||
|
|
||||||
# ── enter_xmpp_jid ───────────────────────────────────────────────────
|
# ── enter_xmpp_jid ───────────────────────────────────────────────────
|
||||||
elif state == "enter_xmpp_jid":
|
elif state == "enter_xmpp_jid":
|
||||||
session["xmpp_jid"] = text
|
default_jid = "{}@xmpp.ovh".format(session["agent_name"])
|
||||||
|
session["xmpp_jid"] = text if text else default_jid
|
||||||
session["state"] = "enter_xmpp_pass"
|
session["state"] = "enter_xmpp_pass"
|
||||||
return "Mot de passe XMPP pour {} :".format(text)
|
return "Mot de passe XMPP pour {} :".format(session["xmpp_jid"])
|
||||||
|
|
||||||
# ── enter_xmpp_pass ──────────────────────────────────────────────────
|
# ── enter_xmpp_pass ──────────────────────────────────────────────────
|
||||||
elif state == "enter_xmpp_pass":
|
elif state == "enter_xmpp_pass":
|
||||||
@@ -216,23 +236,25 @@ def handle_session(jid: str, text: str) -> str | None:
|
|||||||
agent_info = catalog[s["agent_type"]]
|
agent_info = catalog[s["agent_type"]]
|
||||||
return (
|
return (
|
||||||
"Récapitulatif du déploiement :\n"
|
"Récapitulatif du déploiement :\n"
|
||||||
" Agent : {agent_type}\n"
|
" Type : {agent_type}\n"
|
||||||
|
" Nom : {agent_name}\n"
|
||||||
" Repo : {repo}\n"
|
" Repo : {repo}\n"
|
||||||
" Machine : {ssh_user}@{target_ip}\n"
|
" Machine : {ssh_user}@{target_ip}\n"
|
||||||
" Auth SSH : {auth}\n"
|
" Auth SSH : {auth}\n"
|
||||||
" XMPP JID : {xmpp_jid}\n"
|
" XMPP JID : {xmpp_jid}\n"
|
||||||
" MQTT broker: {mqtt_host}\n"
|
" MQTT broker: {mqtt_host}\n"
|
||||||
" MQTT inbox : {mqtt_inbox}\n\n"
|
" MQTT inbox : agents/{agent_name}/inbox\n"
|
||||||
|
" Service : {agent_name}.service\n\n"
|
||||||
"Confirmer le déploiement ? (oui / non)"
|
"Confirmer le déploiement ? (oui / non)"
|
||||||
).format(
|
).format(
|
||||||
agent_type=s["agent_type"],
|
agent_type=s["agent_type"],
|
||||||
|
agent_name=s["agent_name"],
|
||||||
repo=agent_info["repo_url"],
|
repo=agent_info["repo_url"],
|
||||||
ssh_user=s["ssh_user"],
|
ssh_user=s["ssh_user"],
|
||||||
target_ip=s["target_ip"],
|
target_ip=s["target_ip"],
|
||||||
auth="clé SSH" if s["auth_type"] == "key" else "mot de passe",
|
auth="clé SSH" if s["auth_type"] == "key" else "mot de passe",
|
||||||
xmpp_jid=s["xmpp_jid"],
|
xmpp_jid=s["xmpp_jid"],
|
||||||
mqtt_host=s["mqtt_host"],
|
mqtt_host=s["mqtt_host"],
|
||||||
mqtt_inbox=agent_info["mqtt_inbox"],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# ── confirm ───────────────────────────────────────────────────────────
|
# ── confirm ───────────────────────────────────────────────────────────
|
||||||
@@ -316,6 +338,7 @@ class DeployBot(ClientXMPP):
|
|||||||
host = session["target_ip"],
|
host = session["target_ip"],
|
||||||
ssh_user = session["ssh_user"],
|
ssh_user = session["ssh_user"],
|
||||||
agent_type = session["agent_type"],
|
agent_type = session["agent_type"],
|
||||||
|
agent_name = session["agent_name"],
|
||||||
xmpp_jid = session["xmpp_jid"],
|
xmpp_jid = session["xmpp_jid"],
|
||||||
xmpp_pass = session["xmpp_pass"],
|
xmpp_pass = session["xmpp_pass"],
|
||||||
mqtt_host = session["mqtt_host"],
|
mqtt_host = session["mqtt_host"],
|
||||||
@@ -325,12 +348,13 @@ class DeployBot(ClientXMPP):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
mqtt_inbox = catalog[session["agent_type"]]["mqtt_inbox"]
|
speciality = catalog[session["agent_type"]]["description"]
|
||||||
notify_agent1(
|
notify_agent1(
|
||||||
|
agent_name = session["agent_name"],
|
||||||
agent_type = session["agent_type"],
|
agent_type = session["agent_type"],
|
||||||
host = session["target_ip"],
|
host = session["target_ip"],
|
||||||
xmpp_jid = session["xmpp_jid"],
|
xmpp_jid = session["xmpp_jid"],
|
||||||
mqtt_inbox = mqtt_inbox,
|
speciality = speciality,
|
||||||
)
|
)
|
||||||
self.reply(jid, result)
|
self.reply(jid, result)
|
||||||
else:
|
else:
|
||||||
|
|||||||
+12
-8
@@ -48,6 +48,7 @@ def deploy_agent(
|
|||||||
host: str,
|
host: str,
|
||||||
ssh_user: str,
|
ssh_user: str,
|
||||||
agent_type: str,
|
agent_type: str,
|
||||||
|
agent_name: str,
|
||||||
xmpp_jid: str,
|
xmpp_jid: str,
|
||||||
xmpp_pass: str,
|
xmpp_pass: str,
|
||||||
mqtt_host: str,
|
mqtt_host: str,
|
||||||
@@ -57,6 +58,7 @@ def deploy_agent(
|
|||||||
) -> tuple[bool, str]:
|
) -> tuple[bool, str]:
|
||||||
"""
|
"""
|
||||||
Déploie un agent sur la machine distante.
|
Déploie un agent sur la machine distante.
|
||||||
|
agent_name : nom libre choisi par l'utilisateur (ex: trouducul)
|
||||||
progress_cb(msg) : callback appelé à chaque étape pour informer l'utilisateur.
|
progress_cb(msg) : callback appelé à chaque étape pour informer l'utilisateur.
|
||||||
Retourne (succès, message_final).
|
Retourne (succès, message_final).
|
||||||
"""
|
"""
|
||||||
@@ -65,13 +67,15 @@ def deploy_agent(
|
|||||||
return False, "Agent inconnu : {}".format(agent_type)
|
return False, "Agent inconnu : {}".format(agent_type)
|
||||||
|
|
||||||
agent = catalog[agent_type]
|
agent = catalog[agent_type]
|
||||||
install_path = agent["install_path"]
|
|
||||||
repo_url = agent["repo_url"]
|
repo_url = agent["repo_url"]
|
||||||
service_name = agent["service_name"]
|
|
||||||
main_script = agent["main_script"]
|
main_script = agent["main_script"]
|
||||||
deps = " ".join(agent["dependencies"])
|
deps = " ".join(agent["dependencies"])
|
||||||
mqtt_inbox = agent["mqtt_inbox"]
|
|
||||||
mqtt_outbox = agent["mqtt_outbox"]
|
# Le nom libre détermine install_path, service, MQTT
|
||||||
|
install_path = "/opt/{}".format(agent_name)
|
||||||
|
service_name = agent_name
|
||||||
|
mqtt_inbox = "agents/{}/inbox".format(agent_name)
|
||||||
|
mqtt_outbox = "agents/agent1/inbox"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# ── Connexion SSH ──────────────────────────────────────────────────
|
# ── Connexion SSH ──────────────────────────────────────────────────
|
||||||
@@ -119,7 +123,7 @@ def deploy_agent(
|
|||||||
"db_path" : "{}/memory.db".format(install_path),
|
"db_path" : "{}/memory.db".format(install_path),
|
||||||
"mqtt_host" : mqtt_host,
|
"mqtt_host" : mqtt_host,
|
||||||
"mqtt_port" : 1883,
|
"mqtt_port" : 1883,
|
||||||
"mqtt_client_id": agent_type,
|
"mqtt_client_id": agent_name,
|
||||||
"mqtt_inbox" : mqtt_inbox,
|
"mqtt_inbox" : mqtt_inbox,
|
||||||
"mqtt_outbox" : mqtt_outbox,
|
"mqtt_outbox" : mqtt_outbox,
|
||||||
}
|
}
|
||||||
@@ -146,7 +150,7 @@ StandardError=journal
|
|||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
""".format(name=agent_type, path=install_path, script=main_script)
|
""".format(name=agent_name, path=install_path, script=main_script)
|
||||||
|
|
||||||
write_remote_file(client,
|
write_remote_file(client,
|
||||||
"/etc/systemd/system/{}.service".format(service_name),
|
"/etc/systemd/system/{}.service".format(service_name),
|
||||||
@@ -163,11 +167,11 @@ WantedBy=multi-user.target
|
|||||||
client.close()
|
client.close()
|
||||||
|
|
||||||
summary = (
|
summary = (
|
||||||
"Déploiement de {} terminé sur {} !\n"
|
"Déploiement de «{}» ({}) terminé sur {} !\n"
|
||||||
" JID XMPP : {}\n"
|
" JID XMPP : {}\n"
|
||||||
" MQTT inbox : {}\n"
|
" MQTT inbox : {}\n"
|
||||||
" Service : systemctl status {}"
|
" Service : systemctl status {}"
|
||||||
).format(agent_type, host, xmpp_jid, mqtt_inbox, service_name)
|
).format(agent_name, agent_type, host, xmpp_jid, mqtt_inbox, service_name)
|
||||||
|
|
||||||
return True, summary
|
return True, summary
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user