WIP
parent
c546eacac2
commit
ed2c104cf7
|
@ -20,24 +20,20 @@ namespace ln.skyscanner
|
||||||
public SkyScanner SkyScanner { get; }
|
public SkyScanner SkyScanner { get; }
|
||||||
public string BasePath => Path.Combine(SkyScanner.BasePath, "entities");
|
public string BasePath => Path.Combine(SkyScanner.BasePath, "entities");
|
||||||
|
|
||||||
//public GlobalNetwork GlobalNetwork => DBGlobalNetwork.Root;
|
|
||||||
//public ODB<GlobalNetwork> DBGlobalNetwork { get; private set; }
|
|
||||||
|
|
||||||
public GlobalNetwork GlobalNetwork { get; private set; }
|
public GlobalNetwork GlobalNetwork { get; private set; }
|
||||||
public LiteDatabase liteDatabase { get; private set; }
|
public ODB odDatabase { get; private set; }
|
||||||
public LiteCollection<Node> nodeCollection { get; private set; }
|
public ODBCollection<Node> nodeCollection { get; private set; }
|
||||||
public LiteCollection<NetworkInterface> interfaceCollection { get; private set; }
|
public ODBCollection<NetworkInterface> interfaceCollection { get; private set; }
|
||||||
public LiteCollection<Subnet> subnetCollection { get; private set; }
|
public ODBCollection<Subnet> subnetCollection { get; private set; }
|
||||||
|
|
||||||
public SkyEntities(SkyScanner skyScanner)
|
public SkyEntities(SkyScanner skyScanner)
|
||||||
{
|
{
|
||||||
SkyScanner = skyScanner;
|
SkyScanner = skyScanner;
|
||||||
//DBGlobalNetwork = new ODB<GlobalNetwork>(BasePath);
|
|
||||||
|
|
||||||
liteDatabase = new LiteDatabase(String.Format(BasePath, "entities.db"));
|
odDatabase = new ODB(BasePath);
|
||||||
nodeCollection = liteDatabase.GetCollection<Node>("nodes");
|
nodeCollection = odDatabase.GetCollection<Node>();
|
||||||
interfaceCollection = liteDatabase.GetCollection<NetworkInterface>("interfaces");
|
interfaceCollection = odDatabase.GetCollection<NetworkInterface>();
|
||||||
subnetCollection = liteDatabase.GetCollection<Subnet>("subnets");
|
subnetCollection = odDatabase.GetCollection<Subnet>();
|
||||||
|
|
||||||
GlobalNetwork = new GlobalNetwork(this);
|
GlobalNetwork = new GlobalNetwork(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace ln.skyscanner.entities
|
||||||
public class CrawledSubnet
|
public class CrawledSubnet
|
||||||
{
|
{
|
||||||
[DocumentID]
|
[DocumentID]
|
||||||
Guid ID;
|
Guid ID = Guid.NewGuid();
|
||||||
|
|
||||||
public readonly CIDR Network;
|
public readonly CIDR Network;
|
||||||
public String Name;
|
public String Name;
|
||||||
|
|
|
@ -168,6 +168,11 @@ namespace ln.skyscanner.crawl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void EnsureSubnet(CIDR network)
|
||||||
|
{
|
||||||
|
FindSubnet(network);
|
||||||
|
}
|
||||||
|
|
||||||
public void Enqueue(JobDelegate job)
|
public void Enqueue(JobDelegate job)
|
||||||
{
|
{
|
||||||
crawlThreadPool.Enqueue(job);
|
crawlThreadPool.Enqueue(job);
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
// /**
|
|
||||||
// * File: CrawlTest.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 System.Collections.Generic;
|
|
||||||
using System.Reflection;
|
|
||||||
using ln.types;
|
|
||||||
|
|
||||||
namespace ln.skyscanner.crawl.tests
|
|
||||||
{
|
|
||||||
public static class Crawling
|
|
||||||
{
|
|
||||||
|
|
||||||
//public static bool Crawl(Crawl hostCrawl)
|
|
||||||
//{
|
|
||||||
// hostCrawl.setState("ICMP");
|
|
||||||
// if (!ICMP.IsReachable(hostCrawl.Host))
|
|
||||||
// {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (hostCrawl.AbortRequested)
|
|
||||||
// return false;
|
|
||||||
|
|
||||||
// hostCrawl.setState("SSH");
|
|
||||||
// if (SSH.CanConnect(hostCrawl.Host))
|
|
||||||
// {
|
|
||||||
// // ToDo: Extract more details...
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (hostCrawl.AbortRequested)
|
|
||||||
// return false;
|
|
||||||
|
|
||||||
// hostCrawl.setState("SNMP");
|
|
||||||
// if (SNMP.HasSNMP(hostCrawl.Host))
|
|
||||||
// {
|
|
||||||
// if (hostCrawl.AbortRequested)
|
|
||||||
// return false;
|
|
||||||
|
|
||||||
// hostCrawl.setState("RFC1213");
|
|
||||||
// RFC1213.Check(hostCrawl.Host);
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// foreach (CIDR ip in hostCrawl.Host.IPAddresses)
|
|
||||||
// {
|
|
||||||
// if (ip.MaskWidth != 32)
|
|
||||||
// hostCrawl.Crawler.CrawlPool.GetSubnet(ip.Network);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return true;
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -43,15 +43,13 @@ namespace ln.skyscanner.crawl.tests
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
ln.snmp.rfc1213.RFC1213.Interface[] interfaces = ln.snmp.rfc1213.RFC1213.GetInterfaces(snmp);
|
ln.snmp.rfc1213.RFC1213.Interface[] interfaces = ln.snmp.rfc1213.RFC1213.GetInterfaces(snmp);
|
||||||
if (interfaces.Length > 0)
|
if (interfaces.Length > 0)
|
||||||
{
|
{
|
||||||
crawl.Host.IPAddresses = interfaces.SelectMany(intf => intf.IPAddresses).ToArray();
|
crawl.Host.IPAddresses = interfaces.SelectMany(intf => intf.IPAddresses).ToArray();
|
||||||
crawl.Host.HWAddresses = interfaces.Select(intf => intf.HWAddr).ToArray();
|
crawl.Host.HWAddresses = interfaces.Select(intf => intf.HWAddr).ToArray();
|
||||||
|
|
||||||
crawl.Host.SetHint("rfc1213.interfaces",interfaces.Select(intf => string.Format("{0};{1};{2}",intf.Name,intf.HWAddr,String.Join(",",intf.IPAddresses.Select(ip=>ip.ToString())).ToArray())).ToArray());
|
crawl.Host.SetHint("rfc1213.interfaces",interfaces.Select(intf => string.Format("{0};{1};{2}",intf.Name,intf.HWAddr,String.Join(",",intf.IPAddresses.Select(ip=>ip.ToString())))).ToArray());
|
||||||
crawl.Host.SetHint("rfc1213", true);
|
crawl.Host.SetHint("rfc1213", true);
|
||||||
}
|
}
|
||||||
} catch (TimeoutException)
|
} catch (TimeoutException)
|
||||||
|
|
|
@ -120,6 +120,7 @@ namespace ln.skyscanner.crawl.tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
v3endpoint.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -153,6 +154,7 @@ namespace ln.skyscanner.crawl.tests
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
v2endpoint.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -186,6 +188,7 @@ namespace ln.skyscanner.crawl.tests
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
v1endpoint.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -10,6 +10,7 @@ using ln.snmp.rfc1213;
|
||||||
using ln.types.odb;
|
using ln.types.odb;
|
||||||
using ln.types.sync;
|
using ln.types.sync;
|
||||||
using ln.logging;
|
using ln.logging;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
namespace ln.skyscanner.entities
|
namespace ln.skyscanner.entities
|
||||||
{
|
{
|
||||||
|
@ -20,14 +21,11 @@ namespace ln.skyscanner.entities
|
||||||
[Unsynced]
|
[Unsynced]
|
||||||
public SkyEntities SkyEntities { get; private set; }
|
public SkyEntities SkyEntities { get; private set; }
|
||||||
|
|
||||||
public IEnumerable<Subnet> Subnets => subnets;
|
public IEnumerable<Subnet> Subnets => SkyEntities.subnetCollection;
|
||||||
public IEnumerable<Node> Nodes => nodes;
|
public IEnumerable<Node> Nodes => SkyEntities.nodeCollection;
|
||||||
|
|
||||||
public HopMap DefaultHopMap { get; private set; } = new HopMap();
|
public HopMap DefaultHopMap { get; private set; } = new HopMap();
|
||||||
|
|
||||||
private List<Node> nodes = new List<Node>();
|
|
||||||
private List<Subnet> subnets = new List<Subnet>();
|
|
||||||
|
|
||||||
private object _updateLock = new object();
|
private object _updateLock = new object();
|
||||||
|
|
||||||
public GlobalNetwork()
|
public GlobalNetwork()
|
||||||
|
@ -39,52 +37,32 @@ namespace ln.skyscanner.entities
|
||||||
SkyEntities = skyEntities;
|
SkyEntities = skyEntities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void EnsureSubnet(CIDR network)
|
||||||
|
{
|
||||||
|
SkyScanner.Crawler.EnsureSubnet(network);
|
||||||
|
|
||||||
|
Subnet subnet = SkyEntities.subnetCollection.Where(s => s.Network.Equals(network)).FirstOrDefault();
|
||||||
|
if (subnet == null)
|
||||||
|
{
|
||||||
|
subnet = new Subnet(network);
|
||||||
|
SkyEntities.subnetCollection.Upsert(subnet);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public Node GetNode(Guid id)
|
public Node GetNode(Guid id)
|
||||||
{
|
{
|
||||||
//foreach (Node node in nodes)
|
return SkyEntities.nodeCollection.Select(id);
|
||||||
//{
|
|
||||||
// if (node.PersistenceID.Equals(persistenceID))
|
|
||||||
// return node;
|
|
||||||
//}
|
|
||||||
//throw new KeyNotFoundException();
|
|
||||||
|
|
||||||
return SkyEntities.nodeCollection.FindOne(n => n.ID.Equals(id));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Subnet FindSubnetForHost(CIDR host)
|
public Subnet FindSubnetForHost(CIDR host)
|
||||||
{
|
{
|
||||||
//foreach (Subnet subnet in subnets)
|
return SkyEntities.subnetCollection.Select(net => net.Network.Contains(host)).FirstOrDefault();
|
||||||
//{
|
|
||||||
// if (subnet.Network.Contains(host.Host))
|
|
||||||
// return subnet;
|
|
||||||
//}
|
|
||||||
//return null;
|
|
||||||
|
|
||||||
return SkyEntities.subnetCollection.FindOne(net => net.Network.Contains(host));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Node> FindHostsInSubnet(CIDR network)
|
public IEnumerable<Node> FindHostsInSubnet(CIDR network)
|
||||||
{
|
{
|
||||||
//HashSet<Node> result = new HashSet<Node>();
|
return SkyEntities.nodeCollection.Select(node => network.Contains(node.IPAdresses));
|
||||||
|
|
||||||
//foreach (Node node in nodes.ToArray())
|
|
||||||
//{
|
|
||||||
// foreach (NetworkInterface networkInterface in node.Interfaces.ToArray())
|
|
||||||
// {
|
|
||||||
// foreach (CIDR ip in networkInterface.IPs)
|
|
||||||
// {
|
|
||||||
// if (network.Contains(ip))
|
|
||||||
// {
|
|
||||||
// result.Add(node);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//return result;
|
|
||||||
|
|
||||||
return SkyEntities.nodeCollection.Find(node => network.Contains(node.IPAdresses));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Node> FindNeighbors(Node node)
|
public IEnumerable<Node> FindNeighbors(Node node)
|
||||||
|
@ -104,7 +82,8 @@ namespace ln.skyscanner.entities
|
||||||
}
|
}
|
||||||
public Node FindNodeByIP(CIDR ip)
|
public Node FindNodeByIP(CIDR ip)
|
||||||
{
|
{
|
||||||
return SkyEntities.nodeCollection.FindOne(node => node.IPAdresses.Contains(ip) || node.PrimaryIP.Equals(ip));
|
ip = ip.Host;
|
||||||
|
return SkyEntities.nodeCollection.Select(node => ip.In(node.IPAdresses) || ip.In(node.PrimaryIP)).FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Unsynced]
|
[Unsynced]
|
||||||
|
@ -158,14 +137,23 @@ namespace ln.skyscanner.entities
|
||||||
node.PrimaryMac = crawledHost.PrimaryHWAddr;
|
node.PrimaryMac = crawledHost.PrimaryHWAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//foreach (String si in crawledHost.GetHint<string[]>("rfc1213.interfaces",)
|
foreach (String si in crawledHost.GetHint<string[]>("rfc1213.interfaces",new string[0]))
|
||||||
//{
|
{
|
||||||
// NetworkInterface networkInterface = node.GetInterface(intf.Name);
|
String[] fields = si.Split(';');
|
||||||
// if (networkInterface == null)
|
|
||||||
// networkInterface = new NetworkInterface(node, intf.Name);
|
|
||||||
|
|
||||||
// networkInterface.IPs = intf.IPAddresses.ToArray();
|
NetworkInterface networkInterface = node.GetInterface(fields[0]);
|
||||||
//}
|
if (networkInterface == null)
|
||||||
|
networkInterface = new NetworkInterface(node, fields[0]);
|
||||||
|
|
||||||
|
networkInterface.HWAddress = fields[1];
|
||||||
|
networkInterface.IPs = fields[2].Split(',').Where((sip)=> !String.Empty.Equals(sip)).Select((sip) => CIDR.Parse(sip)).ToArray();
|
||||||
|
|
||||||
|
SkyEntities.interfaceCollection.Upsert(networkInterface);
|
||||||
|
|
||||||
|
foreach (CIDR ip in networkInterface.IPs)
|
||||||
|
EnsureSubnet(ip);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
node.RemoveURI("ssh");
|
node.RemoveURI("ssh");
|
||||||
if (crawledHost.GetHint<int>("ssh.port", -1) != -1)
|
if (crawledHost.GetHint<int>("ssh.port", -1) != -1)
|
||||||
|
|
|
@ -18,19 +18,20 @@ namespace ln.skyscanner.entities
|
||||||
{
|
{
|
||||||
public class NetworkInterface : Persistent
|
public class NetworkInterface : Persistent
|
||||||
{
|
{
|
||||||
[BsonId]
|
[DocumentID]
|
||||||
public Guid ID { get; private set; }
|
public readonly Guid ID = Guid.NewGuid();
|
||||||
|
|
||||||
public Guid NodeID { get; set; }
|
public Guid NodeID { get; set; }
|
||||||
|
|
||||||
[JsonIgnoreAttribute]
|
[JsonIgnoreAttribute]
|
||||||
public Node Node
|
public Node Node
|
||||||
{
|
{
|
||||||
get => SkyScanner.Instance.Entities.nodeCollection.FindById(NodeID);
|
get => SkyScanner.Instance.Entities.nodeCollection[NodeID];
|
||||||
set => NodeID = value.ID;
|
set => NodeID = value.ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name { get; private set; } = "";
|
public string Name { get; private set; } = "";
|
||||||
|
public string HWAddress { get; set; } = "";
|
||||||
|
|
||||||
public CIDR[] IPs { get; set; } = new CIDR[0];
|
public CIDR[] IPs { get; set; } = new CIDR[0];
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace ln.skyscanner.entities
|
||||||
public class Node
|
public class Node
|
||||||
{
|
{
|
||||||
[DocumentID]
|
[DocumentID]
|
||||||
public Guid ID { get; set; }
|
public Guid ID { get; set; } = Guid.NewGuid();
|
||||||
|
|
||||||
public CIDR PrimaryIP { get; set; }
|
public CIDR PrimaryIP { get; set; }
|
||||||
public String PrimaryMac { get; set; }
|
public String PrimaryMac { get; set; }
|
||||||
|
@ -37,7 +37,7 @@ namespace ln.skyscanner.entities
|
||||||
|
|
||||||
public string ProductLine { get; set; }
|
public string ProductLine { get; set; }
|
||||||
|
|
||||||
public IEnumerable<NetworkInterface> Interfaces => SkyScanner.Instance.Entities.interfaceCollection.Find( intf => intf.NodeID.Equals(ID));
|
public IEnumerable<NetworkInterface> Interfaces => SkyScanner.Instance.Entities.interfaceCollection.Select( intf => intf.NodeID.Equals(ID));
|
||||||
public IEnumerable<CIDR> IPAdresses => Interfaces.SelectMany(intf => intf.IPs);
|
public IEnumerable<CIDR> IPAdresses => Interfaces.SelectMany(intf => intf.IPs);
|
||||||
|
|
||||||
private HashSet<URI> uris = new HashSet<URI>();
|
private HashSet<URI> uris = new HashSet<URI>();
|
||||||
|
@ -83,7 +83,7 @@ namespace ln.skyscanner.entities
|
||||||
|
|
||||||
public NetworkInterface GetInterface(String intfName)
|
public NetworkInterface GetInterface(String intfName)
|
||||||
{
|
{
|
||||||
return SkyScanner.Instance.Entities.interfaceCollection.FindOne(intf => intf.NodeID.Equals(ID) && intf.Name.Equals(intfName));
|
return SkyScanner.Instance.Entities.interfaceCollection.Where(intf => intf.NodeID.Equals(ID) && intf.Name.Equals(intfName)).FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasInterface(string intfName)
|
public bool HasInterface(string intfName)
|
||||||
|
|
|
@ -16,7 +16,10 @@ namespace ln.skyscanner.entities
|
||||||
{
|
{
|
||||||
public class Subnet : Persistent
|
public class Subnet : Persistent
|
||||||
{
|
{
|
||||||
public GlobalNetwork GlobalNetwork { get; private set; }
|
public SkyEntities SkyEntities => SkyScanner.Instance.Entities;
|
||||||
|
|
||||||
|
[DocumentID]
|
||||||
|
public Guid ID { get; private set; } = Guid.NewGuid();
|
||||||
|
|
||||||
public readonly CIDR Network;
|
public readonly CIDR Network;
|
||||||
public String Name;
|
public String Name;
|
||||||
|
@ -26,32 +29,20 @@ namespace ln.skyscanner.entities
|
||||||
|
|
||||||
public bool AutoScan { get; set; }
|
public bool AutoScan { get; set; }
|
||||||
|
|
||||||
public NetworkInterface[] AttachedInterfaces => networkInterfaces.ToArray();
|
public IEnumerable<NetworkInterface> AttachedInterfaces => SkyEntities.interfaceCollection.Where((intf) => Network.Contains(intf.IPs));
|
||||||
|
public IEnumerable<Node> AttachedNodes => AttachedInterfaces.Select(intf => intf.Node).Distinct();
|
||||||
private HashSet<NetworkInterface> networkInterfaces = new HashSet<NetworkInterface>();
|
|
||||||
|
|
||||||
private Subnet()
|
private Subnet()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public Subnet(GlobalNetwork globalNetwork,CIDR cidr)
|
public Subnet(CIDR cidr)
|
||||||
{
|
{
|
||||||
GlobalNetwork = globalNetwork;
|
|
||||||
Network = cidr;
|
Network = cidr;
|
||||||
Name = Network.ToString();
|
Name = Network.ToString();
|
||||||
FirstSeen = DateTime.Now;
|
FirstSeen = DateTime.Now;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AttachInterface(NetworkInterface networkInterface)
|
|
||||||
{
|
|
||||||
networkInterfaces.Add(networkInterface);
|
|
||||||
}
|
|
||||||
public void DetachInterface(NetworkInterface networkInterface)
|
|
||||||
{
|
|
||||||
networkInterfaces.Remove(networkInterface);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return Network.ToString();
|
return Network.ToString();
|
||||||
|
|
|
@ -63,7 +63,6 @@
|
||||||
<Compile Include="http\CrawlerApi.cs" />
|
<Compile Include="http\CrawlerApi.cs" />
|
||||||
<Compile Include="crawl\CrawlNetwork.cs" />
|
<Compile Include="crawl\CrawlNetwork.cs" />
|
||||||
<Compile Include="crawl\Crawl.cs" />
|
<Compile Include="crawl\Crawl.cs" />
|
||||||
<Compile Include="crawl\service\Crawling.cs" />
|
|
||||||
<Compile Include="crawl\service\SSH.cs" />
|
<Compile Include="crawl\service\SSH.cs" />
|
||||||
<Compile Include="crawl\service\SNMP.cs" />
|
<Compile Include="crawl\service\SNMP.cs" />
|
||||||
<Compile Include="crawl\service\ICMP.cs" />
|
<Compile Include="crawl\service\ICMP.cs" />
|
||||||
|
|
|
@ -70,7 +70,7 @@
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
skyapi().call("api/network","GetHopTable", [ node.PersistenceID ], function(neighbors){
|
skyapi().call("api/network","GetHopTable", [ node.ID ], function(neighbors){
|
||||||
$("#nodeTable").DataTable().clear().rows.add( neighbors ).draw();
|
$("#nodeTable").DataTable().clear().rows.add( neighbors ).draw();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
skyapi().call("api/network","GetNeighbors", [ node.PersistenceID ], function(neighbors){
|
skyapi().call("api/network","GetNeighbors", [ node.ID ], function(neighbors){
|
||||||
$("#nodeTable").DataTable().clear().rows.add( neighbors ).draw();
|
$("#nodeTable").DataTable().clear().rows.add( neighbors ).draw();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue