feat(assistant): reboot via TR-069 pour les ONU tech-3 (repli GenieACS)
Le reboot d'olt-ops = SNMP Raisecom (tech-2) seulement → pour un ONU tech-3
(TPLG, la plus grosse flotte) device_action(reboot) tombait en « non exécutable »
et l'assistant proposait un déplacement. Ajout : devices.rebootBySerial(serial)
(résout le n° de série → _id ACS via fetchDeviceDetails, pose une tâche GenieACS
{name:reboot} + connection_request). device_action route le reboot vers TR-069
(params.via=tr069) quand olt-ops ne peut pas ; sinon SNMP (tech-2) inchangé.
Toujours staged → confirmation humaine avant le moindre redémarrage.
Vérifié live (staging, aucun reboot tiré) : « redémarre le modem de C-LPB4 »
→ device_action staged « Redémarrer le modem (TR-069) — ONU TPLGC4160688 ».
Résolution série→ACS validée (TPLGC4160688 → E4FAC4-Device2-…). 1er reboot réel
= déclenché par l'utilisateur via le bouton Confirmer.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
6d07f070d7
commit
4f24179f4f
|
|
@ -609,4 +609,20 @@ async function handleACSConfig (req, res, method, path) {
|
|||
}
|
||||
}
|
||||
|
||||
module.exports = { handle, handleACSConfig, summarizeDevice, cacheDevice, getCached, getCacheStats, fetchDeviceDetails, startPoller, stopPoller, logDeviceEvent, getDeviceEvents }
|
||||
// Reboot TR-069 (GenieACS) par n° de série — résout l'appareil (fetchDeviceDetails → _id ACS) puis pose une tâche
|
||||
// `reboot` avec connection_request. Sert au reboot des ONU/modems tech-3 (TPLG) que olt-ops ne gère PAS (son reboot
|
||||
// natif = SNMP Raisecom tech-2 seulement). Best-effort → { ok, status, device_id, error }.
|
||||
async function rebootBySerial (serial) {
|
||||
if (!serial) return { ok: false, error: 'serial requis' }
|
||||
let sum = null
|
||||
try { sum = await fetchDeviceDetails(String(serial)) } catch (e) { return { ok: false, error: 'résolution TR-069 : ' + e.message } }
|
||||
const id = sum && sum._id
|
||||
if (!id) return { ok: false, error: 'appareil TR-069 introuvable pour ' + serial }
|
||||
try {
|
||||
const r = await nbiRequest(`/devices/${encodeURIComponent(id)}/tasks?connection_request&timeout=15000`, 'POST', { name: 'reboot' })
|
||||
const ok = r.status >= 200 && r.status < 300
|
||||
return { ok, status: r.status, device_id: id, error: ok ? null : ('GenieACS a refusé la tâche reboot (HTTP ' + r.status + ')') }
|
||||
} catch (e) { return { ok: false, device_id: id, error: e.message } }
|
||||
}
|
||||
|
||||
module.exports = { handle, handleACSConfig, summarizeDevice, cacheDevice, getCached, getCacheStats, fetchDeviceDetails, startPoller, stopPoller, logDeviceEvent, getDeviceEvents, rebootBySerial }
|
||||
|
|
|
|||
|
|
@ -297,15 +297,26 @@ const WRITES = {
|
|||
if (p.new_sn) opts.new_sn = String(p.new_sn)
|
||||
// APERÇU = plan olt-ops (LECTURE SEULE) : effet, cible réseau, avertissements, exécutable ?
|
||||
const pl = await oltOps().plan({ serial, action, ...opts })
|
||||
if (!pl.can_run) throw new Error(`« ${pl.label || action} » non exécutable pour ${serial}${(pl.warnings && pl.warnings.length) ? ' — ' + pl.warnings.join(' ') : ''}`)
|
||||
const idempotencyKey = `sa-${action}-${serial}-${Date.now()}` // fixé au plan → un double-clic Confirmer rejoue la MÊME clé (dédup module)
|
||||
const who = pl.customer ? ` · client ${pl.customer}` : ''
|
||||
if (!pl.can_run) {
|
||||
// Repli REBOOT → TR-069 : les ONU tech-3 (TPLG, la plus grosse flotte) ne rebootent PAS via olt-ops (SNMP
|
||||
// Raisecom = tech-2). On passe alors par GenieACS (devices.rebootBySerial). Autres actions : non exécutables.
|
||||
if (action === 'reboot') {
|
||||
return { title: META.device_action.title, preview: `Redémarrer le modem (TR-069) — ONU ${serial}${who} · le modem redémarre (~2 min hors ligne).`, severity: 'normal', params: { via: 'tr069', serial, action, idempotencyKey } }
|
||||
}
|
||||
throw new Error(`« ${pl.label || action} » non exécutable pour ${serial}${(pl.warnings && pl.warnings.length) ? ' — ' + pl.warnings.join(' ') : ''}`)
|
||||
}
|
||||
const warn = (pl.warnings && pl.warnings.length) ? ' ⚠ ' + pl.warnings.join(' ') : ''
|
||||
const preview = `${pl.label} — ONU ${pl.target.serial}${pl.target.olt ? ' · OLT ' + pl.target.olt : ''}${who}${(pl.effects && pl.effects.length) ? ' · ' + pl.effects.join(' ') : ''}${warn}`
|
||||
const severity = /^(suspend|remove|replace|activate)$/.test(action) ? 'high' : 'normal'
|
||||
const idempotencyKey = `sa-${action}-${serial}-${Date.now()}` // fixé au plan → un double-clic Confirmer rejoue la MÊME clé (dédup module)
|
||||
return { title: META.device_action.title, preview, severity, params: { serial, action, profileid: opts.profileid || '', new_sn: opts.new_sn || '', idempotencyKey } }
|
||||
return { title: META.device_action.title, preview, severity, params: { via: 'olt', serial, action, profileid: opts.profileid || '', new_sn: opts.new_sn || '', idempotencyKey } }
|
||||
},
|
||||
async exec (p, email) {
|
||||
if (p.via === 'tr069') { // reboot via GenieACS (ONU tech-3)
|
||||
const r = await require('./devices').rebootBySerial(p.serial)
|
||||
return { ok: !!(r && r.ok), message: (r && r.ok) ? `✅ Redémarrage (TR-069) envoyé — ${p.serial}` : `échec redémarrage TR-069 : ${(r && r.error) || 'erreur'}`, data: r }
|
||||
}
|
||||
const opts = {}
|
||||
if (p.profileid) opts.profileid = p.profileid
|
||||
if (p.new_sn) opts.new_sn = p.new_sn
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user