Skip to content
Snippets Groups Projects
nren_access.py 4.94 KiB
import json
import os
import jinja2
from concurrent.futures import ProcessPoolExecutor
from brian_dashboard_manager.templating.render import create_dropdown_panel, \
    create_panel_target
from brian_dashboard_manager.templating.helpers import \
    is_aggregate_interface, is_logical_interface, is_physical_interface, \
    num_generator, gridPos_generator, letter_generator, \
    get_panel_definitions, flatten


def get_nrens(interfaces):
    result = {}
    for interface in interfaces:

        description = interface.get('description', '').strip()

        nren_name = description.split(' ')[2].upper()

        nren = result.get(
            nren_name, {'AGGREGATES': [], 'SERVICES': [], 'PHYSICAL': []})

        interface_name = interface.get('name')
        host = interface.get('router', '')
        router = host.replace('.geant.net', '')
        panel_title = f"{router} - {{}} - {interface_name} - {description}"

        if is_aggregate_interface(interface):
            nren['AGGREGATES'].append({
                'interface': interface_name,
                'hostname': host,
                'alias': f"{host.split('.')[1].upper()} - {nren_name}"
            })

            # link aggregates are also shown
            # under the physical dropdown
            nren['PHYSICAL'].append({
                'title': panel_title,
                'hostname': host,
                'interface': interface_name
            })

        elif is_logical_interface(interface):
            nren['SERVICES'].append({
                'title': panel_title,
                'hostname': host,
                'interface': interface_name
            })
        elif is_physical_interface(interface):
            nren['PHYSICAL'].append({
                'title': panel_title,
                'hostname': host,
                'interface': interface_name
            })

        result[nren_name] = nren
    return result


# start IDs from 3 since aggregate
# panels have hardcoded IDs (1, 2).
id_gen = num_generator(start=3)

# aggregate panels have y=0, start generating at 1*height
gridPos = gridPos_generator(id_gen, start=1)


# Aggregate panels have unique targets,
# handle those here.
def get_aggregate_targets(aggregates):
    ingress = []
    egress = []

    # used to generate refIds
    letters = letter_generator()

    for target in aggregates:
        ref_id = next(letters)
        in_data = {
            **target,
            'alias': f"{target['alias']} - Ingress Traffic",
            'refId': ref_id,
            'select_field': 'ingress'
        }
        out_data = {
            **target,
            'alias': f"{target['alias']} - Egress Traffic",
            'refId': ref_id,
            'select_field': 'egress'
        }
        ingress_target = create_panel_target(in_data)
        egress_target = create_panel_target(out_data)
        ingress.append(ingress_target)
        egress.append(egress_target)

    return ingress, egress


def get_dashboard_data(interfaces, datasource):
    with ProcessPoolExecutor(max_workers=4) as executor:

        def get_panels(data):
            for panel in data:
                yield executor.submit(
                    get_panel_definitions,
                    {
                        **panel,
                        **next(gridPos)
                    },
                    datasource
                )

        nren_data = executor.submit(get_nrens, interfaces).result()
        for nren, data in nren_data.items():

            services_dropdown = create_dropdown_panel(
                'Services', **next(gridPos))
            services = get_panels(data['SERVICES'])
            iface_dropdown = create_dropdown_panel(
                'Interfaces', **next(gridPos))
            physical = get_panels(data['PHYSICAL'])
            agg_ingress, agg_egress = executor.submit(
                get_aggregate_targets, data['AGGREGATES']).result()

            yield {
                'nren_name': nren,
                'datasource': datasource,
                'ingress_aggregate_targets': agg_ingress,
                'egress_aggregate_targets': agg_egress,
                'dropdown_groups': [
                    {
                        'dropdown': services_dropdown,
                        'panels': flatten([p.result() for p in services]),
                    },
                    {
                        'dropdown': iface_dropdown,
                        'panels': flatten([p.result() for p in physical]),
                    }
                ]
            }


def generate_nrens(interfaces, datasource):
    file = os.path.abspath(os.path.join(
        os.path.dirname(__file__),
        'templates',
        'nren_access',
        'nren-dashboard.json.j2'))

    with open(file) as f:
        template = jinja2.Template(f.read())

    for dashboard in get_dashboard_data(interfaces, datasource):
        rendered = template.render(dashboard)
        rendered = json.loads(rendered)
        rendered['uid'] = None
        rendered['id'] = None
        yield rendered