diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rwxr-xr-x | collectors/snmpfetchng.pl | 43 | ||||
-rw-r--r-- | include/nms/util.pm | 31 | ||||
-rwxr-xr-x | web/api/public/dhcp-summary | 4 | ||||
-rwxr-xr-x | web/api/public/switch-state | 2 | ||||
-rwxr-xr-x | web/api/read/oplog | 7 | ||||
-rwxr-xr-x | web/api/write/fap | 19 | ||||
-rwxr-xr-x | web/api/write/networks | 3 | ||||
-rwxr-xr-x | web/api/write/switches | 3 | ||||
-rw-r--r-- | web/favicon-32x32.png | bin | 0 -> 1158 bytes | |||
-rw-r--r-- | web/favicon.ico | bin | 0 -> 15406 bytes | |||
-rw-r--r-- | web/js/nms-dhcp.js | 11 | ||||
-rw-r--r-- | web/js/nms-info-box.js | 20 | ||||
-rw-r--r-- | web/js/nms-map-handlers.js | 145 | ||||
-rw-r--r-- | web/js/nms-map.js | 27 | ||||
-rw-r--r-- | web/js/nms.js | 1 | ||||
-rw-r--r-- | web/templates/HOWTO.txt | 126 | ||||
-rw-r--r-- | web/templates/switch.txt | 19 | ||||
-rw-r--r-- | web/templates/switches.txt | 4 | ||||
-rw-r--r-- | web/templates/test.conf | 17 |
20 files changed, 239 insertions, 244 deletions
@@ -1,4 +1,5 @@ .*.swp data/ +web/templates web/templates/ web/files/ diff --git a/collectors/snmpfetchng.pl b/collectors/snmpfetchng.pl index cfa0d77..b0c1d97 100755 --- a/collectors/snmpfetchng.pl +++ b/collectors/snmpfetchng.pl @@ -28,12 +28,13 @@ $dbh->{RaiseError} = 1; my $influx = nms::influx_connect(); my $qualification = <<"EOF"; (last_updated IS NULL OR now() - last_updated > poll_frequency) -AND (locked='f' OR now() - last_updated > '15 minutes'::interval) +AND (locked='f' OR now() - last_updated > '5 minutes'::interval) AND (mgmt_v4_addr is not null or mgmt_v6_addr is not null) AND deleted = false +AND NOT tags ? 'skip-snmp-polling' EOF # Borrowed from snmpfetch.pl -our $qswitch = $dbh->prepare(<<"EOF") +our $qswitch = $dbh->prepare(<<"EOF", {pg_placeholder_dollaronly => 1}) SELECT sysname,switch,host(mgmt_v6_addr) as ip2,host(mgmt_v4_addr) as ip,community, DATE_TRUNC('second', now() - last_updated - poll_frequency) AS overdue @@ -43,7 +44,7 @@ WHERE $qualification ORDER BY overdue DESC -LIMIT ? +LIMIT \$1 EOF or die "Couldn't prepare qswitch"; our $qlock = $dbh->prepare("UPDATE switches SET locked='t', last_updated=now() WHERE switch=?") @@ -99,14 +100,19 @@ sub inner_loop my $s = SNMP::Session->new(DestHost => $switch{'mgtip'}, Community => $switch{'community'}, UseEnums => 1, + Timeout => 5000000, Version => '2'); - my $ret = $s->bulkwalk(0, 10, @nms::config::snmp_objects, sub{ callback(\%switch, @_); }); - if (!defined($ret)) { - mylog("Fudge: ". $s->{'ErrorStr'}); + if (!defined($s)) { + mylog("Fudge, no session defined. Now what?"); + } else { + my $ret = $s->bulkwalk(0, 10, @nms::config::snmp_objects, sub{ callback(\%switch, @_); }); + if (!defined($ret)) { + mylog("Fudge: ". $s->{'ErrorStr'}); + } } } mylog( "Polling " . @switches . " switches: $poll_todo"); - SNMP::MainLoop(5); + SNMP::MainLoop(10); } sub callback{ @@ -197,14 +203,20 @@ sub callback{ $tmp_field = '"'.$tree{$iid}{$key}.'"'; } - push (@influx_tree, - { - measurement => 'snmp', - tags => { - switch => $switch{'sysname'}, - }, - fields => { $key => $tmp_field }, - }); + if ($iid eq "") { + $iid = "0"; + } + if ($key ne "entPhysicalFirmwareRev" && $key ne "entPhysicalHardwareRev" && $key ne "entPhysicalSerialNum") { + push (@influx_tree, + { + measurement => 'snmp', + tags => { + switch => $switch{'sysname'}, + idd => $iid + }, + fields => { $key => $tmp_field }, + }); + } } } if ($total > 0) { @@ -230,6 +242,7 @@ sub callback{ on_success => $cv, on_error => sub { $cv->croak("Failed to write data: @_"); + # warn "Failed to write data: @_"; } ); $cv->recv; diff --git a/include/nms/util.pm b/include/nms/util.pm index 69f5392..e30c0b6 100644 --- a/include/nms/util.pm +++ b/include/nms/util.pm @@ -130,7 +130,10 @@ sub guess_placement_tg { my ($e, $s) = ($1, $2); $src = "main"; - $x = int(292 + (($e-1)/2) * 31.1); + $x = int(572 + (($e-1)/2) * 31.1); + if (($e-1/2)>9) { + $x += 140; + } $y = undef; $x += 14 if ($e >= 21); @@ -148,15 +151,16 @@ sub guess_placement_tg { $yy = $y + 120; # Justeringer - $y += 45 if $name eq "e1-4"; - $y += 20 if $name eq "e3-4"; - $y += 15 if $name eq "e5-4"; - $yy -= 25 if $name eq "e7-1"; - $yy -= 25 if $name eq "e5-1"; - $yy -= 25 if $name eq "e3-1"; - $y += 20 if ($e >= 79 and $s == 2); - $yy -= 20 if ($e >= 79 and $s == 1); - $yy -= 30 if ($e >= 81 and $s == 1); + + # $y += 45 if $name eq "e1-4"; + #$y += 20 if $name eq "e3-4"; + #$y += 15 if $name eq "e5-4"; + #$yy -= 25 if $name eq "e7-1"; + #$yy -= 25 if $name eq "e5-1"; + #$yy -= 25 if $name eq "e3-1"; + #$y += 20 if ($e >= 79 and $s == 2); + #$yy -= 20 if ($e >= 79 and $s == 1); + #$yy -= 30 if ($e >= 81 and $s == 1); } elsif ($name =~ /^creativia(\d+)$/) { my ($s) = ($1); @@ -181,11 +185,14 @@ sub guess_placement_tg { $y = int(759 + 20.5 * $s); $xx = $x + 65; $yy = $y + 14; - } elsif ($name =~ /^s(\d).floor/) { + } elsif ($name =~ /^d(\d).floor/) { my $d = ($1); $src = "distro"; $d -= 1; - $x = 260 + $d * 145; + $x = 438 + $d * 145; + if ($d > 1) { + $x += 230; + } $y = 417; $xx = $x + 130; $yy = $y + 20; diff --git a/web/api/public/dhcp-summary b/web/api/public/dhcp-summary index 5245f34..beed463 100755 --- a/web/api/public/dhcp-summary +++ b/web/api/public/dhcp-summary @@ -6,10 +6,10 @@ use nms::web; nms::web::setwhen('2h'); -my $q2 = $nms::web::dbh->prepare("select count(distinct data->>'clientmac') as clients from metrics where $nms::web::when;"); +my $q2 = $nms::web::dbh->prepare("select count(DISTINCT data ->> 'clientip') as clients, family(inet (data ->> 'clientip')) as family from metrics where $nms::web::when GROUP by family;"); $q2->execute(); while (my $ref = $q2->fetchrow_hashref()) { - $nms::web::json{'dhcp'} = $ref; + $nms::web::json{'dhcp'}{$ref->{'family'}} = $ref->{'clients'}; } $nms::web::cc{'max-age'} = "10"; $nms::web::cc{'stale-while-revalidate'} = "15"; diff --git a/web/api/public/switch-state b/web/api/public/switch-state index d192504..2aff40c 100755 --- a/web/api/public/switch-state +++ b/web/api/public/switch-state @@ -80,7 +80,7 @@ while ( my $ref = $q->fetchrow_hashref() ) { $json{'switches'}{$sysname}{vcp}{jnxVirtualChassisPortInOctets} = $data{'vcp'}{'jnxVirtualChassisPortInOctets'}; $json{'switches'}{$sysname}{vcp}{jnxVirtualChassisPortOutOctets} = $data{'vcp'}{'jnxVirtualChassisPortOutOctets'}; - $json{'switches'}{$sysname}{'temp'} = $data{'misc'}{'jnxOperatingTemp'}{'7.1.0.0'} || $data{'misc'}{'ciscoEnvMonTemperatureStatusValue'}{'1011'} || $data{'misc'}{'ciscoEnvMonTemperatureStatusValue'}{'1008'}; + $json{'switches'}{$sysname}{'temp'} = $data{'misc'}{'jnxOperatingTemp'}{'7.1.0.0'} || $data{'misc'}{'jnxOperatingTemp'}{'7.1.0.0'} || $data{'misc'}{'jnxOperatingTemp'}{'7.2.0.0'} || $data{'misc'}{'jnxOperatingTemp'}{'7.3.0.0'} || $data{'misc'}{'jnxOperatingTemp'}{'7.4.0.0'} || $data{'misc'}{'jnxOperatingTemp'}{'7.5.0.0'} || $data{'misc'}{'jnxOperatingTemp'}{'7.6.0.0'} || $data{'misc'}{'ciscoEnvMonTemperatureStatusValue'}{'1011'} || $data{'misc'}{'ciscoEnvMonTemperatureStatusValue'}{'1008'}; $json{'switches'}{$sysname}{'time'} = $ref->{'time'}; } diff --git a/web/api/read/oplog b/web/api/read/oplog index 88a7616..22e21ac 100755 --- a/web/api/read/oplog +++ b/web/api/read/oplog @@ -17,9 +17,12 @@ my $query = $nms::web::dbh->prepare('select id,date_trunc(\'second\',time) as ti $query->execute(); while (my $ref = $query->fetchrow_hashref()) { my %meh; + if (!defined($ref->{'log'})) { + next; + } $meh{'time'} = $ref->{'h'} . ":" . $ref->{'m'}; - $meh{'log'} = $ref->{'log'}; - $meh{'username'} = $ref->{'username'}; + $meh{'log'} = $ref->{'log'} || "weird?"; + $meh{'username'} = $ref->{'username'} || "undefined"; $meh{'id'} = $ref->{'id'}; $meh{'systems'} = $ref->{'systems'}; $meh{'timestamp'} = $ref->{'timestamp'}; diff --git a/web/api/write/fap b/web/api/write/fap new file mode 100755 index 0000000..1211349 --- /dev/null +++ b/web/api/write/fap @@ -0,0 +1,19 @@ +#!/bin/bash + +fil=/var/log/apache2/kek +echo 'Content-Type: text/html' +echo +echo +pw="<redacted>" +sw=$(echo $PATH_INFO | sed 's/^\///') +POST -H'Content-Type: application/json' https://gondul:${pw}@awx.tg23.gathering.org/api/v2/job_templates/19/launch/ >/dev/null 2>&1 <<_EOF_ +{"credential_passwords":{},"limit":"$sw","extra_vars":{}} +_EOF_ +ret=$? +./oplog >/dev/null 2>&1 <<_EOF_ +{"systems": "$sw", "log": "Refap queued in AWX for $sw"} +_EOF_ +while read; do + true +done +echo '"ok"' diff --git a/web/api/write/networks b/web/api/write/networks index 8a95af7..a4a8868 100755 --- a/web/api/write/networks +++ b/web/api/write/networks @@ -55,6 +55,9 @@ foreach my $tmp2 (@tmp) { if ($template{'gw6'} eq 'DEFAULT' and $template{'subnet6'} ne 'DEFAULT') { $template{'gw6'} = "host(inet $template{'subnet6'} + 1)"; } + if (defined($network{'tags'})) { + $template{'tags'} = "'[". join(",", map { "\"".$_."\"" } @{$network{'tags'}})."]'"; + } $nms::web::dbh->do("INSERT INTO NETWORKS (name, subnet4, subnet6, router, gw4, gw6, vlan, tags) VALUES ($template{'name'}, $template{'subnet4'}, $template{'subnet6'}, $template{'router'}, $template{'gw4'}, $template{'gw6'}, $template{'vlan'}, $template{'tags'});"); push @added, $network{'name'}; } else { diff --git a/web/api/write/switches b/web/api/write/switches index e0ee950..470cde1 100755 --- a/web/api/write/switches +++ b/web/api/write/switches @@ -23,7 +23,6 @@ my @dups; my $sth = $nms::web::dbh->prepare("SELECT sysname FROM switches WHERE sysname=?"); - my @fields = ( 'community', 'tags', 'distro_name', 'distro_phy_port', 'mgmt_v4_addr', 'mgmt_v6_addr', 'mgmt_vlan', 'placement', 'poll_frequency', 'sysname', 'traffic_vlan', 'deleted'); sub convertplace @@ -112,7 +111,7 @@ foreach my $tmp2 (@tmp) { push @set, "$_=" . $dbh->quote($switch{$_}); } } keys %switch; - $nms::web::dbh->do("UPDATE SWITCHES SET " . join(", ", @set) . "WHERE sysname=" . $dbh->quote($switch{'sysname'}) . ";"); + $nms::web::dbh->do("UPDATE SWITCHES SET " . join(", ", @set) . " WHERE sysname=" . $dbh->quote($switch{'sysname'}) . ";"); push @dups, $switch{'sysname'}; } } diff --git a/web/favicon-32x32.png b/web/favicon-32x32.png Binary files differnew file mode 100644 index 0000000..a591b6a --- /dev/null +++ b/web/favicon-32x32.png diff --git a/web/favicon.ico b/web/favicon.ico Binary files differnew file mode 100644 index 0000000..47dbd21 --- /dev/null +++ b/web/favicon.ico diff --git a/web/js/nms-dhcp.js b/web/js/nms-dhcp.js index b852a45..dd2e96d 100644 --- a/web/js/nms-dhcp.js +++ b/web/js/nms-dhcp.js @@ -13,5 +13,14 @@ nmsDhcp.updateSummary = function() { if (e == undefined) { return; } - e.innerHTML = nmsData.dhcpsummary.dhcp.clients + " clients"; + e.innerHTML = ""; + if(nmsData.dhcpsummary.dhcp[4] != undefined){ + e.innerHTML = e.innerHTML + nmsData.dhcpsummary.dhcp[4] + " IPv4 clients"; + } + if(nmsData.dhcpsummary.dhcp[4] != undefined && nmsData.dhcpsummary.dhcp[6] != undefined){ + e.innerHTML = e.innerHTML + " | "; + } + if(nmsData.dhcpsummary.dhcp[6] != undefined){ + e.innerHTML = e.innerHTML + nmsData.dhcpsummary.dhcp[6] + " IPv6 clients"; + } } diff --git a/web/js/nms-info-box.js b/web/js/nms-info-box.js index 2e3eb06..1a15e6c 100644 --- a/web/js/nms-info-box.js +++ b/web/js/nms-info-box.js @@ -938,6 +938,10 @@ nmsInfoBox.setLegendPick = function(tag,id) { nmsInfoBox.addPanelType("switchSummary",switchSummaryPanel); +var copybuttonfunc = function(text) { + console.log('clickened', text); + navigator.clipboard.writeText(text); +} var switchLinks = function() { nmsInfoPanel.call(this,"switchLinks"); var latencyChart; @@ -954,18 +958,30 @@ var switchLinks = function() { var topp = document.createElement("div") var urls = [ "http://gondul.tg23.gathering.org/api/templates/magic.conf/switch=" + sw, - "http://185.110.149.4/api/templates/magic.conf/switch=" + sw ]; + "http://185.110.148.105/api/templates/magic.conf/switch=" + sw, + "http://gondul.tg23.gathering.org/api/write/fap/" + sw + ]; if (testTree(nmsData,['smanagement','switches',sw])) { var mg = nmsData["smanagement"]["switches"][sw]; urls.push("ssh://[" + mg.mgmt_v6_addr + "]"); urls.push("ssh://" + mg.mgmt_v4_addr); } for (var x in urls) { + console.log("create link") topp.appendChild(document.createElement("br")); + var container = document.createElement("div"); var link = document.createElement("a"); link.href = urls[x]; link.textContent = urls[x]; - topp.appendChild(link); + var copybutton = document.createElement("button"); + copybutton.setAttribute("onclick", "copybuttonfunc('"+urls[x]+"')"); + copybutton.type = "button"; + var btnText = document.createTextNode("copy url"); + copybutton.className = "btn btn-primary"; + copybutton.appendChild(btnText); + container.appendChild(link); + container.appendChild(copybutton); + topp.appendChild(container); } this._render(topp); }; diff --git a/web/js/nms-map-handlers.js b/web/js/nms-map-handlers.js index 03ee2ea..0097586 100644 --- a/web/js/nms-map-handlers.js +++ b/web/js/nms-map-handlers.js @@ -200,7 +200,7 @@ function uplinkInfo(sw) var tu = parseInt(nmsData.switchstate.switches[sw].clients.live); var tt = parseInt(nmsData.switchstate.switches[sw].clients.total); ret.data[1] = {}; - ret.data[1].value = (tu && tt) ? (tu) + " / " + (tt) : "None configured"; + ret.data[1].value = tt ? (tu) + " / " + (tt) : "None configured"; ret.data[1].description = "Client ports (live/total)"; } if (testTree(nmsData,['switchstate','switches',sw,'totals','live'])) { @@ -432,6 +432,36 @@ function pingUpdater() } } } +function printDiff(t) +{ + var str = ""; + if (t.d > 1) + str = t.d + " days"; + else if (t.d == 1) + str = t.d + " day"; + + if (t.h > 1) + str += " " + t.h + " hours"; + else if (t.h == 1) + str += " " + t.h + " hour"; + else if (t.d > 0) + str += " 0 hours"; + + if (t.m > 1) + str += " " + t.m + " minutes"; + else if (t.m == 1) + str += " " + t.m + " minute"; + else if (t.d > 0 || t.h > 0) + str += " 0 minutes"; + + if (t.s > 1) + str += " " + t.s + " seconds"; + else if (t.s == 1) + str += " " + t.s + " second"; + else if (t.d > 0 || t.h > 0 || t.m > 0) + str += " 0 seconds"; + return str; +} function pingInfo(sw) { @@ -445,11 +475,8 @@ function pingInfo(sw) v4 = undefined; if (v6 == undefined || v6 == null || isNaN(v6)) v6 = undefined; - ret.data[0].value = v4; - ret.data[0].description = "IPv4 latency(ms)"; - ret.data[1] = {}; - ret.data[1].value = v6; - ret.data[1].description = "IPv6 latency(ms)"; + ret.data[0].value = v6 + " (v4: " + v4 + " )"; + ret.data[0].description = "Latency(ms)"; if (v4 == undefined && v6 == undefined) { ret.score = 1000; ret.why = "No IPv4 or IPv6 ping reply"; @@ -485,6 +512,9 @@ function pingInfo(sw) var distro = nmsData['smanagement']['switches'][sw]['distro_name']; var phy = nmsData['smanagement']['switches'][sw]['distro_phy_port']; if (!(distro == "" || phy == "" || distro == undefined || phy == undefined)) { + ret.data[3] = {}; + ret.data[3].description = "Distro-port"; + ret.data[3].value = distro + " " + phy; if (testTree(nmsData,['snmp','snmp',distro, 'ports',phy,'ifOperStatus'])) { var x = nmsData['snmp']['snmp'][distro]['ports'][phy]['ifOperStatus']; var ping = "no"; @@ -494,13 +524,30 @@ function pingInfo(sw) ping6 = parseFloat(nmsData["ping"]["switches"][sw]["latency6"]); } catch(e) {} if (x == "up") { - ret.data[3] = {}; - ret.data[3].description = "Distro-port"; - ret.data[3].value = "Distro port is live"; + ret.data[3].value += " (😇 up!)"; if (isNaN(ping) && isNaN(ping6)) { ret.score = 700; - ret.why = "Distro port is alive, but no IPv4/IPv6 ping. ROLLBACK!"; + ret.why = "Distro port is alive, but no IPv4/IPv6 ping."; + if (testTree(nmsData,['snmp','snmp',distro, 'ports',phy,'ifLastChange'])) { + if (testTree(nmsData,['snmp','snmp',distro, 'misc','sysUpTimeInstance'])) { + ret.data[4] = {}; + ret.data[4].description = 'Distro port changed'; + diff = (parseInt(nmsData['snmp']['snmp'][distro]['misc']['sysUpTimeInstance']['']) - parseInt(nmsData['snmp']['snmp'][distro]['ports'][phy]['ifLastChange'])) / 100; + var diff2 = { + d:parseInt((diff/60/60/24)), + h:parseInt((diff/60/60)%24), + m:parseInt((diff/60)%60), + s:parseInt(diff%60) + } + + + + ret.data[4].value = printDiff(diff2); + } + } } + } else { + ret.data[3].value += " (👺down)"; } } } @@ -545,7 +592,7 @@ function dhcpUpdater() var c = nmsColor.blue; var sv4 = nmsData.dhcp.dhcp4[nmsData.smanagement.switches[sw].traffic_vlan]; var sv6 = nmsData.dhcp.dhcp6[nmsData.smanagement.switches[sw].traffic_vlan]; - if (sv4 == undefined || sv6 == undefined) { + if (sv4 == undefined && sv6 == undefined) { nmsMap.setSwitchColor(sw,c); continue; } @@ -580,7 +627,7 @@ function dhcpInfo(sw) { var now = nmsData.dhcp.time; var then = nmsData.dhcp.dhcp4[nmsData.smanagement.switches[sw].traffic_vlan]; var diff = now - then; - var divider = 6; + var divider = 10; if (dhcpClients < 10) { divider = 12; } @@ -616,7 +663,7 @@ function dhcpInfo(sw) { var now = nmsData.dhcp.time; var then = nmsData.dhcp.dhcp6[nmsData.smanagement.switches[sw].traffic_vlan]; var diff = now - then; - var divider = 6; + var divider = 10; if (dhcpClients < 10) { divider = 12; } @@ -752,7 +799,12 @@ function secondsToTime(input) { function snmpInfo(sw) { var ret = new handlerInfo("snmp","SNMP data"); ret.why = "No SNMP data"; - if (!testTree(nmsData,['snmp','snmp',sw,'misc'])) { + if (tagged(sw,'ignore-snmp')) { + ret.score = 0; + ret.why += "(Ignored)"; + ret.data[0].value += "(Ignored)"; + } + else if (!testTree(nmsData,['snmp','snmp',sw,'misc'])) { ret.score = 500; ret.why = "No SNMP data"; ret.data[0].value = "No data"; @@ -787,6 +839,15 @@ function snmpInfo(sw) { ret.why = "System rebooted last 15 minutes"; } } + if (testTree(nmsData,['snmp','snmp',sw,'misc','sysDescr','0'])) { + ret.data[1].description = "Description"; + lol = nmsData['snmp']['snmp'][sw]['misc']['sysDescr']['0']; + re1 = /Juniper Networks, Inc./ + re2 = /, Build date.*$/ + lol = lol.replace(re1,"") + lol = lol.replace(re2,"") + ret.data[1].value = lol + } return ret; } @@ -846,11 +907,11 @@ function cpuInfo(sw) { var local = nmsData.snmp.snmp[sw].misc['jnxOperatingCPU'][u]; cpu = Math.max(nmsData.snmp.snmp[sw].misc.jnxOperatingCPU[u],cpu); } - if (cpu < 30) { + if (cpu < 40) { ret.score = 0; } else if (cpu < 50) { ret.score = 100; - } else if (cpu < 70 ) { + } else if (cpu < 85 ) { ret.score = cpu * 3; } else { ret.score = cpu * 7; @@ -958,30 +1019,18 @@ function networkInfo(sw) { } ret.data[i++] = { - value: a.v.name || "Not set", + value: (a.v.name || "Not set") + " " + "vlan: " + (a.v.vlan || "Not set"), description: a.d + " network" } - ret.data[i++] = { - value: a.v.vlan || "Not set", - description: a.d + " vlan" - } ret.data[i++] = { value: a.v.subnet4 || "Not set", description: a.d + " subnet IPv4" } ret.data[i++] = { - value: a.v.gw4 || "Not set", - description: a.d + " gw IPv4" - } - ret.data[i++] = { value: a.v.subnet6 || "Not set", description: a.d + " subnet IPv6" } ret.data[i++] = { - value: a.v.gw6 || "Not set", - description: a.d + " gw IPv6" - } - ret.data[i++] = { value: a.v.router || "Not set", description: a.d + " net router" } @@ -997,14 +1046,8 @@ function mgmtInfo(sw) { var mg = nmsData.smanagement.switches[sw]; ret.data = [{ - value: mg.mgmt_v4_addr || "N/A", - description: "Management IP (v4)" - }, { - value: mg.mgmt_v6_addr || "N/A", - description: "Management IP (v6)" - }, { - value: mg.distro_name || "N/A", - description: "Distro" + value: (mg.mgmt_v4_addr || "N/A") + " / " + (mg.mgmt_v6_addr || "N/A"), + description: "Management IP" } ]; if ((mg.mgmt_v4_addr == undefined || mg.mgmt_v4_addr == "") && (mg.mgmt_v6_addr == undefined || mg.mgmt_v6_addr == "")) { @@ -1015,7 +1058,7 @@ function mgmtInfo(sw) { ret.score = 550; } else if (mg.mgmt_v6_addr == undefined || mg.mgmt_v6_addr == "") { ret.why = "No IPv6 management IP"; - ret.score = 550; + ret.score = 560; if (tagged(sw,'ignorev6')) { ret.score = 0; } @@ -1027,6 +1070,10 @@ function mgmtInfo(sw) { ret.data[0].value = "N/A"; ret.data[0].description = "Management info"; }; + if (tagged(sw,'maint')) { + ret.score = 1337; + ret.why = "Maintenance mode: maint tag"; + } return ret; } @@ -1076,12 +1123,32 @@ function healthInfo(sw) { return worst; } +var nmsBlink = [] function healthUpdater() { if (nmsData.switches == undefined || nmsData.switches.switches == undefined) return; for (var sw in nmsData.switches.switches) { var worst = healthInfo(sw); - nmsMap.setSwitchColor(sw, nmsColor.getColorStop(worst.score)); + color = nmsColor.getColorStop(worst.score); + // maint + if (worst.score == 1337) { + nmsMap.setSwitchColor(sw, "#89cff0"); + nmsMap.setSwitchInfo(sw, "maint"); + continue; + } + rigge = true; + // blinkenlights + if (rigge == false && worst.score > 650) { + if (nmsBlink[sw] == true) { + nmsMap.setSwitchColor(sw, "rebeccapurple"); + nmsBlink[sw] = false; + } else { + nmsMap.setSwitchColor(sw, nmsColor.getColorStop(worst.score)); + nmsBlink[sw] = true; + } + } else { + nmsMap.setSwitchColor(sw, nmsColor.getColorStop(worst.score)); + } if (worst.score > 200) nmsMap.setSwitchInfo(sw, worst.tag); else { diff --git a/web/js/nms-map.js b/web/js/nms-map.js index d5bc044..bd88d1d 100644 --- a/web/js/nms-map.js +++ b/web/js/nms-map.js @@ -72,6 +72,12 @@ nmsMap.init = function() { }; nmsMap.setSwitchColor = function(sw, color) { + /* + * NEED TO LOCATE? YAS. + if (nmsData.switches.switches[sw] && nmsData.switches.switches[sw].tags.includes("locating") && this._color[sw] != "purple") { + color = "purple"; + } + */ if (this._color[sw] != color) { this._color[sw] = color; this._drawSwitch(sw); @@ -333,8 +339,21 @@ nmsMap._drawSwitch = function(sw) this._c.switch.ctx.shadowBlur = 0; var switchtext = sw; var textl = switchtext.length; - if (textl > 12) - switchtext = switchtext.slice(0,7) + ".." + switchtext.slice(textl-2,textl); + // Cut switch name if longer than this + var text_cut_l = 14; + // Cut switch name by more if we have a status indicator + if (this._info[sw]) { + text_cut_l -= this._info[sw].length + } + if (textl > text_cut_l) { + var rhs_text = this._info[sw]; + + switchtext = switchtext.slice(0,text_cut_l - 5) + ".." + switchtext.slice(textl-2,textl); + } + // Don't display AP name + if (switchtext[0] == "a" && switchtext[1] == "p") { + switchtext = "ap"; + } if (this._lastName[sw] != switchtext) { nmsMap.stats.textSwitchDraws++; @@ -350,6 +369,10 @@ nmsMap._drawSwitchInfo = function(sw) { var box = this._getBox(sw); if (this._lastInfo[sw] == this._info[sw]) return; + // Skip info on APs + if (sw[0] == "a" && sw[1] == "p") { + return; + } this._clearBox(this._c.textInfo.ctx, box, 3); nmsMap.stats.textInfoClears++; if (this._info[sw] != undefined) { diff --git a/web/js/nms.js b/web/js/nms.js index 5012bff..f0b82a7 100644 --- a/web/js/nms.js +++ b/web/js/nms.js @@ -75,6 +75,7 @@ var nms = { '7':setMapModeFromN, '8':setMapModeFromN, '9':setMapModeFromN, + '0':setMapModeFromN, 'c':toggleConnect, 'H':moveTimeFromKey, 'h':moveTimeFromKey, diff --git a/web/templates/HOWTO.txt b/web/templates/HOWTO.txt deleted file mode 100644 index 641878e..0000000 --- a/web/templates/HOWTO.txt +++ /dev/null @@ -1,126 +0,0 @@ -How to use Gondul templating -============================ - -We utilize Jinja2 templates. - -{# - This is a jinja2 comment! --#} - -{% set url = "localhost" -%} -{% set example_switch = "r1.tele" -%} - -See http://jinja.pocoo.org/ for the full documentation of the templating -language. - -The rest of this document is about templating as it relates to Gondul - -Neat: This document is an actual template, so the examples are working -examples. The best place to view this HOWTO is in the Gondul GUI, where you -get a side-by-side comparison of the template and the rendered result. - -URLs -==== - -To read raw (unprocessed) templates, see http://{{ url }}/templates - -To see the rendered final result, see http://{{ url }}/api/templates - -Otherwise, use the Template-tab at http://{{ url }}/ - -Basics -====== - -Gondul provides templating through two different, but similar mechanisms. - -First, there are permanent templates, or server-side templates. These are -templates stored on the server and accessible by all Tech crew/equipment. - -These are fetched typically through a HTTP GET request. E.g.: - -http://{{ url }}/api/templates/switches.txt - -Secondly, you can write templates yourself and POST them to Gondul. This is -highly useful for one-off templates or template development. The syntax is -the same. - -Simply write a template-file and POST it with your favorite command-line -tool to: - -http://{{ url }}/api/templates/WHATEVER - -Example: - -POST http://{{ url }}nms/api/templates/foobar < my-local-template - -Available objects -================= - -Gondul templates have two dictionaries available for general use. The first -is "options". This is a simple list of GET parameters. If you access -http://{{ url }}/api/templates/HOWTO.txt?foo=bar, options[foo] will evaluate to -"bar" in that template. This can be accessed in the template as: - -Foo: {{ options["foo"] }} - -The second object is the "objects" ... dictionary. This is a list of all -the HTTP API end-points, in all their glory. The key is the URL. - -To use this, you need to review the relevant endpoint. This is best done by -reading the API documentation (or skimming through other templates). If you -want to acces e13-2's latency, for example, you can access -objects["public/ping"].switches["{{ example_switch }}"].latency4 - -As such: {{ objects["public/ping"].switches[example_switch].latency4 }} - -The logic is that "public/ping" is the url: http://{{ url }}/api/public/ping, it -contains JSON that begins with "switches", a list of all switches, each -switch as a "latency4" object (among other things) - -Other worth-while api-endpoints: - -- read/switch-management - Management information -- public/switches - All switches -- read/snmp - All SNMP data - -Filters -======= - -Jinja2 uses a number of filters to transform variables. They can be used to -do anything from upper-case all text to pretty-print JSON objects. They are -used by piping a variable. For example: options|pprint . This will "pretty -print" the options-object: - -{{ options|pprint }} - -See http://jinja.pocoo.org/docs/dev/templates/#builtin-filters for a list -of available filters. - -Loops -===== - -You can easily loop over objects, such as switches, using a for-loop. -Combine this with the "dictsort" filter to get a sorted list. - -{% for switch in objects["public/switches"].switches|dictsort %} - Switch {{ loop.index }} is {{ switch[0] }} or {{ switch[1] }} or full version: {{ switch }} -{% endfor %} - -To avoid having to worry about indices of tuples (e.g.: switch[0]), you can -also use a simpler style: - -{% for key, value in objects["public/ping"].switches|dictsort %} - Switch {{ loop.index }} is {{ key}} with latency4 of {{ value.latency4 }}ms -{% endfor %} - -Work flow -========= - -Recommended: - -1. Read some other template with relevant data. -2. Open the API endpoints in your browser to review the data structure -3. Use query-parameters to provide user-selection (e.g.: ?switch=foobar) -4. Write your template on your local machine, test frequently by POST'ing it -5. When done: Ask us and we'll upload it server-side - diff --git a/web/templates/switch.txt b/web/templates/switch.txt deleted file mode 100644 index 0fd9754..0000000 --- a/web/templates/switch.txt +++ /dev/null @@ -1,19 +0,0 @@ -{# - This can be used through GET /templating/switch.txt?switch=e41-2 - - It is provided as a simple demo of how to combine "GET parameters" with - templating. - - #} -{% set sw = options["switch"] %} -{% set s = objects["public/switches"].switches[sw] %} -{% if s %} -{% set mg = objects["read/switches-management"].switches[sw] %} - -Switch {{ sw }} has management ip {{ mg.mgmt_v4_addr }} - -It is assoicated with distro {{ s.distro_name }} -{% else %} -Switch not found -{% endif %} - diff --git a/web/templates/switches.txt b/web/templates/switches.txt deleted file mode 100644 index b710066..0000000 --- a/web/templates/switches.txt +++ /dev/null @@ -1,4 +0,0 @@ -{% for (switch, s) in objects["public/switches"].switches|dictsort %} - {% set mg = objects["read/switches-management"].switches[switch] -%} - {{ switch }} {{mg.subnet4 }} {{ mg.subnet6 }} {{ mg.mgmt_v4_addr }} {{ mg.mgmt_v6_addr }} {{ mg.traffic_vlan }} {{ s.distro_name }} -{% endfor %} diff --git a/web/templates/test.conf b/web/templates/test.conf deleted file mode 100644 index ce2fe0d..0000000 --- a/web/templates/test.conf +++ /dev/null @@ -1,17 +0,0 @@ -{# Fetches something simple from gondul #} -{# Query parameters: ?switch=e1-1 #} - -{# Check if ?switch option is given#} -{% if not options["switch"] %} - {# pretty print public/switches endpoint#} - {{ objects["public/switches"] | pprint }} -{% else %} - {# sets sw variable using the query parameter #} - {% set sw = options["switch"] %} -{% endif %} -{% if sw %} - {# find the correct switch from public/switches api endpoint using query paramter#} - {% set switch = objects["public/switches"].switches[sw] %} - {# pretty print info in api #} - {{ switch | tojson }} -{% endif %} |