#!/usr/bin/env python3

# SPDX-FileCopyrightText: © 2021 Open Networking Foundation <support@opennetworking.org>
# SPDX-License-Identifier: Apache-2.0

# tenant_validator.py
# Grab the data from Tenant and check if the information is invalidate

from __future__ import absolute_import

import argparse
import logging
import re
import sys

import netaddr
import pynetbox
import requests
import yaml

logging.basicConfig()
logger = logging.getLogger("TenentValidator")

# The Global variable shared with different netbox api caller function
netboxapi = None
netbox_config = None
misconfs = list()

# The consistent variable should be same in every devices, prefixes of the deployment
site_name = None
deployment_name = None

# A Regex rule to identify if device name is a valid domain
fqdn_regex = re.compile(
    r"^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*"
    + r"([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$"
)


class Configuration:

    mapping_dict = {
        logging.ERROR: logger.error,
        logging.WARN: logger.warn,
        logging.INFO: logger.info,
    }

    def __init__(self, obj, message, level=logging.ERROR):
        self.level = level
        self.obj = obj
        self.message = message

        # self.mapping_dict[level](self)

    def __repr__(self):
        return "[%s] object %s: %s\nRef. %s" % (
            "/".join(self.obj.url.split("/")[-4:-2]),
            self.obj,
            self.message,
            self.obj.url.replace("10.76.28.11", "netbox.infra.onlab.us").replace(
                "api/", ""
            ),
        )


def get_object_type(obj):
    return ("/".join(obj.url.split("/")[-4:-2]),)


def validate_vlans(vlans=None):
    global misconfs

    for vlan in vlans:
        if not vlan.group:
            misconfs.append(Configuration(vlan, "VLAN group isn't set"))
        if not vlan.site:
            misconfs.append(Configuration(vlan, "VLAN site isn't set"))
        if not vlan.tenant:
            misconfs.append(Configuration(vlan, "VLAN tenant isn't set"))


def validate_prefixes(prefixes=None):
    global misconfs

    tenant_dict = dict()

    for prefix in prefixes:
        netmask = prefix.prefix.split("/")[-1]

        if not re.search(fqdn_regex, prefix.description):
            misconfs.append(Configuration(prefix, "Description (FQDN) is invalid"))
        else:
            device = netboxapi.dcim.devices.filter(tenant_id=prefix.tenant.id)[0]
            if device:
                sitename = device.name.split(".")[-1]
                if sitename not in prefix.description:
                    misconfs.append(
                        Configuration(prefix, "Site name should in the prefix FQDN")
                    )

        if not prefix.tenant:
            misconfs.append(Configuration(prefix, "Tenant isn't set"))
        else:
            tenant_dict.setdefault(prefix.tenant, dict())
            tenant_dict[prefix.tenant].setdefault(netmask, list())
            tenant_dict[prefix.tenant][netmask].append(prefix)

    # Assume prefixes in different tenants don't have the intersection
    # So parent prefix only check if it has a DHCP sub-prefix in same tenant
    for prefixes_by_tenant in tenant_dict.values():
        for netmask, prefixes_by_netmask in prefixes_by_tenant.items():
            for prefix in prefixes_by_netmask:
                if int(netmask) < 26:
                    children = [
                        child
                        for key, value in prefixes_by_tenant.items()
                        if int(key) > int(netmask)
                        for child in value
                    ]

                    children = [
                        child
                        for child in children
                        if str(
                            netaddr.IPNetwork(
                                child.prefix.split("/")[0] + "/" + netmask
                            ).cidr
                        )
                        == prefix.prefix
                    ]
                    if children:
                        continue

                    dhcp_addr = list(
                        filter(
                            lambda ip: ip.status.value == "dhcp",
                            netboxapi.ipam.ip_addresses.filter(parent=prefix.prefix),
                        )
                    )

                    if not dhcp_addr:
                        misconfs.append(
                            Configuration(prefix, "DHCP subnet not found in prefix")
                        )
                        continue

                    if len(dhcp_addr) > 1:
                        misconfs.append(
                            Configuration(
                                prefix, "Prefix should have exact 1 DHCP subnet"
                            )
                        )
                        continue

                    dhcp_range = dhcp_addr[0].address
                    ip_addrs = netboxapi.ipam.ip_addresses.filter(parent=dhcp_range)
                    ip_addrs = ip_addrs.remove(dhcp_addr[0])
                    if ip_addrs:
                        misconfs.append(
                            Configuration(
                                prefix,
                                "DHCP range %s contains other IP addresses: %s"
                                % (dhcp_range, ip_addrs),
                            )
                        )


def validate_ip_addresses(ip_addresses=None):
    global misconfs
    prefix_dict = dict()

    for ip_address in ip_addresses:

        if netaddr.IPNetwork(ip_address.address).network.is_private():
            if not ip_address.vrf:
                misconfs.append(
                    Configuration(ip_address, "VRF isn't set for this IP address")
                )
            else:
                prefix = str(netaddr.IPNetwork(ip_address.address).cidr)
                if prefix not in prefix_dict:
                    prefix_dict[prefix] = netboxapi.ipam.prefixes.get(prefix=prefix)

                if prefix_dict[prefix] and prefix_dict[prefix].vrf != ip_address.vrf:
                    misconfs.append(
                        Configuration(ip_address, "VRF isn't match with Prefix")
                    )


def validate_interfaces(interfaces=None):
    global misconfs

    for interface in interfaces:
        count_ips = 0

        if get_object_type(interface) == "virtualization/interfaces":
            count_ips = len(
                netboxapi.ipam.ip_addresses.filter(vminterface_id=interface.id)
            )
        elif get_object_type(interface) == "dcim/interfaces":
            count_ips = interface.count_ipaddresses

        if count_ips > 0 and not interface.mac_address:
            misconfs.append(
                Configuration(
                    interface,
                    "VM Interface has IP address assigned but mac address isn't set",
                )
            )

        if (
            get_object_type(interface) == "dcim/interfaces"
            and interface.type.value == "virtaul"
            and (not interface.mgmt_only or not interface.tagged_vlans)
        ):
            misconfs.append(
                Configuration(
                    interface,
                    "Virtual interface should be management only or VLAN interface",
                )
            )

        if interface.tagged_vlans:
            if len(interface.tagged_vlans) > 1:
                misconfs.append(
                    Configuration(interface, "Virtual Interface has multiple VLANs set")
                )
            elif str(interface.tagged_vlans[0].vid) not in interface.name:
                misconfs.append(
                    Configuration(
                        interface, "Virtual Interface name not match to VLAN ID"
                    )
                )


def validate_vrfs(vrfs=None):
    global misconfs

    for vrf in vrfs:
        if not vrf.enforce_unique:
            misconfs.append(
                Configuration(vrf, "VRF doesn't have enforce_unique set as True")
            )

        if not vrf.tenant:
            misconfs.append(Configuration(vrf, "VRF doesn't have tenant set"))


def validate_machines(machines=None):
    global misconfs

    tenant_info = dict()

    for machine in machines:
        if not re.search(fqdn_regex, machine.name):
            misconfs.append(
                Configuration(
                    machine, "Device/VM FQDN name %s is invalid" % machine.name
                )
            )

        if not machine.tenant:
            misconfs.append(Configuration(machine, "Device/VM doesn't have tenant set"))

        segments = machine.name.split(".")
        if len(segments) != 3:
            misconfs.append(
                Configuration(
                    machine,
                    "Device/VM FQDN should have 3 segments, found %d" % len(segments),
                )
            )
        elif machine.tenant:
            if machine.tenant not in tenant_info:
                tenant_info.setdefault(
                    machine.tenant, {"deployment": segments[1], "site": segments[2]}
                )
            else:
                deployment = tenant_info[machine.tenant]["deployment"]
                site = tenant_info[machine.tenant]["site"]
                if deployment != segments[1] or site != segments[2]:
                    misconfs.append(
                        Configuration(
                            machine,
                            "Deployment or Site name is not consistent with other Device/VM",
                        )
                    )

        if (
            (
                machine.__class__.__name__ == "Devices"
                and machine.device_role.name in ["Router", "Switch", "Server"]
            )
            or machine.__class__.__name__ == "VirtualMachines"
        ) and not machine.primary_ip:
            misconfs.append(
                Configuration(machine, "Primary IP must be set for this Device/VM")
            )


def validate_tenants(tenants=None):
    global misconfs

    for tenant in tenants:
        if tenant.device_count == 0:
            misconfs.append(Configuration(tenant, "0 device was found for this tenant"))
        if tenant.prefix_count == 0:
            misconfs.append(Configuration(tenant, "0 prefix was found for this tenant"))
        if tenant.vrf_count == 0:
            misconfs.append(Configuration(tenant, "0 vrf was found for this tenant"))

        devices = list(netboxapi.dcim.devices.filter(tenant_id=tenant.id))
        mgmtserver = list(filter(lambda d: d.device_role.name == "Router", devices))
        if len(mgmtserver) != 1:
            misconfs.append(
                Configuration(tenant, "Tenant must have exact 1 Router (mgmtserver)")
            )


def get_objects(tenant_name=""):
    return_dict = dict()

    tenants = list(netboxapi.tenancy.tenants.filter(name=tenant_name))
    if len(tenants) == 0:
        logger.critical("Tenant name %s wasn't found in Netbox", tenant_name)
        sys.exit(1)
    tenant_id = None if len(tenants) != 1 else tenants[0].id

    # If the tenant_id is None, then Netbox API will return all objects by default
    devices = list(netboxapi.dcim.devices.filter(tenant_id=tenant_id))
    virtual_machines = list(
        netboxapi.virtualization.virtual_machines.filter(tenant_id=tenant_id)
    )

    physical_interfaces = list()
    for device in devices:
        physical_interfaces.extend(
            list(netboxapi.dcim.interfaces.filter(device_id=device.id))
        )

    virtual_interfaces = list()
    for virtual_machine in virtual_machines:
        virtual_interfaces.extend(
            list(
                netboxapi.virtualization.interfaces.filter(
                    virtual_machine_id=virtual_machine.id
                )
            )
        )

    vrfs = list(netboxapi.ipam.vrfs.filter(tenant_id=tenant_id))
    vlans = list(netboxapi.ipam.vlans.filter(tenant_id=tenant_id))
    ip_addresses = list(netboxapi.ipam.ip_addresses.filter(tenant_id=tenant_id))

    prefixes = list()
    for vrf in vrfs:
        prefixes.extend(list(netboxapi.ipam.prefixes.filter(vrf_id=vrf.id)))

    return_dict = {
        "tenants": tenants,
        "devices": devices,
        "physical_interfaces": physical_interfaces,
        "virtual_machines": virtual_machines,
        "virtual_interfaces": virtual_interfaces,
        "vrfs": vrfs,
        "prefixes": prefixes,
        "vlans": vlans,
        "ip_addresses": ip_addresses,
    }

    return return_dict


if __name__ == "__main__":

    parser = argparse.ArgumentParser(description="Netbox Tenant Validator")
    parser.add_argument(
        "settings",
        type=argparse.FileType("r"),
        help="YAML Ansible inventory file w/NetBox API token",
    )

    args = parser.parse_args()
    netbox_config = yaml.safe_load(args.settings.read())
    netboxapi = pynetbox.api(
        netbox_config["api_endpoint"], token=netbox_config["token"], threading=True
    )

    if not netbox_config.get("validate_certs", True):
        session = requests.Session()
        session.verify = False
        netboxapi.http_session = session

    mapping_func = {
        "tenants": validate_tenants,
        "devices": validate_machines,
        "physical_interfaces": validate_interfaces,
        "virtual_machines": validate_machines,
        "virtual_interfaces": validate_interfaces,
        "vrfs": validate_vrfs,
        "vlans": validate_vlans,
        "prefixes": validate_prefixes,
        "ip_addresses": validate_ip_addresses,
    }

    netbox_data = get_objects(netbox_config.get("tenant_name", ""))

    for key, validate_func in mapping_func.items():
        if netbox_data[key]:
            validate_func(netbox_data[key])

    if not misconfs:
        print("All checks passed.")
    else:
        for misconf in misconfs:
            print(misconf)
