WIP
parent
53a9f198b5
commit
9a4f448a47
|
@ -0,0 +1,188 @@
|
||||||
|
using System;
|
||||||
|
using ln.application;
|
||||||
|
using ln.application.service;
|
||||||
|
using System.Threading;
|
||||||
|
using ln.types.odb.ng;
|
||||||
|
using ln.types;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using ln.json;
|
||||||
|
using ln.types.odb.ng.storage.session;
|
||||||
|
namespace ln.provider
|
||||||
|
{
|
||||||
|
public class IPPoolService : ApplicationServiceBase
|
||||||
|
{
|
||||||
|
CoreService CoreService { get; set; }
|
||||||
|
ProviderApplication Application => (ProviderApplication)base.CurrentApplicationInterface;
|
||||||
|
|
||||||
|
RPC rpc;
|
||||||
|
|
||||||
|
SessionStorageContainer mapperSession;
|
||||||
|
Mapper mapper;
|
||||||
|
|
||||||
|
IPAllocation v6Root;
|
||||||
|
IPAllocation v4Root;
|
||||||
|
|
||||||
|
public IPPoolService()
|
||||||
|
:base("IPPoolService")
|
||||||
|
{
|
||||||
|
DependOnService<CoreService>();
|
||||||
|
|
||||||
|
rpc = new RPC(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ServiceMain(IApplicationInterface applicationInterface)
|
||||||
|
{
|
||||||
|
CoreService = Dependency<CoreService>();
|
||||||
|
|
||||||
|
using (mapperSession = new SessionStorageContainer(CoreService.CoreStorageContainer))
|
||||||
|
{
|
||||||
|
mapper = new Mapper(mapperSession);
|
||||||
|
|
||||||
|
mapper.EnsureIndex<IPAllocation>("CIDR");
|
||||||
|
mapper.EnsureIndex<IPAllocation>("Pool");
|
||||||
|
|
||||||
|
Application.RPCContainer.Add("ippool", rpc);
|
||||||
|
|
||||||
|
v6Root = mapper.Load<IPAllocation>(Query.Equals<IPAllocation>("CIDR",IPv6.ANY)).FirstOrDefault();
|
||||||
|
v4Root = mapper.Load<IPAllocation>(Query.Equals<IPAllocation>("CIDR", IPv6.V4Space)).FirstOrDefault();
|
||||||
|
|
||||||
|
if (v6Root == null)
|
||||||
|
{
|
||||||
|
v6Root = new IPAllocation(IPv6.ANY, "Global IPv6 Space", null);
|
||||||
|
mapper.Save(v6Root);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v4Root == null)
|
||||||
|
{
|
||||||
|
v4Root = new IPAllocation(IPv6.V4Space, "Global IPv4 Space", v6Root.CIDR);
|
||||||
|
mapper.Save(v4Root);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ready();
|
||||||
|
|
||||||
|
while (!StopRequested)
|
||||||
|
{
|
||||||
|
lock (Thread.CurrentThread)
|
||||||
|
{
|
||||||
|
Monitor.Wait(Thread.CurrentThread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mapper = null;
|
||||||
|
|
||||||
|
Application.RPCContainer.Remove("ippool");
|
||||||
|
CoreService = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IPAllocation[] GetAllocations()
|
||||||
|
{
|
||||||
|
return mapper.Load<IPAllocation>().ToArray();
|
||||||
|
}
|
||||||
|
public IPAllocation GetAllocation(IPv6 cidr)
|
||||||
|
{
|
||||||
|
return mapper.Load<IPAllocation>(Query.Equals<IPAllocation>("CIDR", cidr)).FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IPAllocation[] GetPoolAllocations(IPv6 pool)
|
||||||
|
{
|
||||||
|
return mapper.Load<IPAllocation>(Query.Equals<IPAllocation>("Pool", pool)).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public IPAllocation AllocateAny(IPv6 zone,int width,string usage)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public IPAllocation AllocateCIDR(IPv6 zone,IPv6 cidr,string usage,bool splitZones)
|
||||||
|
{
|
||||||
|
IPAllocation pool = GetAllocation(zone);
|
||||||
|
if (pool == null)
|
||||||
|
throw new KeyNotFoundException();
|
||||||
|
|
||||||
|
if (!pool.CIDR.Contains(cidr))
|
||||||
|
throw new ArgumentException(String.Format("{0} doesn't contain {1}", pool.CIDR.ToCIDR(), cidr.ToCIDR()));
|
||||||
|
|
||||||
|
if (splitZones)
|
||||||
|
{
|
||||||
|
IPAllocation allocation = pool;
|
||||||
|
while (!allocation.CIDR.Equals(cidr))
|
||||||
|
{
|
||||||
|
foreach (IPv6 splitCIDR in allocation.CIDR.Split(1))
|
||||||
|
{
|
||||||
|
if (splitCIDR.Contains(cidr))
|
||||||
|
{
|
||||||
|
IPAllocation split = GetAllocation(splitCIDR);
|
||||||
|
if (split == null)
|
||||||
|
{
|
||||||
|
split = new IPAllocation(splitCIDR,allocation.CIDR);
|
||||||
|
mapper.Save(split);
|
||||||
|
allocation = split;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allocation;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IPAllocation allocation = GetAllocation(cidr);
|
||||||
|
if (allocation != null)
|
||||||
|
throw new Exception("Allocation already present");
|
||||||
|
|
||||||
|
allocation = new IPAllocation(cidr, cidr.ToCIDR(), pool.CIDR);
|
||||||
|
allocation.AllocatedTo = usage;
|
||||||
|
|
||||||
|
mapper.Save(allocation);
|
||||||
|
|
||||||
|
return allocation;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class RPC
|
||||||
|
{
|
||||||
|
IPPoolService poolService;
|
||||||
|
|
||||||
|
public RPC(IPPoolService poolService)
|
||||||
|
{
|
||||||
|
this.poolService = poolService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IPAllocation[] GetAllocations() => poolService.GetAllocations();
|
||||||
|
public IPAllocation GetAllocation(IPv6 cidr) => poolService.GetAllocation(cidr);
|
||||||
|
public IPAllocation[] GetPoolAllocations(IPv6 pool) => poolService.GetPoolAllocations(pool);
|
||||||
|
|
||||||
|
public IPAllocation AllocateAny(IPv6 zone, int width, string usage) => poolService.AllocateAny(zone, width, usage);
|
||||||
|
public IPAllocation AllocateCIDR(IPv6 zone, IPv6 cidr, string usage, bool splitZones) => poolService.AllocateCIDR(zone, cidr, usage,splitZones);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class IPAllocation
|
||||||
|
{
|
||||||
|
public IPv6 CIDR { get; }
|
||||||
|
public string Name { get; set; } = String.Empty;
|
||||||
|
|
||||||
|
public string AllocatedTo { get; set; } = String.Empty;
|
||||||
|
|
||||||
|
public IPv6 Pool { get; }
|
||||||
|
|
||||||
|
private IPAllocation(){}
|
||||||
|
public IPAllocation(IPv6 cidr): this(cidr, cidr.ToCIDR(), IPv6.ANY) { }
|
||||||
|
public IPAllocation(IPv6 cidr, IPv6 pool) : this(cidr, cidr.ToCIDR(), pool) { }
|
||||||
|
public IPAllocation(IPv6 cidr,String name,IPv6 pool)
|
||||||
|
{
|
||||||
|
Pool = pool;
|
||||||
|
CIDR = cidr;
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,8 @@ using ln.types.odb.ng.storage;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using ln.types;
|
using ln.types;
|
||||||
|
using ln.types.odb.ng.storage.session;
|
||||||
|
using ln.types.odb.ng.storage.fs;
|
||||||
namespace ln.provider
|
namespace ln.provider
|
||||||
{
|
{
|
||||||
public class ProviderApplication : Application
|
public class ProviderApplication : Application
|
||||||
|
@ -28,12 +30,10 @@ namespace ln.provider
|
||||||
if (Directory.Exists("../../www"))
|
if (Directory.Exists("../../www"))
|
||||||
WWWPath = "../../www";
|
WWWPath = "../../www";
|
||||||
|
|
||||||
ServiceDefinition coreRPCService = new ServiceDefinition("ln.provider.CoreService");
|
ServiceDefinition coreRPCService = ServiceDefinition.From<CoreService>(true);
|
||||||
coreRPCService.AutoStart = true;
|
ServiceContainer.Add(coreRPCService);
|
||||||
|
|
||||||
ServiceContainer.Add(
|
ServiceContainer.Add(ServiceDefinition.From<IPPoolService>(true));
|
||||||
coreRPCService
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void PrepareStart()
|
public override void PrepareStart()
|
||||||
|
@ -66,7 +66,7 @@ namespace ln.provider
|
||||||
public ProviderApplication Application => (ProviderApplication)base.CurrentApplicationInterface;
|
public ProviderApplication Application => (ProviderApplication)base.CurrentApplicationInterface;
|
||||||
|
|
||||||
public IStorageContainer CoreStorageContainer { get; private set; }
|
public IStorageContainer CoreStorageContainer { get; private set; }
|
||||||
public Session CoreStorageSession { get; private set; }
|
public SessionStorageContainer CoreStorageSession { get; private set; }
|
||||||
public Mapper CoreStorageMapper { get; private set; }
|
public Mapper CoreStorageMapper { get; private set; }
|
||||||
|
|
||||||
public CoreService()
|
public CoreService()
|
||||||
|
@ -79,7 +79,7 @@ namespace ln.provider
|
||||||
CoreStorageContainer = new FSStorageContainer("/var/cache/ln.provider");
|
CoreStorageContainer = new FSStorageContainer("/var/cache/ln.provider");
|
||||||
CoreStorageContainer.Open();
|
CoreStorageContainer.Open();
|
||||||
|
|
||||||
CoreStorageSession = new Session(CoreStorageContainer);
|
CoreStorageSession = new SessionStorageContainer(CoreStorageContainer);
|
||||||
CoreStorageMapper = new Mapper(CoreStorageSession);
|
CoreStorageMapper = new Mapper(CoreStorageSession);
|
||||||
|
|
||||||
CoreStorageMapper.EnsureIndex<AuthenticatedUser>("ID");
|
CoreStorageMapper.EnsureIndex<AuthenticatedUser>("ID");
|
||||||
|
@ -90,6 +90,8 @@ namespace ln.provider
|
||||||
Application.HttpServer.DefaultApplication = Application.WWWApplication;
|
Application.HttpServer.DefaultApplication = Application.WWWApplication;
|
||||||
Application.RPCContainer.Add("core",new RPC(Application));
|
Application.RPCContainer.Add("core",new RPC(Application));
|
||||||
|
|
||||||
|
Ready();
|
||||||
|
|
||||||
while (!StopRequested)
|
while (!StopRequested)
|
||||||
{
|
{
|
||||||
lock (this)
|
lock (this)
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="ProviderApplication.cs" />
|
<Compile Include="ProviderApplication.cs" />
|
||||||
|
<Compile Include="IPPoolService.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\ln.types\ln.types.csproj">
|
<ProjectReference Include="..\ln.types\ln.types.csproj">
|
||||||
|
@ -78,6 +79,11 @@
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
<None Include="www\style.css" />
|
<None Include="www\style.css" />
|
||||||
|
<None Include="www\ln.provider.js" />
|
||||||
|
<None Include="www\page.layout.css" />
|
||||||
|
<None Include="www\ln.provider.pool.js" />
|
||||||
|
<None Include="www\ln.provider.pool.html" />
|
||||||
|
<None Include="www\ln.provider.components.js" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
|
@ -2,38 +2,68 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<title>ln.provider</title>
|
<title>ln.provider Web Interface</title>
|
||||||
<link rel="stylesheet" href="style.css">
|
|
||||||
<script type="text/javascript" src="vue.js"></script>
|
<link href="/style.css" rel="stylesheet" />
|
||||||
<script type="text/javascript" src="ln.application.js"></script>
|
<link href="/page.layout.css" rel="stylesheet" />
|
||||||
|
<link href="/tables.layout.css" rel="stylesheet" />
|
||||||
|
|
||||||
|
<script type="text/javascript" src="/vue.js"></script>
|
||||||
|
<script type="text/javascript" src="/vue-router.js"></script>
|
||||||
|
<script type="text/javascript" src="/ln.tools.js"></script>
|
||||||
|
<script type="text/javascript" src="/ln.application.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="ln.provider.components.js"></script>
|
||||||
|
<script type="text/javascript" src="ln.provider.js"></script>
|
||||||
|
<script type="text/javascript" src="ln.provider.pool.js"></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script type="text/javascript">
|
<div id="body">
|
||||||
LN();
|
<div id="header">
|
||||||
</script>
|
<div class="logo">
|
||||||
|
<div style="background-color: #2a7fff; color: white;">ln.</div><div style="background-color: white;">provider</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="app">
|
<div id="navbar">
|
||||||
|
<router-link
|
||||||
<h1>{{ serverString }}</h1>
|
v-for="route in LNProvider.routes"
|
||||||
|
v-if="route.label"
|
||||||
|
v-bind:to="route.path"
|
||||||
|
>{{ route.label }}</router-link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="page">
|
||||||
|
<router-view
|
||||||
|
v-bind="{ LNP: LNP }"
|
||||||
|
></router-view>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="footer" class="flex row">
|
||||||
|
<div id="ServerString" class="silver">{{ LNP.serverString }}</div>
|
||||||
|
<div class="grow"></div>
|
||||||
|
<div id="ServerTime" class="" style="margin-right: 12px;">{{ LNP.serverTime }}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var providerCore = {
|
var LNP = new LNProvider();
|
||||||
serverString: "",
|
|
||||||
}
|
|
||||||
|
|
||||||
LN().rpc("core","GetServerString",[],function(result,error){
|
LNP
|
||||||
document.title = result;
|
.initialize()
|
||||||
providerCore.serverString = result;
|
.then(function(){
|
||||||
|
const router = new VueRouter({
|
||||||
|
routes: LNProvider.routes,
|
||||||
|
});
|
||||||
|
new Vue({
|
||||||
|
el: "#body",
|
||||||
|
data: {
|
||||||
|
LNP,
|
||||||
|
},
|
||||||
|
router,
|
||||||
|
}).$mount("#body");
|
||||||
});
|
});
|
||||||
|
|
||||||
var app = new Vue({
|
|
||||||
el: "#app",
|
|
||||||
data: providerCore,
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,336 +0,0 @@
|
||||||
var LN = (function(){
|
|
||||||
var appInterface;
|
|
||||||
|
|
||||||
var defaultOptions = {
|
|
||||||
url: null,
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class LNInterface {
|
|
||||||
constructor(opt){
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
this.options = {}
|
|
||||||
Object.assign(this.options,opt);
|
|
||||||
|
|
||||||
if (this.options.url == null)
|
|
||||||
this.options.url = this.constructURL();
|
|
||||||
|
|
||||||
|
|
||||||
this.rpcCallbacks = [];
|
|
||||||
this.rpcNextID = 1;
|
|
||||||
|
|
||||||
this.websocket = new WebSocket(this.options.url);
|
|
||||||
this.websocket.onerror = function(e){
|
|
||||||
alert("WebSocket caught error: " + e.date);
|
|
||||||
}
|
|
||||||
this.websocket.onmessage = function(e){
|
|
||||||
var j = JSON.parse(e.data);
|
|
||||||
if (j.state){
|
|
||||||
updateState(j.state);
|
|
||||||
} else if (j.id)
|
|
||||||
{
|
|
||||||
for (var n=0;n<self.rpcCallbacks.length;n++)
|
|
||||||
{
|
|
||||||
if (self.rpcCallbacks[n].id == j.id)
|
|
||||||
{
|
|
||||||
if (j.error)
|
|
||||||
{
|
|
||||||
console.log("RPCResult with error received: " + JSON.stringify(j.error));
|
|
||||||
}
|
|
||||||
self.rpcCallbacks[n].cbfn(j.result,j.error);
|
|
||||||
self.rpcCallbacks.splice(n,1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rpc(module,method,parameters,cbfn){
|
|
||||||
|
|
||||||
var rpcCall = {
|
|
||||||
module: module,
|
|
||||||
method: method,
|
|
||||||
parameters: parameters,
|
|
||||||
id: this.rpcNextID++,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (this.websocket.readyState != 1)
|
|
||||||
{
|
|
||||||
setTimeout(function(){
|
|
||||||
LN().rpc(module,method,parameters,cbfn);
|
|
||||||
},250);
|
|
||||||
} else {
|
|
||||||
this.rpcCallbacks.push( { id: rpcCall.id, cbfn: cbfn } );
|
|
||||||
this.websocket.send(
|
|
||||||
JSON.stringify(rpcCall)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
constructURL(){
|
|
||||||
var pageURI = window.location;
|
|
||||||
|
|
||||||
var scheme = pageURI.scheme == "https" ? "wss:" : "ws:";
|
|
||||||
var host = pageURI.host;
|
|
||||||
|
|
||||||
return scheme + "//" + host + "/socket";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return function(options){
|
|
||||||
if (!appInterface)
|
|
||||||
appInterface = new LNInterface(options);
|
|
||||||
return appInterface;
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
Object.values = function(o) {
|
|
||||||
var values = [];
|
|
||||||
for(var property in o) {
|
|
||||||
values.push(o[property]);
|
|
||||||
}
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
|
|
||||||
function encodeID( t )
|
|
||||||
{
|
|
||||||
return ("" + t).replace( /[\.\/]/g, "_");
|
|
||||||
}
|
|
||||||
|
|
||||||
var lagDetector = null;
|
|
||||||
|
|
||||||
function updateState(state)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (lagDetector)
|
|
||||||
clearTimeout(lagDetector);
|
|
||||||
|
|
||||||
$("#ServerTime").text("ServerTime: " + moment(state.currentTime).format());
|
|
||||||
|
|
||||||
lagDetector = setTimeout(function(){
|
|
||||||
$("#ServerTime").text("Server lag detected");
|
|
||||||
}, 2000);
|
|
||||||
|
|
||||||
} catch (e)
|
|
||||||
{
|
|
||||||
$("#ServerTime").text("Server state unexpected!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function SKYAPI(baseurl){
|
|
||||||
|
|
||||||
this.baseurl = baseurl;
|
|
||||||
this.refresh = []
|
|
||||||
|
|
||||||
this.websocket = new WebSocket("ws://localhost:8080/socket");
|
|
||||||
this.websocket.onerror = function(e){
|
|
||||||
alert("WebSocket Error: " + e);
|
|
||||||
}
|
|
||||||
this.websocket.onmessage = function(e){
|
|
||||||
var j = JSON.parse(e.data);
|
|
||||||
if (j.state){
|
|
||||||
updateState(j.state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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.__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;
|
|
||||||
if (json && !content)
|
|
||||||
handler( JSON.parse( responseText ) );
|
|
||||||
else
|
|
||||||
handler( responseText );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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, null, j );
|
|
||||||
}
|
|
||||||
|
|
||||||
this.call = function(endpoint,method,parameters = [], receiver = null){
|
|
||||||
var x = new XMLHttpRequest();
|
|
||||||
|
|
||||||
x.open("POST", this.baseurl + endpoint, (receiver != null));
|
|
||||||
x.setRequestHeader("content-type","application/json");
|
|
||||||
|
|
||||||
if (receiver)
|
|
||||||
{
|
|
||||||
x.onload = function(){ var r = JSON.parse(this.responseText).Result; receiver(r); }
|
|
||||||
x.onerror = function(){ receiver(false); }
|
|
||||||
}
|
|
||||||
|
|
||||||
var methodCall = {
|
|
||||||
"MethodName": method,
|
|
||||||
"Parameters": parameters
|
|
||||||
}
|
|
||||||
|
|
||||||
x.send(JSON.stringify(methodCall));
|
|
||||||
|
|
||||||
if (!receiver)
|
|
||||||
{
|
|
||||||
var result = JSON.parse(x.responseText);
|
|
||||||
if (result.Exception != null)
|
|
||||||
throw result.Exception;
|
|
||||||
|
|
||||||
return result.Result;
|
|
||||||
}
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
{
|
|
||||||
$("#content").empty();
|
|
||||||
$("#content").append(this.responseText);
|
|
||||||
history.pushState(null, page, skyapi().baseurl + page);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.refresh = []
|
|
||||||
|
|
||||||
x.send();
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.fireOnLoad = function(element){
|
|
||||||
if (element.onload != null)
|
|
||||||
{
|
|
||||||
element.onload();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var n=0;n<element.children.length;n++)
|
|
||||||
this.fireOnLoad(element.children[n]);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.__refresh_index = 0;
|
|
||||||
this.UIRefresh = function(){
|
|
||||||
|
|
||||||
this.__refresh_index++;
|
|
||||||
|
|
||||||
for (var n=0;n<this.refresh.length;n++)
|
|
||||||
{
|
|
||||||
var r = this.refresh[n];
|
|
||||||
if ((this.__refresh_index % r.interval)==0)
|
|
||||||
r.refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
setInterval( function(){ skyapi().UIRefresh(); }, 1000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
function showStatistics(stats)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$("#ServerTime").text("ServerTime: " + stats.ServerTime);
|
|
||||||
|
|
||||||
$("#indHttpServer").attr("state",stats.States.HttpServer);
|
|
||||||
$("#indManager").attr("state",stats.States.Manager);
|
|
||||||
$("#indCrawler").attr("state",stats.States.Crawler);
|
|
||||||
$("#indChecks").attr("state",stats.States.Checks);
|
|
||||||
$("#indDispatcher").attr("state",stats.States.Dispatcher);
|
|
||||||
|
|
||||||
$("#indHttpServer").attr("title",stats.States.HttpServer);
|
|
||||||
$("#indManager").attr("title",stats.States.Manager);
|
|
||||||
$("#indCrawler").attr("title",stats.States.Crawler);
|
|
||||||
$("#indChecks").attr("title",stats.States.Checks);
|
|
||||||
$("#indDispatcher").attr("title",stats.States.Dispatcher);
|
|
||||||
|
|
||||||
} catch (e)
|
|
||||||
{
|
|
||||||
$("#ServerTime").text("Server unreachable");
|
|
||||||
|
|
||||||
$("#indHttpServer").attr("state",3);
|
|
||||||
$("#indManager").attr("state",0);
|
|
||||||
$("#indCrawler").attr("state",0);
|
|
||||||
$("#indChecks").attr("state",0);
|
|
||||||
$("#indDispatcher").attr("state",0);
|
|
||||||
|
|
||||||
$("#indHttpServer").attr("title","UNKNOWN");
|
|
||||||
$("#indManager").attr("title","UNKNOWN");
|
|
||||||
$("#indCrawler").attr("title","UNKNOWN");
|
|
||||||
$("#indChecks").attr("title","UNKNOWN");
|
|
||||||
$("#indDispatcher").attr("title","UNKNOWN");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateStatistics()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var request = skyapi().call("api/management","GetStatistics",[],showStatistics);
|
|
||||||
} catch (e)
|
|
||||||
{
|
|
||||||
showStatistics(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var __skyapi = new SKYAPI("/");
|
|
||||||
|
|
||||||
function skyapi()
|
|
||||||
{
|
|
||||||
return __skyapi;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function ScaleSI(value)
|
|
||||||
{
|
|
||||||
if (value > 1000000000)
|
|
||||||
return ((value / 1000000000) | 0) + "G";
|
|
||||||
if (value > 1000000)
|
|
||||||
return ((value / 1000000) | 0) + "M";
|
|
||||||
if (value > 1000)
|
|
||||||
return ((value / 1000) | 0) + "k";
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
Vue.component('toggle-pane',{
|
||||||
|
props: {
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
label: String,
|
||||||
|
class: String,
|
||||||
|
},
|
||||||
|
data: function(){
|
||||||
|
return {
|
||||||
|
};
|
||||||
|
},
|
||||||
|
template: `
|
||||||
|
<div class="toggle-pane">
|
||||||
|
<button
|
||||||
|
@click="visible = !visible"
|
||||||
|
>{{ label }}</button>
|
||||||
|
<div
|
||||||
|
v-if="visible"
|
||||||
|
><slot></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
});
|
|
@ -0,0 +1,92 @@
|
||||||
|
var LNProvider = (function(){
|
||||||
|
|
||||||
|
class LNProvider
|
||||||
|
{
|
||||||
|
constructor(options){
|
||||||
|
let self = this;
|
||||||
|
|
||||||
|
this.serverString = "N/A";
|
||||||
|
this.serverTime = "N/A";
|
||||||
|
|
||||||
|
this.lagDetector = null;
|
||||||
|
|
||||||
|
this.IPAllocations = [];
|
||||||
|
|
||||||
|
LN().option("wsError",(e)=>self.wsError(e));
|
||||||
|
LN().option("wsClose",(e)=>self.wsClose(e));
|
||||||
|
LN().option("wsUpdate",(e)=>self.wsUpdate(e));
|
||||||
|
|
||||||
|
LN().connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize(){
|
||||||
|
return Promise.all(LNProvider.initializers);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadIPAllocations(){
|
||||||
|
let self = this;
|
||||||
|
console.log("loadIPAllocations()");
|
||||||
|
LN().rpc("ippool","GetAllocations",[],function(r,e){
|
||||||
|
self.IPAllocations = r;
|
||||||
|
console.log("IPA: " + JSON.stringify(r));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
allocate(type,cidr,maskWidth,zone,usage,splitZone){
|
||||||
|
let self = this;
|
||||||
|
|
||||||
|
if (type == 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
} else if (type == 1)
|
||||||
|
{
|
||||||
|
LN().rpc("ippool","AllocateCIDR",[zone,cidr,usage,splitZone],function(r,e){
|
||||||
|
if (e){
|
||||||
|
alert("Error: \n" + JSON.stringify(e));
|
||||||
|
} else {
|
||||||
|
self.IPAllocations.push(r);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
wsUpdate(state)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (this.lagDetector)
|
||||||
|
clearTimeout(this.lagDetector);
|
||||||
|
|
||||||
|
this.serverTime = moment(state.currentTime).format();
|
||||||
|
|
||||||
|
this.lagDetector = setTimeout(function(){
|
||||||
|
this.serverTime = "Server lag detected";
|
||||||
|
}, 2000);
|
||||||
|
|
||||||
|
} catch (e)
|
||||||
|
{
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wsError(e){
|
||||||
|
this.serverTime = "WebSocket: Error: " + JSON.stringify(e);
|
||||||
|
}
|
||||||
|
wsClose(e){
|
||||||
|
this.serverTime = "WebSocket: Connection lost";
|
||||||
|
setTimeout(function(){
|
||||||
|
LN().connect();
|
||||||
|
}, 2500 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LNProvider.routes = [];
|
||||||
|
LNProvider.initializers = [];
|
||||||
|
|
||||||
|
|
||||||
|
return LNProvider;
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
<div>
|
||||||
|
<h1>IP Pools</h1>
|
||||||
|
<toggle-pane
|
||||||
|
label="Allokationsparameter..."
|
||||||
|
:visible="true"
|
||||||
|
>
|
||||||
|
<div class="flex row">
|
||||||
|
<span>
|
||||||
|
<label for="allocFree">Freie Allokation</label>
|
||||||
|
<input type="radio" id="allocFree" v-model="allocationType" value="0"><br>
|
||||||
|
<label for="allocCIDR">CIDR Allokation</label>
|
||||||
|
<input type="radio" id="allocCIDR" v-model="allocationType" value="1"><br>
|
||||||
|
</span>
|
||||||
|
<fieldset
|
||||||
|
v-if="allocationType == 0"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<span>Maskenlänge:</span>
|
||||||
|
<span><input type="number" min="1" max="127" v-model="subnetWidth"></span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>Netzbreite:</span>
|
||||||
|
<span><input type="number" min="1" max="127" v-model="allocationWidth"></span>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset
|
||||||
|
v-if="allocationType == 1"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<span>Zielnetz:</span>
|
||||||
|
<span><input type="text" v-model="targetCIDR"></span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="independentAllocation">Unabhängige Allokation</label>
|
||||||
|
<input type="checkbox" id="independentAllocation" v-model="independentAllocation">
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<span>Verwendung:</span>
|
||||||
|
<span><input type="text" v-model="allocationUsage"></span>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
</toggle-pane>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td>Aktionen</td>
|
||||||
|
<td>CIDR</td>
|
||||||
|
<td>Name</td>
|
||||||
|
<td>Pool</td>
|
||||||
|
<td>Verwendungsnachweis</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr
|
||||||
|
v-for="ipa in IPAllocations"
|
||||||
|
>
|
||||||
|
<td>
|
||||||
|
<button
|
||||||
|
@click="LNP.allocate(allocationType,targetCIDR,subnetWidth,ipa.CIDR,allocationUsage,!independentAllocation);"
|
||||||
|
>+</button>
|
||||||
|
</td>
|
||||||
|
<td>{{ ipa.CIDR }}</td>
|
||||||
|
<td>{{ ipa.Name }}</td>
|
||||||
|
<td>{{ ipa.Pool }}</td>
|
||||||
|
<td>{{ ipa.AllocatedTo }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
|
@ -0,0 +1,45 @@
|
||||||
|
LNProvider.initializers.push(
|
||||||
|
new Promise((resolve,reject)=>{
|
||||||
|
LN()
|
||||||
|
.load("/ln.provider.pool.html")
|
||||||
|
.then((template)=>{
|
||||||
|
LNProvider.routes.push(
|
||||||
|
{
|
||||||
|
path: "/ippool",
|
||||||
|
label: "IP Pool",
|
||||||
|
component: {
|
||||||
|
props: {
|
||||||
|
LNP: Object,
|
||||||
|
},
|
||||||
|
template: template,
|
||||||
|
data: function(){
|
||||||
|
return {
|
||||||
|
allocationWidth: 64,
|
||||||
|
targetCIDR: "",
|
||||||
|
independentAllocation: false,
|
||||||
|
allocationType: 0,
|
||||||
|
allocationUsage: "",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
IPAllocations: ()=>LNP.IPAllocations,
|
||||||
|
subnetWidth: {
|
||||||
|
get: function(){
|
||||||
|
return 128 - this.allocationWidth;
|
||||||
|
},
|
||||||
|
set: function(v){
|
||||||
|
this.allocationWidth = 128 - v;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
beforeRouteEnter: function(to,from,next){
|
||||||
|
LNP.loadIPAllocations();
|
||||||
|
next();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
|
@ -0,0 +1,145 @@
|
||||||
|
|
||||||
|
html {
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
font-size: 12px;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
bottom: 0px;
|
||||||
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#body {
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header {
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
|
||||||
|
border-bottom: 1px solid black;
|
||||||
|
background-color: #bad6ff;
|
||||||
|
padding: 4px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#header > div {
|
||||||
|
margin: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navbar {
|
||||||
|
padding: 8px;
|
||||||
|
|
||||||
|
border-bottom: 1px solid black;
|
||||||
|
|
||||||
|
font-size: 16px;
|
||||||
|
color: #808080;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navbar > a {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 16px;
|
||||||
|
margin-right: 16px;
|
||||||
|
|
||||||
|
}
|
||||||
|
#navbar > a.router-link-active {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
#page {
|
||||||
|
padding: 16px;
|
||||||
|
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
#page::after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
height: 16px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
height: 20px;
|
||||||
|
padding: 6px;
|
||||||
|
padding-left: 24px;
|
||||||
|
background-color: #bad6ff;
|
||||||
|
border-top: 1px solid black;
|
||||||
|
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.DISABLED {
|
||||||
|
color: #D0D0D0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
fieldset > div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
margin: 4px;
|
||||||
|
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset > div > * {
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
fieldset > div > *:first-child {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.toggle-pane {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
.toggle-pane > div {
|
||||||
|
display: block;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
height: 16px;
|
||||||
|
|
||||||
|
border: 1px solid #bad6ff;
|
||||||
|
border-radius: 3px;
|
||||||
|
|
||||||
|
padding: 4px;
|
||||||
|
}
|
|
@ -25,3 +25,32 @@ div.app {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
display: inline-block;
|
||||||
|
border: 1px solid black;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 800;
|
||||||
|
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.logo > div {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex.row {
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
.flex.column {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex > * {
|
||||||
|
margin: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
table tr {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
table td {
|
||||||
|
padding: 4px;
|
||||||
|
border-bottom: 1px solid #D0D0D0;
|
||||||
|
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
table > thead {
|
||||||
|
font-style: italic;
|
||||||
|
background-color: #bad6ff;
|
||||||
|
transition: background-color 1000ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
table > thead tr {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
table > thead td {
|
||||||
|
}
|
||||||
|
|
||||||
|
table > tbody tr {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
table > tbody td {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
table > tfoot tr {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
table > tfoot td {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
table > tbody > tr:hover > td {
|
||||||
|
border-top: 2px solid black;
|
||||||
|
border-bottom: 2px solid black;
|
||||||
|
}
|
Loading…
Reference in New Issue