Loading modules/snmp/snmp.cpp +12 −6 Changes for modules/snmp/snmp.cpp: 12 added lines, 6 removed lines. Original line number Diff line number Diff line Loading @@ -29,20 +29,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * over its sysbus API (include/snmpdd/api.h), plus syslite's services to * choose from. * * info -> {settings, status, units} * info -> {settings, state, units} * (not "status": the frontend takes a reply's "status" as its HTTP * status and drops it) * settings: enabled, interval, events, report{raid, lvm, * filesystems, disks, smart_attributes, services}, fsWarning, * fsCritical, tempWarning, tempCritical, * services[], targets[{host, port, version, community (1, 2c); * user, level, auth, authPasswordSet, priv, privPasswordSet * (3)}], enterprise, engineId (read only) * status: lastReport, nextReport (unix time, 0: never/off), sent, * state: lastReport, nextReport (unix time, 0: never/off), sent, * status, engineId, engineBoots, problems[], * targets[{target, sent, error}] * save {settings} replaces them all (as above, without enterprise and * engineId; version 3: authPassword, privPassword -- * empty keeps the target's current one) * send a report now -> {sent} * send a report now, collected and sent in the background * -> {started} (false: one is being collected already) */ #include <cstdlib> Loading @@ -69,7 +72,9 @@ long long num(const std::string &s) { return std::strtoll(s.c_str(), nullptr, 10 json_object *callSnmpdd(sysbus::Client &bus, const char *method, const Fields &args, sysbus::Message &reply) { Fields all = args; all.emplace_back("lang", webctl::language()); reply = bus.callService(snmpdd::Service, method, all); // snmpdd answers at once (it collects in the background): a call that // takes long means it hangs -- don't hold up webctl (calls are serialized) reply = bus.callService(snmpdd::Service, method, all, 15000); if (reply.type != sysbus::MessageType::Error) return nullptr; const std::string &name = reply.member; if (name == sysbus::error::ServiceUnknown) Loading Loading @@ -131,6 +136,7 @@ json_object *statusJson(const sysbus::Message &r) { else if (k == "next_report") json_object_object_add(o, "nextReport", json_object_new_int64(num(v))); else if (k == "sent") json_object_object_add(o, "sent", json_object_new_int64(num(v))); else if (k == "status") json_object_object_add(o, "status", jstr(v)); else if (k == "collecting") json_object_object_add(o, "collecting", json_object_new_boolean(v == "yes")); else if (k == "engine_id") json_object_object_add(o, "engineId", jstr(v)); else if (k == "engine_boots") json_object_object_add(o, "engineBoots", json_object_new_int64(num(v))); else if (k == "problem") json_object_array_add(problems, jstr(v)); Loading Loading @@ -205,7 +211,7 @@ json_object *call(const webctl_request *req) { } json_object *out = json_object_new_object(); json_object_object_add(out, "settings", settings); json_object_object_add(out, "status", statusJson(reply)); json_object_object_add(out, "state", statusJson(reply)); // the services to choose from (mounts are file systems) json_object *units = json_object_new_array(); for (auto &u : bus.listUnits()) Loading @@ -225,7 +231,7 @@ json_object *call(const webctl_request *req) { if (action == "send") { if (json_object *err = callSnmpdd(bus, snmpdd::method::SendReport, {}, reply)) return err; json_object *out = json_object_new_object(); json_object_object_add(out, "sent", json_object_new_int64(num(reply.get("sent", "0")))); json_object_object_add(out, "started", json_object_new_boolean(reply.get("started") == "yes")); return out; } return error(tr("unknown action %1", "unbekannte Aktion %1", {action}), 404); Loading www/modules/snmp.js +22 −6 Changes for www/modules/snmp.js: 22 added lines, 6 removed lines. Original line number Diff line number Diff line Loading @@ -43,7 +43,10 @@ 'File system warning at (% used)': 'Dateisystem-Warnung ab (% belegt)', 'critical at (% used)': 'kritisch ab (% belegt)', 'Services reported': 'Berichtete Dienste', 'None ticked: all services.': 'Keiner angehakt: alle Dienste.', 'Settings saved.': 'Einstellungen gespeichert.', '{0} notifications sent.': '{0} Benachrichtigungen gesendet.', 'Settings saved.': 'Einstellungen gespeichert.', 'Try again': 'Erneut versuchen', 'The report is collected and sent …': 'Der Bericht wird gesammelt und gesendet …', 'A report is being collected already.': 'Es wird bereits ein Bericht gesammelt.', 'collecting …': 'wird gesammelt …', 'Target saved.': 'Ziel gespeichert.', 'Target removed.': 'Ziel entfernt.', 'SNMPDD-MIB describes the notifications (/usr/share/snmp/mibs/SNMPDD-MIB.txt); load it into the NMS.': 'SNMPDD-MIB beschreibt die Benachrichtigungen (/usr/share/snmp/mibs/SNMPDD-MIB.txt); im NMS laden.', Loading @@ -58,8 +61,18 @@ const every = s => s % 3600 === 0 ? t('{0} h', s / 3600) : s % 60 === 0 ? t('{0} min', s / 60) : t('{0} s', s); async function load() { const r = await run(() => call('snmp', 'info')); if (!r) return; let r; try { r = await call('snmp', 'info'); } catch (e) { // keep the error on the page (a toast is gone after a few seconds) if (!data) root.replaceChildren(h('section', {class: 'panel'}, h('p', {class: 'dialog-error'}, e.message), h('button', {onclick: () => { root.replaceChildren(h('p', {class: 'empty'}, t('Loading …'))); load(); }}, t('Try again')))); else toast(e.message, true); return; } data = r; draw(); } Loading Loading @@ -199,8 +212,10 @@ button.disabled = true; const r = await run(() => call('snmp', 'send')); button.disabled = false; if (r) toast(t('{0} notifications sent.', r.sent)); if (r) toast(r.started ? t('The report is collected and sent …') : t('A report is being collected already.')); load(); // collecting asks every disk: look again when it should be done setTimeout(load, 5000); } const levelText = {authPriv: 'authPriv', authNoPriv: 'authNoPriv', noAuthNoPriv: 'noAuthNoPriv'}; Loading @@ -215,7 +230,7 @@ } function draw() { const s = data.settings, st = data.status; const s = data.settings, st = data.state; const row = (label, value) => h('tr', {}, h('th', {}, label), h('td', {}, value)); const badge = name => h('span', {class: 'badge ' + (stateClass[name] || '')}, t(name || 'unknown')); const key = tg => (tg.host.includes(':') ? '[' + tg.host + ']' : tg.host) + ':' + tg.port; Loading @@ -232,7 +247,8 @@ : h('span', {class: 'badge'}, t('off'))), row(t('Last report'), when(st.lastReport)), row(t('Next report'), s.enabled ? when(st.nextReport) : '–'), row(t('Status'), st.lastReport ? badge(st.status) : '–'), row(t('Status'), st.collecting ? h('span', {class: 'badge warn'}, t('collecting …')) : st.lastReport ? badge(st.status) : '–'), st.problems.length ? row(t('Not collected'), st.problems.join('; ')) : null, row(t('Notifications sent'), String(st.sent || 0)), row(t('Enterprise OID'), h('span', {class: 'mono'}, s.enterprise || '')), Loading Loading
modules/snmp/snmp.cpp +12 −6 Changes for modules/snmp/snmp.cpp: 12 added lines, 6 removed lines. Original line number Diff line number Diff line Loading @@ -29,20 +29,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * over its sysbus API (include/snmpdd/api.h), plus syslite's services to * choose from. * * info -> {settings, status, units} * info -> {settings, state, units} * (not "status": the frontend takes a reply's "status" as its HTTP * status and drops it) * settings: enabled, interval, events, report{raid, lvm, * filesystems, disks, smart_attributes, services}, fsWarning, * fsCritical, tempWarning, tempCritical, * services[], targets[{host, port, version, community (1, 2c); * user, level, auth, authPasswordSet, priv, privPasswordSet * (3)}], enterprise, engineId (read only) * status: lastReport, nextReport (unix time, 0: never/off), sent, * state: lastReport, nextReport (unix time, 0: never/off), sent, * status, engineId, engineBoots, problems[], * targets[{target, sent, error}] * save {settings} replaces them all (as above, without enterprise and * engineId; version 3: authPassword, privPassword -- * empty keeps the target's current one) * send a report now -> {sent} * send a report now, collected and sent in the background * -> {started} (false: one is being collected already) */ #include <cstdlib> Loading @@ -69,7 +72,9 @@ long long num(const std::string &s) { return std::strtoll(s.c_str(), nullptr, 10 json_object *callSnmpdd(sysbus::Client &bus, const char *method, const Fields &args, sysbus::Message &reply) { Fields all = args; all.emplace_back("lang", webctl::language()); reply = bus.callService(snmpdd::Service, method, all); // snmpdd answers at once (it collects in the background): a call that // takes long means it hangs -- don't hold up webctl (calls are serialized) reply = bus.callService(snmpdd::Service, method, all, 15000); if (reply.type != sysbus::MessageType::Error) return nullptr; const std::string &name = reply.member; if (name == sysbus::error::ServiceUnknown) Loading Loading @@ -131,6 +136,7 @@ json_object *statusJson(const sysbus::Message &r) { else if (k == "next_report") json_object_object_add(o, "nextReport", json_object_new_int64(num(v))); else if (k == "sent") json_object_object_add(o, "sent", json_object_new_int64(num(v))); else if (k == "status") json_object_object_add(o, "status", jstr(v)); else if (k == "collecting") json_object_object_add(o, "collecting", json_object_new_boolean(v == "yes")); else if (k == "engine_id") json_object_object_add(o, "engineId", jstr(v)); else if (k == "engine_boots") json_object_object_add(o, "engineBoots", json_object_new_int64(num(v))); else if (k == "problem") json_object_array_add(problems, jstr(v)); Loading Loading @@ -205,7 +211,7 @@ json_object *call(const webctl_request *req) { } json_object *out = json_object_new_object(); json_object_object_add(out, "settings", settings); json_object_object_add(out, "status", statusJson(reply)); json_object_object_add(out, "state", statusJson(reply)); // the services to choose from (mounts are file systems) json_object *units = json_object_new_array(); for (auto &u : bus.listUnits()) Loading @@ -225,7 +231,7 @@ json_object *call(const webctl_request *req) { if (action == "send") { if (json_object *err = callSnmpdd(bus, snmpdd::method::SendReport, {}, reply)) return err; json_object *out = json_object_new_object(); json_object_object_add(out, "sent", json_object_new_int64(num(reply.get("sent", "0")))); json_object_object_add(out, "started", json_object_new_boolean(reply.get("started") == "yes")); return out; } return error(tr("unknown action %1", "unbekannte Aktion %1", {action}), 404); Loading
www/modules/snmp.js +22 −6 Changes for www/modules/snmp.js: 22 added lines, 6 removed lines. Original line number Diff line number Diff line Loading @@ -43,7 +43,10 @@ 'File system warning at (% used)': 'Dateisystem-Warnung ab (% belegt)', 'critical at (% used)': 'kritisch ab (% belegt)', 'Services reported': 'Berichtete Dienste', 'None ticked: all services.': 'Keiner angehakt: alle Dienste.', 'Settings saved.': 'Einstellungen gespeichert.', '{0} notifications sent.': '{0} Benachrichtigungen gesendet.', 'Settings saved.': 'Einstellungen gespeichert.', 'Try again': 'Erneut versuchen', 'The report is collected and sent …': 'Der Bericht wird gesammelt und gesendet …', 'A report is being collected already.': 'Es wird bereits ein Bericht gesammelt.', 'collecting …': 'wird gesammelt …', 'Target saved.': 'Ziel gespeichert.', 'Target removed.': 'Ziel entfernt.', 'SNMPDD-MIB describes the notifications (/usr/share/snmp/mibs/SNMPDD-MIB.txt); load it into the NMS.': 'SNMPDD-MIB beschreibt die Benachrichtigungen (/usr/share/snmp/mibs/SNMPDD-MIB.txt); im NMS laden.', Loading @@ -58,8 +61,18 @@ const every = s => s % 3600 === 0 ? t('{0} h', s / 3600) : s % 60 === 0 ? t('{0} min', s / 60) : t('{0} s', s); async function load() { const r = await run(() => call('snmp', 'info')); if (!r) return; let r; try { r = await call('snmp', 'info'); } catch (e) { // keep the error on the page (a toast is gone after a few seconds) if (!data) root.replaceChildren(h('section', {class: 'panel'}, h('p', {class: 'dialog-error'}, e.message), h('button', {onclick: () => { root.replaceChildren(h('p', {class: 'empty'}, t('Loading …'))); load(); }}, t('Try again')))); else toast(e.message, true); return; } data = r; draw(); } Loading Loading @@ -199,8 +212,10 @@ button.disabled = true; const r = await run(() => call('snmp', 'send')); button.disabled = false; if (r) toast(t('{0} notifications sent.', r.sent)); if (r) toast(r.started ? t('The report is collected and sent …') : t('A report is being collected already.')); load(); // collecting asks every disk: look again when it should be done setTimeout(load, 5000); } const levelText = {authPriv: 'authPriv', authNoPriv: 'authNoPriv', noAuthNoPriv: 'noAuthNoPriv'}; Loading @@ -215,7 +230,7 @@ } function draw() { const s = data.settings, st = data.status; const s = data.settings, st = data.state; const row = (label, value) => h('tr', {}, h('th', {}, label), h('td', {}, value)); const badge = name => h('span', {class: 'badge ' + (stateClass[name] || '')}, t(name || 'unknown')); const key = tg => (tg.host.includes(':') ? '[' + tg.host + ']' : tg.host) + ':' + tg.port; Loading @@ -232,7 +247,8 @@ : h('span', {class: 'badge'}, t('off'))), row(t('Last report'), when(st.lastReport)), row(t('Next report'), s.enabled ? when(st.nextReport) : '–'), row(t('Status'), st.lastReport ? badge(st.status) : '–'), row(t('Status'), st.collecting ? h('span', {class: 'badge warn'}, t('collecting …')) : st.lastReport ? badge(st.status) : '–'), st.problems.length ? row(t('Not collected'), st.problems.join('; ')) : null, row(t('Notifications sent'), String(st.sent || 0)), row(t('Enterprise OID'), h('span', {class: 'mono'}, s.enterprise || '')), Loading