broken
Harald Wolff 2019-04-05 00:59:04 +02:00
parent 9905238db5
commit c9b145482d
15 changed files with 224 additions and 30 deletions

View File

@ -12,11 +12,17 @@ using ln.types.odb;
using ln.skyscanner.entities; using ln.skyscanner.entities;
using System.IO; using System.IO;
using LiteDB; using LiteDB;
using ln.http.resources;
using System.Linq;
namespace ln.skyscanner namespace ln.skyscanner
{ {
public class SkyEntities public class SkyEntities
{ {
[Callable]
public Node[] Nodes => nodeCollection.ToArray();
public SkyScanner SkyScanner { get; } public SkyScanner SkyScanner { get; }
public string BasePath => Path.Combine(SkyScanner.BasePath, "entities"); public string BasePath => Path.Combine(SkyScanner.BasePath, "entities");

View File

@ -12,6 +12,8 @@ using ln.types.threads;
using ln.skyscanner.entities; using ln.skyscanner.entities;
using ln.logging; using ln.logging;
using Newtonsoft.Json; using Newtonsoft.Json;
using ln.types.odb;
using System.Linq;
namespace ln.skyscanner.checks namespace ln.skyscanner.checks
{ {
public class CheckJob : PoolJob public class CheckJob : PoolJob
@ -36,9 +38,18 @@ namespace ln.skyscanner.checks
if (checks[n].IsValid(Node)) if (checks[n].IsValid(Node))
{ {
Query stateQuery = Query.AND(
Query.Equals<SkyCheckState>("CheckName",checks[n].Name),
Query.Equals<SkyCheckState>("UniqueNodeIdentifier", Node.UniqueIdentity)
);
SkyCheckState checkState = SkyScanner.Instance.Checker.CheckStates.Select(stateQuery).FirstOrDefault();
try try
{ {
checks[n].Check(SkyScanner.Instance.Checker, Node); checks[n].Check(SkyScanner.Instance.Checker, ref checkState, Node);
if (checkState != null)
SkyScanner.Instance.Checker.CheckStates.Upsert(checkState);
} catch (Exception e) } catch (Exception e)
{ {
Logging.Log(e); Logging.Log(e);

View File

@ -29,7 +29,7 @@ namespace ln.skyscanner.checks
public override bool IsCritical => true; public override bool IsCritical => true;
public override bool IsValid(Node node) => node.PrimaryIP != null; public override bool IsValid(Node node) => node.PrimaryIP != null;
public override void Check(SkyChecker skyChecker, Node node) public override void Check(SkyChecker skyChecker,ref SkyCheckState checkState,Node node)
{ {
long roundTripTime = 0; long roundTripTime = 0;
int success = 0; int success = 0;

View File

@ -32,7 +32,7 @@ namespace ln.skyscanner.checks
public virtual bool IsCritical => false; public virtual bool IsCritical => false;
public abstract bool IsValid(Node node); public abstract bool IsValid(Node node);
public abstract void Check(SkyChecker skyChecker,Node node); public abstract void Check(SkyChecker skyChecker,ref SkyCheckState checkState,Node node);
static SkyCheck() static SkyCheck()

View File

@ -0,0 +1,37 @@
// /**
// * File: SkyCheckState.cs
// * Author: haraldwolff
// *
// * This file and it's content is copyrighted by the Author and / or copyright holder.
// * Any use wihtout proper permission is illegal and may lead to legal actions.
// *
// *
// **/
using System;
using ln.skyscanner.entities;
namespace ln.skyscanner.checks
{
public enum CheckState { OK, WARN, CRITICAL, FAIL, ERROR }
public class SkyCheckState
{
public readonly String CheckName;
public readonly String UniqueNodeIdentifier;
public DateTime LastCheckTime { get; set; }
public double WarnLower { get; set; } = Double.MinValue;
public double WarnUpper { get; set; } = Double.MaxValue;
public double CritLower { get; set; } = Double.MinValue;
public double CritUpper { get; set; } = Double.MaxValue;
protected SkyCheckState()
{
}
public SkyCheckState(SkyCheck skyCheck,Node node)
{
CheckName = skyCheck.Name;
UniqueNodeIdentifier = node.UniqueIdentity;
}
}
}

View File

@ -17,15 +17,20 @@ using System.Threading;
using System.Linq; using System.Linq;
using ln.logging; using ln.logging;
using ln.snmp; using ln.snmp;
using ln.http.resources;
using ln.types.odb;
namespace ln.skyscanner.checks namespace ln.skyscanner.checks
{ {
public class SkyChecker public class SkyChecker
{ {
public string BasePath { get; } public string BasePath { get; }
[Callable]
public PoolJob[] CurrentJobs => checkPool.CurrentPoolJobs; public PoolJob[] CurrentJobs => checkPool.CurrentPoolJobs;
[Callable]
public PoolJob[] QueuedJobs => checkPool.QueuedJobs; public PoolJob[] QueuedJobs => checkPool.QueuedJobs;
[Callable]
public string[] PerfNames => perfFiles.Keys.ToArray(); public string[] PerfNames => perfFiles.Keys.ToArray();
public bool ContainsPerfFile(String perfName) => perfFiles.ContainsKey(perfName); public bool ContainsPerfFile(String perfName) => perfFiles.ContainsKey(perfName);
@ -38,10 +43,20 @@ namespace ln.skyscanner.checks
bool stopping; bool stopping;
ODB odb;
public ODBCollection<SkyCheckState> CheckStates { get; private set; }
public SkyChecker() public SkyChecker()
{ {
BasePath = Path.Combine(SkyScanner.Instance.BasePath, "perfdb"); BasePath = Path.Combine(SkyScanner.Instance.BasePath, "perfdb");
SNMPEngine = new SNMPEngine(); SNMPEngine = new SNMPEngine();
SNMPEngine.Timeout = 4000;
odb = new ODB(Path.Combine(BasePath));
CheckStates = odb.GetCollection<SkyCheckState>();
CheckStates.EnsureIndex("CheckName");
CheckStates.EnsureIndex("UniqueNodeIdentifier");
} }
public void Start() public void Start()
@ -49,7 +64,7 @@ namespace ln.skyscanner.checks
if ((threadScheduler != null) && (threadScheduler.IsAlive)) if ((threadScheduler != null) && (threadScheduler.IsAlive))
throw new NotSupportedException("SkyChecker.scheduler() already running"); throw new NotSupportedException("SkyChecker.scheduler() already running");
checkPool.SetPoolSize(64); checkPool.SetPoolSize(128);
threadScheduler = new Thread(scheduler); threadScheduler = new Thread(scheduler);
threadScheduler.Start(); threadScheduler.Start();
@ -155,6 +170,8 @@ namespace ln.skyscanner.checks
} }
} catch (ThreadInterruptedException) } catch (ThreadInterruptedException)
{ {
} catch (OperationCanceledException)
{
} }
} }

View File

@ -16,8 +16,14 @@ namespace ln.skyscanner.checks
} }
public override void Check(SkyChecker skyChecker, Node node) public override void Check(SkyChecker skyChecker,ref SkyCheckState checkState,Node node)
{ {
if ((checkState == null) || !(checkState is UbiquityCheckState))
{
checkState = new UbiquityCheckState(this, node);
}
UbiquityCheckState ubiquityCheckState = checkState as UbiquityCheckState;
foreach (URI snmpUri in node.FindURIs("snmp")) foreach (URI snmpUri in node.FindURIs("snmp"))
{ {
using (SnmpInterface snmp = SnmpInterface.FromURI(snmpUri,skyChecker.SNMPEngine)) using (SnmpInterface snmp = SnmpInterface.FromURI(snmpUri,skyChecker.SNMPEngine))
@ -38,8 +44,14 @@ namespace ln.skyscanner.checks
skyChecker.WritePerfValue(this, "ptp_rx_pwr", node, (double)((Integer)(row[2].Items[1])).LongValue); skyChecker.WritePerfValue(this, "ptp_rx_pwr", node, (double)((Integer)(row[2].Items[1])).LongValue);
skyChecker.WritePerfValue(this, "ptp_tx_pwr", node, (double)((Integer)(row[3].Items[1])).LongValue); skyChecker.WritePerfValue(this, "ptp_tx_pwr", node, (double)((Integer)(row[3].Items[1])).LongValue);
skyChecker.WritePerfValue(this, "ptp_rx_rate", node, (double)((Integer)(row[4].Items[1])).LongValue); // ToDo: multiply 8 / delta T long rxBytes = ((Integer)(row[4].Items[1])).LongValue;
skyChecker.WritePerfValue(this, "ptp_tx_rate", node, (double)((Integer)(row[5].Items[1])).LongValue); // ToDo: multiply 8 / delta T long txBytes = ((Integer)(row[5].Items[1])).LongValue;
ubiquityCheckState.RXRate.Update(rxBytes * 8);
ubiquityCheckState.TXRate.Update(txBytes * 8);
skyChecker.WritePerfValue(this, "ptp_rx_rate", node, ubiquityCheckState.RXRate.Current);
skyChecker.WritePerfValue(this, "ptp_tx_rate", node, ubiquityCheckState.TXRate.Current);
} }
} }
@ -51,4 +63,20 @@ namespace ln.skyscanner.checks
return (node.Vendor != null) && node.Vendor.Equals("Ubiquity"); return (node.Vendor != null) && node.Vendor.Equals("Ubiquity");
} }
} }
class UbiquityCheckState : SkyCheckState
{
public dVdT RXRate { get; private set; }
public dVdT TXRate { get; private set; }
public UbiquityCheckState(SkyCheck skyCheck,Node node)
:base(skyCheck,node)
{
RXRate = new dVdT();
TXRate = new dVdT();
}
private UbiquityCheckState()
{ }
}
} }

View File

@ -84,7 +84,8 @@ namespace ln.skyscanner.entities
networks.Add(network); networks.Add(network);
} }
Subnet subnet = FindSubnetForIP(node.PrimaryIP); Subnet subnet = FindSubnetForIP(node.PrimaryIP);
networks.Add(subnet.Network); if (subnet != null)
networks.Add(subnet.Network);
foreach (Network4 network in networks) foreach (Network4 network in networks)
foreach (Node neighbor in FindHostsInSubnet(network)) foreach (Node neighbor in FindHostsInSubnet(network))
@ -275,7 +276,16 @@ namespace ln.skyscanner.entities
if (httpIndex.Contains("<title>RouterOS router configuration page</title>")) if (httpIndex.Contains("<title>RouterOS router configuration page</title>"))
{ {
node.Vendor = "MicroTik"; node.Vendor = "MicroTik";
} else if (httpIndex.Contains("mimosa-white-web-logo.png"))
{
node.Vendor = "Mimosa";
if (httpIndex.Contains("<title>B5c</title>"))
{
node.Product = "B5c";
}
} }
if (crawledHost.GetHint("http.server", "").Equals("Viprinet")) if (crawledHost.GetHint("http.server", "").Equals("Viprinet"))
node.Vendor = "Viprinet"; node.Vendor = "Viprinet";

View File

@ -81,10 +81,15 @@ namespace ln.skyscanner.http
PerfFile perfFile = SkyScanner.Instance.Checker.GetPerfFile(Name); PerfFile perfFile = SkyScanner.Instance.Checker.GetPerfFile(Name);
PerfValue[] perfValues = null; PerfValue[] perfValues = null;
int interval = 3600;
if (httpRequest.Query.ContainsKey("interval"))
interval = int.Parse(httpRequest.Query["interval"]);
lock (perfFile) lock (perfFile)
{ {
perfFile.EnsureOpen(); perfFile.EnsureOpen();
perfValues = perfFile.QueryTime((int)(TimeSpan.FromHours(1).TotalSeconds), 0); perfValues = perfFile.QueryTime(interval, 0);
perfFile.Close(); perfFile.Close();
} }

View File

@ -11,7 +11,8 @@ namespace ln.skyscanner.http
public String BasePath { get; private set; } public String BasePath { get; private set; }
public String TemplatesBasePath => Path.Combine(BasePath, "templates","static"); public String TemplatesBasePath => Path.Combine(BasePath, "templates","static");
ReflectiveResource refChecker;
ReflectiveResource refEntities;
public SkyScannerHttpApplication(SkyScanner skyScanner) public SkyScannerHttpApplication(SkyScanner skyScanner)
{ {
@ -26,6 +27,8 @@ namespace ln.skyscanner.http
RootResource.DefaultResource = staticTemplates; RootResource.DefaultResource = staticTemplates;
refEntities = new ReflectiveResource(RootResource, "entities", SkyScanner.Entities);
refChecker = new ReflectiveResource(RootResource, "checker", SkyScanner.Checker);
SkyScannerHttpApi api = new SkyScannerHttpApi(this); SkyScannerHttpApi api = new SkyScannerHttpApi(this);
} }

View File

@ -83,6 +83,7 @@
<Compile Include="checks\CheckJob.cs" /> <Compile Include="checks\CheckJob.cs" />
<Compile Include="http\CheckerApi.cs" /> <Compile Include="http\CheckerApi.cs" />
<Compile Include="checks\Ubiquity.cs" /> <Compile Include="checks\Ubiquity.cs" />
<Compile Include="checks\SkyCheckState.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />
@ -162,6 +163,9 @@
<None Include="templates\static\checks\index.html"> <None Include="templates\static\checks\index.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
<None Include="templates\static\checks\status.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="identify\" /> <Folder Include="identify\" />

View File

@ -4,6 +4,14 @@
<div class="flex row"> <div class="flex row">
<div> <div>
<select id="interval" style="width: 180px;">
<option value="3600">1 Stunde</option>
<option value="21600">6 Stunden</option>
<option value="43200">12 Stunden</option>
<option value="86400">1 Tag</option>
<option value="604800">1 Woche</option>
</select><br/>
<br/>
<select size="25" id="perfList"></select> <select size="25" id="perfList"></select>
</div> </div>
<div> <div>
@ -49,32 +57,35 @@
} }
} ); } );
function drawChart(perfValues)
{
}
var perfList = skyapi().getJson("api/checker/checks", function(checks){ var perfList = skyapi().getJson("api/checker/checks", function(checks){
$.each( checks, function(){ $.each( checks, function(){
$("#perfList").append( $( "<option value='"+ this +"'>" + this + "</option>" ) ); $("#perfList").append( $( "<option value='"+ this +"'>" + this + "</option>" ) );
}); });
}); });
$("#perfList").change( function(e){ function showGraph()
var perfName = $(this).children("option:selected").val(); {
skyapi().getJson("api/checker/checks/" + perfName, function(perfValues){ var perfName = $("#perfList").children("option:selected").val();
chart.data.labels.length = 0; if (perfName)
chart.data.datasets[0].data.length = 0; {
chart.data.datasets[0].label = perfName; skyapi().getJson("api/checker/checks/" + perfName + "?interval=" + $("#interval").children("option:selected").val(), function(perfValues){
$.each( perfValues, function(){ chart.data.labels.length = 0;
if (this.TimeStamp != 0) chart.data.datasets[0].data.length = 0;
{ chart.data.datasets[0].label = perfName;
//chart.data.labels.push(this.TimeStamp); $.each( perfValues, function(){
chart.data.datasets[0].data.push( { x: this.TimeStamp, y: this.Value } ); if (this.TimeStamp != 0)
}; {
chart.data.datasets[0].data.push( { x: this.TimeStamp, y: this.Value } );
};
});
chart.update();
}); });
}
}
chart.update(); $("#perfList").change( function(e){ showGraph(); } );
}); $("#interval").change( function(e){ showGraph(); } );
});
skyapi().addRefresh( showGraph, 60 );
</script> </script>

View File

@ -0,0 +1,59 @@
<%frame "frame.html"%>
<h1>Checker Status</h1>
<br/>
<div class="flex column">
<div>
<h2>Current Jobs</h2>
<div style="width: 100%;">
<table id="CurrentPoolJobs"></table>
</div>
</div>
<div>
<h2>Queued Jobs</h2>
<table id="QueuedPoolJobs"></table>
</div>
</div>
<script type="text/javascript">
var pbar = $().dataTable.render.percentBar('round','#fff', '#FF9CAB', '#FF0033', '#FF9CAB', 0, 'solid');
var dtDef = {
columns: [
{ title: "Name", data: "Name" },
{ title: "Progress", data: "Progress" },
{ title: "State", data: "State" },
{ title: "JobState", data: "JobState" }
],
columnDefs: [
{
targets: 1,
render: function(d, t, row){ d *= 100.0; return pbar(d,t,row); }
}
]
};
$("#CurrentPoolJobs").DataTable( dtDef );
$("#QueuedPoolJobs").DataTable( dtDef );
function refresh()
{
skyapi().getJson("checker/CurrentJobs", function(data){
if (!data)
data = []
$("#CurrentPoolJobs").DataTable().clear();
$("#CurrentPoolJobs").DataTable().rows.add( data ).draw();
});
skyapi().getJson("checker/QueuedJobs", function(data){
if (!data)
data = []
$("#QueuedPoolJobs").DataTable().clear();
$("#QueuedPoolJobs").DataTable().rows.add( data ).draw();
});
}
skyapi().addRefresh( refresh, 1 );
</script>

View File

@ -28,6 +28,9 @@
</div> </div>
<div> <div>
<h1>&Uuml;berwachung</h1> <h1>&Uuml;berwachung</h1>
<div>
<a href="/static/checks/status.html" onclick="skyapi().loadPage('static/checks/status.html'); return false;"><div>Status</div></a>
</div>
<div> <div>
<a href="/static/checks/index.html" onclick="skyapi().loadPage('static/checks/index.html'); return false;"><div>Checks</div></a> <a href="/static/checks/index.html" onclick="skyapi().loadPage('static/checks/index.html'); return false;"><div>Checks</div></a>
</div> </div>

View File

@ -115,7 +115,7 @@
function refreshNodeTable() function refreshNodeTable()
{ {
skyapi().call("api/network","GetNodes",[], skyapi().getJson("entities/Nodes",
function(rows){ function(rows){
$("#nodeTable").DataTable().clear().rows.add( rows ).draw(); $("#nodeTable").DataTable().clear().rows.add( rows ).draw();
}); });