ln.provider/IPPoolService.cs

199 lines
5.0 KiB
C#

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;
using ln.types.net;
namespace ln.provider
{
public class IPPoolService : ApplicationServiceBase
{
CoreService CoreService { get; set; }
ProviderApplication Application => base.CurrentApplication as ProviderApplication;
RPC rpc;
SessionStorageContainer mapperSession;
Mapper mapper;
IPAllocation v6Root;
IPAllocation v4Root;
public IPPoolService()
:base("IPPoolService")
{
DependOnService<CoreService>();
rpc = new RPC(this);
}
public override void ServiceMain(Application 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))
{
IPAllocation split = null;
foreach (IPv6 splitCIDR in allocation.CIDR.Split(1))
{
if (splitCIDR.Contains(cidr))
{
split = GetAllocation(splitCIDR);
if (split == null)
{
split = new IPAllocation(splitCIDR,allocation.CIDR);
mapper.Save(split);
break;
}
else if (Equals(String.Empty,split.AllocatedTo))
{
break;
}
throw new ArgumentOutOfRangeException(String.Format("No subnet available below {0}",allocation.CIDR.ToCIDR()));
}
}
allocation = split;
}
allocation.AllocatedTo = usage;
mapper.Save(allocation);
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;
}
}
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;
}
}
}
}