Commit 292ab1b4 authored by Alberts S's avatar Alberts S
Browse files

add DNS A/PTR support

parent a2738ead
......@@ -4,6 +4,7 @@ import itertools
from CapybaraNetty import CapybaraNetty
from ControllerStatic import ControllerStatic
from Dns import Dns
from Inventory import Inventory
from Pinger import Pinger
from Router import Router
......@@ -20,6 +21,7 @@ class Controller(CapybaraNetty):
self.tunnel_network_base = ipaddress.ip_network(self.config["tunnel_network_base"]).subnets(new_prefix=30)
self.dummy_network_base = ipaddress.ip_network(self.config["dummy_network_base"]).subnets(new_prefix=32)
self.controller = ControllerStatic(routers=self.routers)
self.dns = Dns()
@classmethod
async def run(cls):
......@@ -61,6 +63,7 @@ class Controller(CapybaraNetty):
router_coroutines.append(router.add_default_dummy_interface_ip(ip=self.get_dummy_ip()))
await asyncio.gather(*router_coroutines)
await asyncio.gather(self.set_router_interface_tunnels())
await self.setup_router_dns()
self.load_pingers()
concurrent_tasks = [
......@@ -153,3 +156,28 @@ class Controller(CapybaraNetty):
}
)
return pinger_data
async def setup_router_dns(self):
router_interfaces = []
# list of router_name, interface_name, ip
for router in self.routers:
for interface_name, value in router.managed_interfaces.items():
router_interfaces.append(
{"name": router.name_simplified, "interface_name": interface_name, "ip": value["ip"]}
)
ptr_records = []
for interface in router_interfaces:
ptr_records.append(
{
"name": interface["name"],
"ip": interface["ip"].ip,
}
)
self.dns.create_ptr_records(ptr_records)
records = []
for router in self.routers:
records.append({"name": router.name_simplified, "ip": ipaddress.ip_address(router.ip)})
self.dns.create_records(records)
import ipaddress
import pdns_cli.models as pdns_models
from pdns_cli.api import PDNSAPI
from CapybaraNetty import CapybaraNetty
class Dns(CapybaraNetty):
def __init__(self):
super().__init__()
self.api = PDNSAPI(self.config["dns_pdns_api_endpoint"])
self.api.session.headers.update({"X-Api-Key": self.config["dns_pdns_api_key"]})
self.ptr_zone = self.api.server("localhost").zone(self.config["dns_ptr_zone"])
self.name_zone = self.api.server("localhost").zone(self.config["dns_name_zone"])
if self.config["dns_ptr_delete_existing"]:
rrsets = self.ptr_zone.rrsets
self.ptr_zone.update_rrsets([x for x in rrsets if x.type == "PTR"], delete=True)
if self.config["dns_name_delete_existing"]:
rrsets = self.name_zone.rrsets
self.name_zone.update_rrsets([x for x in rrsets if x.type == "A"], delete=True)
def create_ptr_records(self, records: list[dict[str, ipaddress.ip_address]]):
# expects records=[{'name': 'x' 'ip': IPv4Address('10.88.224.0/32')}]
new_rrsets = set()
for record in records:
ptr = pdns_models.RRset(name=f"{record['ip'].reverse_pointer}.", type="PTR", ttl=60)
ptr.records.add(pdns_models.Record(content=f"{record['name']}.local."))
new_rrsets.add(ptr)
self.ptr_zone.update_rrsets(new_rrsets)
self.__logger.info(f"Created {len(new_rrsets)} PTR records")
def create_records(self, records: list[dict[str, ipaddress.ip_address]]):
# expects records=[{'name': 'x' 'ip': IPv4Address('10.88.224.0/32')}]
new_rrsets = set()
for record in records:
r = pdns_models.RRset(name=f"{record['name']}.{self.name_zone.id}", type="A", ttl=60)
r.records.add(pdns_models.Record(content=f"{record['ip']}"))
new_rrsets.add(r)
self.name_zone.update_rrsets(new_rrsets)
self.__logger.info(f"Created {len(new_rrsets)} A records")
......@@ -21,6 +21,7 @@ class Router(CapybaraNetty):
self.interface_prefix = self.config["router_interface_prefix"]
self.interfaces = []
self.interface_group_id = self.config["router_interface_group_id"]
self.managed_interfaces = {}
self.dummy_interface_name = self.config["router_dummy_interface_name"]
@classmethod
......@@ -61,7 +62,6 @@ class Router(CapybaraNetty):
await self.vty.del_config_routes(self.config_routes)
def get_default_interface_name(self):
self.__logger.debug(f"{self.log_format_ip(self.ip)} has {len(self.routes)} routes")
try:
default_route = next(route for route in self.routes if route["prefix"] == "0.0.0.0/0")
self.default_interface_name = default_route["nexthops"][0]["interfaceName"]
......@@ -94,6 +94,13 @@ class Router(CapybaraNetty):
else:
raise
self.interfaces = []
self.del_managed_interfaces_info()
def add_managed_interface_info(self, name, ip: ipaddress.ip_interface):
self.managed_interfaces.update({name: {"interface_name": name, "ip": ip}})
def del_managed_interfaces_info(self):
self.managed_interfaces = {}
async def add_gre_interface(
self, interface_name, local_ip: ipaddress.ip_address, remote_ip: ipaddress.ip_address, ttl=255
......@@ -111,6 +118,7 @@ class Router(CapybaraNetty):
interface_name = self.get_interface_name(interface_name)
command = f"sudo ip addr add {str(ip)} dev {interface_name} && sudo ip link set {interface_name} up"
await self.ssh_exec(command)
self.add_managed_interface_info(interface_name, ip)
async def add_default_dummy_interface_ip(self, ip: ipaddress.ip_interface):
await self.add_interface_ip(self.dummy_interface_name, ip)
......
......@@ -60,7 +60,7 @@ class Visualizer(CapybaraNetty):
for key, path in paths.items():
if len(path) > 2 and not (
path[0] in self.external_targets_for_optimizations
and path[-1] in self.external_targets_for_optimizations
or path[-1] in self.external_targets_for_optimizations
):
optimized_ms = G[key][path[0]]["weight"] - lengths[key]
if optimized_ms < self.optimization_threshold_ms:
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment