diff --git a/Program.cs b/Program.cs index 3b70788..d6d2b07 100644 --- a/Program.cs +++ b/Program.cs @@ -46,7 +46,7 @@ namespace ln.skyscanner Console.WriteLine("Core Node (alt): {0}", coreNode2); Query nodeByIpQuery = Query.Equals("Interfaces[].ConfiguredIPs[].IP", IPv4.Parse("10.255.7.129")); - IEnumerable qnodes = skyScanner.Entities.nodeCollection.Select(nodeByIpQuery); + IEnumerable qnodes = skyScanner.Entities.nodeCollection.Query(nodeByIpQuery); IEnumerable neighbors = skyScanner.Entities.GlobalNetwork.FindNeighbors(coreNode); diff --git a/SkyEntities.cs b/SkyEntities.cs index 9080e1d..7a89996 100644 --- a/SkyEntities.cs +++ b/SkyEntities.cs @@ -13,6 +13,7 @@ using ln.skyscanner.entities; using System.IO; using ln.http.resources; using System.Linq; +using ln.types.odb.mapped; namespace ln.skyscanner { @@ -21,7 +22,6 @@ namespace ln.skyscanner [Callable] public Node[] Nodes => nodeCollection.ToArray(); - public SkyScanner SkyScanner { get; } public string BasePath => Path.Combine(SkyScanner.BasePath, "entities"); @@ -31,6 +31,7 @@ namespace ln.skyscanner //public ODBCollection interfaceCollection { get; private set; } //public ODBCollection intfIPCollection { get; private set; } public ODBCollection subnetCollection { get; private set; } + public ODBCollection popCollection { get; private set; } public SkyEntities(SkyScanner skyScanner) { @@ -43,9 +44,14 @@ namespace ln.skyscanner nodeCollection.EnsureIndex("PrimaryIP"); nodeCollection.EnsureIndex("Interfaces[].ConfiguredIPs[].IP"); nodeCollection.EnsureIndex("Interfaces[].ConfiguredIPs[].Network"); + nodeCollection.EnsureIndex("uniqueIdentity"); subnetCollection.EnsureIndex("Network"); + popCollection = odDatabase.GetCollection(); + popCollection.EnsureIndex("ForeignName"); + popCollection.EnsureIndex("nodeIDList[]"); + GlobalNetwork = new GlobalNetwork(this); } diff --git a/checks/CheckJob.cs b/checks/CheckJob.cs index 819dbdd..5adfac5 100644 --- a/checks/CheckJob.cs +++ b/checks/CheckJob.cs @@ -30,7 +30,7 @@ namespace ln.skyscanner.checks Node = node; Query stateQuery = Query.Equals("UniqueNodeIdentifier", Node.UniqueIdentity); - SkyCheckState[] skyCheckStates = SkyScanner.Instance.Checker.checkStates.Select(stateQuery).ToArray(); + SkyCheckState[] skyCheckStates = SkyScanner.Instance.Checker.checkStates.Query(stateQuery).ToArray(); foreach (SkyCheckState checkState in skyCheckStates) { checkStates.Add(checkState.CheckName, checkState); diff --git a/checks/SkyCheckState.cs b/checks/SkyCheckState.cs index 3b2f9e8..07feade 100644 --- a/checks/SkyCheckState.cs +++ b/checks/SkyCheckState.cs @@ -12,6 +12,8 @@ using ln.skyscanner.entities; using ln.types.odb; using Newtonsoft.Json; using Newtonsoft.Json.Converters; +using System.Linq; +using ln.types.odb.attributes; namespace ln.skyscanner.checks { [JsonConverter(typeof(StringEnumConverter))] @@ -25,6 +27,9 @@ namespace ln.skyscanner.checks public readonly String CheckName; public readonly String UniqueNodeIdentifier; + [ByReference] + public Node Node; + public DateTime LastCheckTime { get; set; } public double WarnLower { get; set; } = Double.MinValue; diff --git a/checks/SkyChecker.cs b/checks/SkyChecker.cs index fb43e8a..6609866 100644 --- a/checks/SkyChecker.cs +++ b/checks/SkyChecker.cs @@ -20,6 +20,7 @@ using ln.snmp; using ln.http.resources; using ln.types.odb; using System.Collections.Generic; +using ln.types.odb.mapped; namespace ln.skyscanner.checks { public class SkyChecker diff --git a/crawl/CrawledHost.cs b/crawl/CrawledHost.cs index a127147..1fce7dd 100644 --- a/crawl/CrawledHost.cs +++ b/crawl/CrawledHost.cs @@ -15,6 +15,7 @@ using System.Linq; using ln.snmp.rfc1213; using ln.types.odb; using ln.types.net; +using ln.types.odb.attributes; namespace ln.skyscanner.crawl { diff --git a/crawl/CrawledSubnet.cs b/crawl/CrawledSubnet.cs index 9de64c7..64b2f5a 100644 --- a/crawl/CrawledSubnet.cs +++ b/crawl/CrawledSubnet.cs @@ -13,6 +13,7 @@ using ln.types.odb; using System.Collections.Generic; using System.Linq; using ln.types.net; +using ln.types.odb.attributes; namespace ln.skyscanner.crawl { public class CrawledSubnet diff --git a/crawl/Crawler.cs b/crawl/Crawler.cs index 67d0c2a..d6a22cd 100644 --- a/crawl/Crawler.cs +++ b/crawl/Crawler.cs @@ -21,6 +21,7 @@ using ln.types.odb; using ln.skyscanner.crawl.service; using ln.skyscanner.crawl.tests; using ln.types.net; +using ln.types.odb.mapped; namespace ln.skyscanner.crawl { @@ -200,7 +201,7 @@ namespace ln.skyscanner.crawl Query.Equals("IPAddresses[]", ip), Query.Equals("PrimaryIP", ip) ); - CrawledHost crawledHost = hosts.Select(nodeByIpQuery).FirstOrDefault(); + CrawledHost crawledHost = hosts.Query(nodeByIpQuery).FirstOrDefault(); if (crawledHost == null) { crawledHost = new CrawledHost(); @@ -217,7 +218,7 @@ namespace ln.skyscanner.crawl lock (this) { Query subnetQuery = Query.Equals("Network", network); - CrawledSubnet sn = CrawledSubnets.Select(subnetQuery).FirstOrDefault(); + CrawledSubnet sn = CrawledSubnets.Query(subnetQuery).FirstOrDefault(); if (sn == null) { Logging.Log(LogLevel.INFO, "Crawler adds new subnet: {0}", network); diff --git a/entities/CheckSeverity.cs b/entities/CheckSeverity.cs new file mode 100644 index 0000000..7b9af31 --- /dev/null +++ b/entities/CheckSeverity.cs @@ -0,0 +1,25 @@ +// /** +// * File: ProductionState.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 Newtonsoft.Json; +using Newtonsoft.Json.Converters; +namespace ln.skyscanner.entities +{ + [JsonConverter(typeof(StringEnumConverter))] + public enum CheckSeverity + { + OLD = 0, + PLANNED = 10, + SETUP = 20, + TESTING = 30, + PRODUCTION = 40, + SYSTEMCRITICAL = 50 + } +} diff --git a/entities/ConfiguredIP.cs b/entities/ConfiguredIP.cs index 4ea1ace..e811110 100644 --- a/entities/ConfiguredIP.cs +++ b/entities/ConfiguredIP.cs @@ -12,6 +12,7 @@ using ln.types.odb; using ln.types; using Newtonsoft.Json; using ln.types.net; +using ln.types.odb.attributes; namespace ln.skyscanner.entities { public class ConfiguredIP diff --git a/entities/GlobalNetwork.cs b/entities/GlobalNetwork.cs index 1f83a94..a1419d8 100644 --- a/entities/GlobalNetwork.cs +++ b/entities/GlobalNetwork.cs @@ -53,12 +53,12 @@ namespace ln.skyscanner.entities public Node GetNode(Guid id) { - return SkyEntities.nodeCollection.Select(id); + return SkyEntities.nodeCollection[id]; } public Subnet FindSubnetForIP(IPv4 ip) { - return SkyEntities.subnetCollection.Select(net => net.Network.Contains(ip)).FirstOrDefault(); + return SkyEntities.subnetCollection.Where((net) => net.Network.Contains(ip)).FirstOrDefault(); } public IEnumerable FindHostsInSubnet(Network4 network) @@ -70,7 +70,7 @@ namespace ln.skyscanner.entities Query.Equals("Interfaces[].ConfiguredIPs[].Network", network), Query.IF("PrimaryIP", (ip) => ((firstIP <= ip) && (ip <= lastIP))) ); - return SkyEntities.nodeCollection.Select(nodeByIpQuery); + return SkyEntities.nodeCollection.Query(nodeByIpQuery); } public IEnumerable FindNeighbors(Node node) @@ -107,11 +107,11 @@ namespace ln.skyscanner.entities public Node FindNodeByIP(IPv4 ip) { - Node node = SkyEntities.nodeCollection.SelectOne("PrimaryIP", ip); + Node node = SkyEntities.nodeCollection.Query("PrimaryIP", ip).FirstOrDefault(); if (node == null) { Query nodeByIpQuery = Query.Equals("Interfaces[].ConfiguredIPs[].IP", ip); - node = SkyEntities.nodeCollection.Select(nodeByIpQuery).FirstOrDefault(); + node = SkyEntities.nodeCollection.Query(nodeByIpQuery).FirstOrDefault(); } return node; } diff --git a/entities/NetworkInterface.cs b/entities/NetworkInterface.cs index 6eacda3..7378c62 100644 --- a/entities/NetworkInterface.cs +++ b/entities/NetworkInterface.cs @@ -15,6 +15,7 @@ using ln.types.odb; using Newtonsoft.Json; using ln.logging; using ln.types.net; +using ln.types.odb.attributes; namespace ln.skyscanner.entities { public class NetworkInterface diff --git a/entities/Node.cs b/entities/Node.cs index 9dd9032..3a32eaa 100644 --- a/entities/Node.cs +++ b/entities/Node.cs @@ -15,6 +15,7 @@ using ln.types.odb; using Newtonsoft.Json; using ln.types.threads; using ln.types.net; +using ln.types.odb.attributes; namespace ln.skyscanner.entities { public class Node @@ -37,6 +38,7 @@ namespace ln.skyscanner.entities public string Product { get; set; } public string ProductLine { get; set; } + public CheckSeverity Severity { get; set; } = CheckSeverity.PLANNED; public List Interfaces { get; private set; } = new List(); @@ -45,9 +47,17 @@ namespace ln.skyscanner.entities [JsonIgnore] public IEnumerable Networks => Interfaces.SelectMany(intf => intf.ConfiguredIPs.Select(nip => nip.Network)).Distinct(); [JsonIgnore] - public IEnumerable Subnets => SkyScanner.Instance.Entities.subnetCollection.Select("Network", Networks.Select(net => net.Network)); + public IEnumerable Subnets => SkyScanner.Instance.Entities.subnetCollection.Query(Query.Equals("Network", Networks.Select(net => net.Network))); - public String UniqueIdentity => PrimaryIP.ToString(); + private string uniqueIdentity; + public String UniqueIdentity { + get { + if (uniqueIdentity == null) + uniqueIdentity = PrimaryIP.ToString(); + return uniqueIdentity; + } + set => uniqueIdentity = value; + } public String[] Checks => checks.ToArray(); private HashSet uris = new HashSet(); diff --git a/entities/PointOfPresence.cs b/entities/PointOfPresence.cs new file mode 100644 index 0000000..af2c8cb --- /dev/null +++ b/entities/PointOfPresence.cs @@ -0,0 +1,45 @@ +// /** +// * File: PointOfPresence.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.types.odb; +using System.Collections.Generic; +using System.Linq; +using ln.types; +using ln.types.odb.attributes; +using Newtonsoft.Json; +namespace ln.skyscanner.entities +{ + public class PointOfPresence + { + [DocumentID] + public Guid ID = Guid.NewGuid(); + + public String Name { get; set; } + public String ForeignName { get; set; } + + public GeoLocation GeoLocation { get; set; } + + [JsonIgnore] + public Node[] Nodes => SkyScanner.Instance.Entities.nodeCollection.Query(Query.Equals("ID", nodeIDList.Select(id => ODBMapper.Default.MapValue(id)).ToArray())).ToArray(); + HashSet nodeIDList = new HashSet(); + + public DateTime Created { get; private set; } = DateTime.Now; + + public PointOfPresence() + { + } + + public void AddNode(Node node) => nodeIDList.Add(node.ID); + public void RemoveNode(Node node) => nodeIDList.Remove(node.ID); + + + + } +} diff --git a/entities/Subnet.cs b/entities/Subnet.cs index c14e8b6..a5ac6a5 100644 --- a/entities/Subnet.cs +++ b/entities/Subnet.cs @@ -14,6 +14,7 @@ using System.Collections.Generic; using System.Linq; using ln.types.net; using Newtonsoft.Json; +using ln.types.odb.attributes; namespace ln.skyscanner.entities { public class Subnet : Persistent diff --git a/http/SkyScannerHttpApplication.cs b/http/SkyScannerHttpApplication.cs index 2be3a31..5ddc152 100644 --- a/http/SkyScannerHttpApplication.cs +++ b/http/SkyScannerHttpApplication.cs @@ -2,6 +2,8 @@ using ln.http; using ln.http.resources; using System.IO; +using ln.skyscanner.entities; +using ln.skyscanner.checks; namespace ln.skyscanner.http { public class SkyScannerHttpApplication : ResourceApplication @@ -31,6 +33,12 @@ namespace ln.skyscanner.http refChecker = new ReflectiveResource(RootResource, "checker", SkyScanner.Checker); SkyScannerHttpApi api = new SkyScannerHttpApi(this); + + BaseResource collections = new BaseResource(RootResource, "collections"); + new CollectionResource(collections, skyScanner.Entities.popCollection); + new CollectionResource(collections, skyScanner.Entities.nodeCollection); + new CollectionResource(collections, skyScanner.Entities.subnetCollection); + new CollectionResource(collections, skyScanner.Checker.checkStates); } private Resource ResourceTypeHook(DirectoryResource directoryResource, FileInfo fileInfo) diff --git a/ln.skyscanner.csproj b/ln.skyscanner.csproj index 56ea8cb..a154b07 100644 --- a/ln.skyscanner.csproj +++ b/ln.skyscanner.csproj @@ -78,6 +78,8 @@ + + @@ -163,6 +165,37 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + @@ -178,6 +211,7 @@ + diff --git a/templates/static/checks/checkstates.html b/templates/static/checks/checkstates.html index d4f8307..18acc4c 100644 --- a/templates/static/checks/checkstates.html +++ b/templates/static/checks/checkstates.html @@ -20,23 +20,21 @@ { title: "UniqueNodeIdentifier", data: "UniqueNodeIdentifier" }, { title: "LastCheckTime", data: "LastCheckTime" }, { title: "CheckState", data: "CheckState" }, + { title: "Check Schwere", data: null, render: function(d,t,r){ return "-"; } }, ], - }; + ajax: { + url: "/collections/SkyCheckState", + dataSrc: "" + } + }; $("#CheckStates").DataTable( dtDef ); function refresh() { - skyapi().getJson("checker/CheckStates", function(data){ - if (!data) - data = [] - - $("#CheckStates").DataTable().clear(); - $("#CheckStates").DataTable().rows.add( data ).draw(); - }); + $("#CheckStates").DataTable().ajax.reload( null, false ); } - refresh(); skyapi().addRefresh( refresh, 15 ); diff --git a/templates/static/checks/status.html b/templates/static/checks/status.html index 9a3fe00..74a4156 100644 --- a/templates/static/checks/status.html +++ b/templates/static/checks/status.html @@ -19,40 +19,40 @@ diff --git a/templates/static/css/style.css b/templates/static/css/style.css index c3ceb62..1c594bc 100644 --- a/templates/static/css/style.css +++ b/templates/static/css/style.css @@ -73,7 +73,7 @@ button { border-bottom: 1px solid black; background-color: #c7def5; - padding: 12px; + padding: 4px; display: flex; @@ -258,3 +258,68 @@ fieldset > label { min-width: 140px; } + +.popup { + border: 2px solid rgba(0,0,0,0); + + position: relative; + display: inline-block; + padding: 4px; + + z-index: 1; + + font-size: 16px; + transition: background-color 250ms; +} + +.popup:hover { + border: 1px solid black; + border-bottom: 3px solid white; + border-radius: 6px 6px 0px 0px; + + background-color: #dbe7f3; + transition: background-color 250ms; +} + +.popup > div { + visibility: hidden; + opacity: 0; + transition: opacity 250ms; + + display: block; + position: absolute; + z-index: -1; + left: -1px; + top: 26px; + + min-width: 140px; + max-width: 240px; + + background-color: white; + border: 1px solid black; + border-radius: 0px 6px 6px 6px; + + padding: 8px; +} + +.popup:hover > div { + visibility: visible; + opacity: 1; + transition: opacity 250ms; +} + +.popup > div > div { + position: relative; + display: block; + padding: 4px; + + white-space: nowrap; +} + +.popup > div > div:hover { + background-color: #dbe7f3; +} + +.ui-icon { + background-image: url(images/ui-icons_6495ED_256x240.png); +} diff --git a/templates/static/frame.html b/templates/static/frame.html index 70c4067..76a962b 100644 --- a/templates/static/frame.html +++ b/templates/static/frame.html @@ -29,28 +29,27 @@
-
HTTPServer
-
Manager
-
Crawler
-
Checks
-
Message Dispatcher
-
-
-
<%=__frame__%>
+ diff --git a/templates/static/network/index.html b/templates/static/network/index.html index 8a05bb9..35c65b4 100644 --- a/templates/static/network/index.html +++ b/templates/static/network/index.html @@ -1,8 +1,11 @@ <%frame "frame.html"%>

Network Overview

-

Hosts / Nodes

-
+

Hosts / Nodes

+ +
+
+

Details

@@ -69,10 +72,11 @@ $("#dInterfaces").append( $( "" ) ); }); }); - + /* skyapi().call("api/network","GetNeighbors", [ node.ID ], function(neighbors){ $("#nodeTable").DataTable().clear().rows.add( neighbors ).draw(); }); + */ } } @@ -100,7 +104,11 @@ ], select: "single", height: 300, - fixedHeader: true + fixedHeader: true, + ajax: { + url: "/collections/Node", + dataSrc: "" + } }) .on( "select", function(e,dt,type,indexes){ if (indexes.length > 0) @@ -115,13 +123,10 @@ function refreshNodeTable() { - skyapi().getJson("entities/Nodes", - function(rows){ - $("#nodeTable").DataTable().clear().rows.add( rows ).draw(); - }); + $("#nodeTable").DataTable().ajax.reload(null, false); } showNode(null); - refreshNodeTable(); + //refreshNodeTable(); diff --git a/templates/static/network/pops.html b/templates/static/network/pops.html new file mode 100644 index 0000000..4a26be5 --- /dev/null +++ b/templates/static/network/pops.html @@ -0,0 +1,107 @@ +<%frame "frame.html"%> + +

Points of Presence

+
+

List

+
+
+ +
+
+

Details

+
+
+
+
+
+
+
+
+ +
+ + diff --git a/templates/static/skyapi.js b/templates/static/skyapi.js index ccdf266..7eb21b2 100644 --- a/templates/static/skyapi.js +++ b/templates/static/skyapi.js @@ -5,44 +5,40 @@ function SKYAPI(baseurl){ this.refresh = [] this.setBaseURL = function(url){ this.baseurl = url; } - this.addRefresh = function( rh, seconds = null ){ this.refresh.push( { interval: seconds ? seconds : 5, refresh: rh } ); } + + this.get = function(page, json, handler = null){ return this.__request("GET", page, json, handler); } + this.post = function(page, json, handler = null){ return this.__request("POST", page, json, handler); } + this.put = function(page, json, handler = null){ return this.__request("PUT", page, json, handler); } - this.get = function(page, handler = null){ - var x = new XMLHttpRequest(); - var async = (handler != null); - - if (async) - { - x.onload = function(){ - var responseText = x.responseText; - handler( responseText ); - } - } - x.open("GET", this.baseurl + page, async); - x.send(); - - if (!async) - return x.responseText - } - this.post = function(page, handler = null){ + this.__request = function(method, page, json, handler = null){ + if (page[0] == '/') + page = page.substr(1); + var x = new XMLHttpRequest(); if (handler != null) { x.onload = function(){ var responseText = x.responseText; - handler( responseText ); + if (json && !content) + handler( JSON.parse( responseText ) ); + else + handler( responseText ); } } - x.open("POST", this.baseurl + page); - x.send(); + x.open(method, this.baseurl + page); + + if (json) + x.send(JSON.stringify(json)); + else + x.send(); } this.getJson = function(page, handler){ var j = function(t){ handler(JSON.parse(t)); }; - return this.get( page, j ); + return this.get( page, null, j ); } this.call = function(endpoint,method,parameters = [], receiver = null){ @@ -76,9 +72,11 @@ function SKYAPI(baseurl){ } this.loadPage = function (page) { - + if (page[0] == '/') + page = page.substr(1); + var x = new XMLHttpRequest(); - + x.open("GET", this.baseurl + page); x.setRequestHeader("x-template-unframed","unframed"); x.onload = function() diff --git a/templates/static/system/index.html b/templates/static/system/index.html new file mode 100644 index 0000000..07b259d --- /dev/null +++ b/templates/static/system/index.html @@ -0,0 +1,27 @@ +<%frame "frame.html"%> +
+

Modul Steuerung

+
+ +
+ + + + + + + + + + + + + + + + + + + +
System
Crawler
+
diff --git a/templates/static/topnav.html b/templates/static/topnav.html new file mode 100644 index 0000000..18ba7a8 --- /dev/null +++ b/templates/static/topnav.html @@ -0,0 +1,75 @@ + + + + + + + + + + + +