diff --git a/brian_dashboard_manager/config.py b/brian_dashboard_manager/config.py index e167231f1208f3c27f304d4b1bb6fc1ca63bf721..0fc54529b201b814d5250f83f17d301fb346c9e2 100644 --- a/brian_dashboard_manager/config.py +++ b/brian_dashboard_manager/config.py @@ -41,10 +41,14 @@ DEFAULT_ORGANIZATIONS = [ }, { "name": "NRENs", - "excluded_nrens": [], + "excluded_nrens": [ + "CUSTOMER GEANT", + "GEANT-IT" + ], "excluded_dashboards": [ "GÉANT Office devices", - "GÉANT VM" + "GÉANT VM", + "GÉANT LAB devices" ], "excluded_folders": { "Aggregates": ["CAE1"], @@ -54,12 +58,15 @@ DEFAULT_ORGANIZATIONS = [ { "name": "General Public", "excluded_nrens": [ - "CARNET", - "PSNC" + "CARNET", + "PSNC", + "CUSTOMER GEANT", + "GEANT-IT" ], "excluded_dashboards": [ "GÉANT Office devices", "GÉANT VM", + "GÉANT LAB devices" "IAS", "GEANTOPEN" ], @@ -73,22 +80,29 @@ DEFAULT_ORGANIZATIONS = [ }, { "name": "CAE1 - Europe", - "excluded_nrens": [], + "excluded_nrens": [ + "CUSTOMER GEANT", + "GEANT-IT" + ], "excluded_dashboards": [ "GÉANT Office devices", - "GÉANT VM" + "GÉANT VM", + "GÉANT LAB devices", ], "excluded_folders": {} }, { "name": "CAE1 - Asia", "excluded_nrens": [ - "CARNET", - "PSNC" + "CARNET", + "PSNC", + "CUSTOMER GEANT", + "GEANT-IT" ], "excluded_dashboards": [ "GÉANT Office devices", "GÉANT VM", + "GÉANT LAB devices" "IAS" ], "excluded_folders": { diff --git a/brian_dashboard_manager/dashboards/infrastructure_lab.json b/brian_dashboard_manager/dashboards/infrastructure_lab.json new file mode 100644 index 0000000000000000000000000000000000000000..d8c841f6372c9f8975ebc2a38f5dcdc11ea778b2 --- /dev/null +++ b/brian_dashboard_manager/dashboards/infrastructure_lab.json @@ -0,0 +1,717 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": 6858, + "iteration": 1607526562704, + "links": [], + "panels": [ + { + "collapsed": false, + "datasource": null, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 12, + "panels": [], + "repeat": "interface_name", + "scopedVars": { + "interface_name": { + "selected": true, + "text": "ae1", + "value": "ae1" + } + }, + "title": "$hostname - $interface_name", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 11, + "w": 24, + "x": 0, + "y": 1 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.3.4", + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "v", + "scopedVars": { + "interface_name": { + "selected": true, + "text": "ae1", + "value": "ae1" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Ingress", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "linear" + ], + "type": "fill" + } + ], + "measurement": "interface_rates", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "ingress" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "hostname", + "operator": "=~", + "value": "/^$hostname$/" + }, + { + "condition": "AND", + "key": "interface_name", + "operator": "=~", + "value": "/^$interface_name$/" + } + ] + }, + { + "alias": "Egress", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "linear" + ], + "type": "fill" + } + ], + "measurement": "interface_rates", + "orderByTime": "ASC", + "policy": "default", + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "egress" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "hostname", + "operator": "=~", + "value": "/^$hostname$/" + }, + { + "condition": "AND", + "key": "interface_name", + "operator": "=~", + "value": "/^$interface_name$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Traffic $hostname - $interface_name", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:211", + "format": "bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:212", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 11, + "w": 12, + "x": 0, + "y": 12 + }, + "hiddenSeries": false, + "id": 30, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.3.4", + "pointradius": 2, + "points": false, + "renderer": "flot", + "scopedVars": { + "interface_name": { + "selected": true, + "text": "ae1", + "value": "ae1" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Ingress", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "linear" + ], + "type": "fill" + } + ], + "measurement": "interface_rates", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "ingressv6" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "hostname", + "operator": "=~", + "value": "/^$hostname$/" + }, + { + "condition": "AND", + "key": "interface_name", + "operator": "=~", + "value": "/^$interface_name$/" + } + ] + }, + { + "alias": "Egress", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "linear" + ], + "type": "fill" + } + ], + "measurement": "interface_rates", + "orderByTime": "ASC", + "policy": "default", + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "egressv6" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "hostname", + "operator": "=~", + "value": "/^$hostname$/" + }, + { + "condition": "AND", + "key": "interface_name", + "operator": "=~", + "value": "/^$interface_name$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "IPV6 - $hostname - $interface_name", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:391", + "format": "bps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:392", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": null, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 11, + "w": 12, + "x": 12, + "y": 12 + }, + "hiddenSeries": false, + "id": 56, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.3.4", + "pointradius": 2, + "points": false, + "renderer": "flot", + "scopedVars": { + "interface_name": { + "selected": true, + "text": "ae1", + "value": "ae1" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "In", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "linear" + ], + "type": "fill" + } + ], + "measurement": "interface_rates", + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "errorsIn" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "hostname", + "operator": "=~", + "value": "/^$hostname$/" + } + ] + }, + { + "alias": "Out", + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "linear" + ], + "type": "fill" + } + ], + "measurement": "interface_rates", + "orderByTime": "ASC", + "policy": "default", + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "errorsOut" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "hostname", + "operator": "=~", + "value": "/^$hostname$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Errors - $hostname - $interface_name", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:547", + "format": "err/s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "$$hashKey": "object:548", + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "schemaVersion": 26, + "style": "dark", + "tags": [ + "infrastructure" + ], + "templating": { + "list": [ + { + "allValue": null, + "current": { + "selected": true, + "text": "mx1.lab.office.geant.net", + "value": "mx1.lab.office.geant.net" + }, + "error": null, + "hide": 0, + "includeAll": false, + "label": "Hostname", + "multi": false, + "name": "hostname", + "options": [ + { + "selected": true, + "text": "mx1.lab.office.geant.net", + "value": "mx1.lab.office.geant.net" + }, + { + "selected": false, + "text": "mx2.lab.office.geant.net", + "value": "mx2.lab.office.geant.net" + }, + { + "selected": false, + "text": "mx3.lab.office.geant.net", + "value": "mx3.lab.office.geant.net" + }, + { + "selected": false, + "text": "mx4.lab.office.geant.net", + "value": "mx4.lab.office.geant.net" + }, + { + "selected": false, + "text": "mx5.lab.office.geant.net", + "value": "mx5.lab.office.geant.net" + } + + ], + "query": "mx1.lab.office.geant.net,mx2.lab.office.geant.net,mx3.lab.office.geant.net,mx4.lab.office.geant.net,mx5.lab.office.geant.net", + "queryValue": "", + "skipUrlSync": false, + "type": "custom" + }, + { + "allValue": null, + "current": { + "selected": true, + "text": [ + "ae1" + ], + "value": [ + "ae1" + ] + }, + "datasource": "PollerInfluxDB", + "definition": "", + "error": null, + "hide": 0, + "includeAll": true, + "label": "Interface Name", + "multi": true, + "name": "interface_name", + "options": [], + "query": "SHOW TAG VALUES ON test_brian WITH KEY IN (interface_name) WHERE hostname =~ /$hostname/ ", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Lab Devices", + "version": 17 + } \ No newline at end of file diff --git a/brian_dashboard_manager/dashboards/infrastructure_office.json b/brian_dashboard_manager/dashboards/infrastructure_office.json index 2255dce494d57a8affc8acabb64eab38537bedfa..48761f23752936b44f98f7b66db13603a5f1ed2c 100644 --- a/brian_dashboard_manager/dashboards/infrastructure_office.json +++ b/brian_dashboard_manager/dashboards/infrastructure_office.json @@ -687,7 +687,7 @@ "multi": true, "name": "interface_name", "options": [], - "query": "SHOW TAG VALUES ON poller WITH KEY IN (interface_name) WHERE hostname =~ /$hostname/ ", + "query": "SHOW TAG VALUES WITH KEY IN (interface_name) WHERE hostname =~ /$hostname/ ", "refresh": 1, "regex": "", "skipUrlSync": false, diff --git a/brian_dashboard_manager/dashboards/infrastructure_vm.json b/brian_dashboard_manager/dashboards/infrastructure_vm.json index 3cea9a9f32a8acaced302f357626dd070d01ec00..cb041359eb1bc3b37e45ef838f623f77ff6bf33c 100644 --- a/brian_dashboard_manager/dashboards/infrastructure_vm.json +++ b/brian_dashboard_manager/dashboards/infrastructure_vm.json @@ -690,7 +690,7 @@ "label": "Interface Name", "multi": true, "name": "interface_name", - "query": "SHOW TAG VALUES ON poller WITH KEY IN (interface_name) WHERE hostname =~ /$hostname/ ", + "query": "SHOW TAG VALUES WITH KEY IN (interface_name) WHERE hostname =~ /$hostname/ ", "refresh": 0, "regex": "", "skipUrlSync": false, diff --git a/brian_dashboard_manager/grafana/organization.py b/brian_dashboard_manager/grafana/organization.py index d075660ea874aec41a559abe3b40786dad8d948d..bf8f2e85f0533a5e3d008b1639f5c78a7c7a886d 100644 --- a/brian_dashboard_manager/grafana/organization.py +++ b/brian_dashboard_manager/grafana/organization.py @@ -5,11 +5,14 @@ Grafana Organization management helpers. import random import string import logging +import jinja2 +import json +import os from typing import Dict, List, Union from datetime import datetime - from brian_dashboard_manager.grafana.utils.request import AdminRequest, \ TokenRequest +from brian_dashboard_manager.grafana.dashboard import create_dashboard logger = logging.getLogger(__name__) @@ -94,8 +97,20 @@ def delete_expired_api_tokens(request: AdminRequest, org_id: int) -> bool: return True -def set_home_dashboard(request: TokenRequest, dashboard_id: int): +def set_home_dashboard(request: TokenRequest, is_staff): + file = os.path.abspath(os.path.join( + os.path.dirname(__file__), + '..', + 'templating', + 'templates', + 'homedashboard.json.j2')) + + with open(file) as f: + template = jinja2.Template(f.read()) + rendered = template.render({'staff': is_staff}) + rendered = json.loads(rendered) + dashboard = create_dashboard(request, rendered) r = request.put('api/org/preferences', json={ - 'homeDashboardId': dashboard_id + 'homeDashboardId': dashboard.get('id') }) return r and r.get('message') == 'Preferences updated' diff --git a/brian_dashboard_manager/grafana/provision.py b/brian_dashboard_manager/grafana/provision.py index 685be93971bbd9b49ea946a4ea1748331c4ee79a..345317f3c0c3c6d343fb2c2b3ec463e66cd976dc 100644 --- a/brian_dashboard_manager/grafana/provision.py +++ b/brian_dashboard_manager/grafana/provision.py @@ -2,6 +2,7 @@ This module is responsible for the entire provisioning lifecycle. """ +import os import logging import time import json @@ -15,8 +16,7 @@ from brian_dashboard_manager.grafana.organization import \ get_organizations, create_organization, create_api_token, \ delete_api_token, delete_expired_api_tokens, set_home_dashboard from brian_dashboard_manager.grafana.dashboard import \ - get_dashboard_definitions, create_dashboard, find_dashboard, \ - delete_dashboard + get_dashboard_definitions, create_dashboard, delete_dashboard from brian_dashboard_manager.grafana.datasource import \ check_provisioned, create_datasource from brian_dashboard_manager.grafana.folder import find_folder, \ @@ -105,8 +105,10 @@ def provision_maybe(config): f.truncate() try: + # don't conditionally provision in dev + val = os.environ.get('FLASK_ENV') != 'development' now = datetime.datetime.now() - write_timestamp(now.timestamp(), True) + write_timestamp(now.timestamp(), val) provision(config) finally: now = datetime.datetime.now() @@ -321,8 +323,6 @@ def provision(config): logger.info('Provisioning static dashboards') for dashboard in get_dashboard_definitions(): if dashboard['title'] not in excluded_dashboards: - if dashboard['title'].lower() == 'home': - dashboard['uid'] = 'home' create_dashboard(token_request, dashboard) else: delete_dashboard(token_request, dashboard) @@ -330,9 +330,8 @@ def provision(config): # Home dashboard is always called "Home" # Make sure it's set for the organization logger.info('Configuring Home dashboard') - home_dashboard = find_dashboard(token_request, 'Home') - if home_dashboard: - set_home_dashboard(token_request, home_dashboard['id']) + is_staff = org['name'] == 'GÉANT Staff' + set_home_dashboard(token_request, is_staff) logger.info(f'Time to complete: {time.time() - start}') for org_id, token in tokens: diff --git a/brian_dashboard_manager/templating/helpers.py b/brian_dashboard_manager/templating/helpers.py index cc7fa18a6a436cf7939defe3d7a6813aa8a72cb5..d2001f1156f5299a477bfb21c88746ce98ed1e85 100644 --- a/brian_dashboard_manager/templating/helpers.py +++ b/brian_dashboard_manager/templating/helpers.py @@ -224,13 +224,17 @@ def get_interface_data(interfaces, name_parse_func=None): def get_aggregate_interface_data(interfaces, agg_type): result = [] + # Aggregate dashboards have aggregates at the top for all remotes + # as well as aggregate panels for specific remotes. + # This builds a dict with interfaces for each remote + # and one with all interfaces. def reduce_func(prev, curr): remotes = prev.get(curr['remote'], []) remotes.append(curr) - all_agg = prev.get('EVERYSINGLEPANEL', []) + all_agg = prev.get('EVERYSINGLETARGET', []) all_agg.append(curr) prev[curr['remote']] = remotes - prev['EVERYSINGLEPANEL'] = all_agg + prev['EVERYSINGLETARGET'] = all_agg return prev for interface in interfaces: @@ -241,12 +245,13 @@ def get_aggregate_interface_data(interfaces, agg_type): remote = description.split(' ')[2].upper() + location = host.split('.')[1].upper() result.append({ 'type': agg_type, 'interface': interface_name, 'hostname': host, 'remote': remote, - 'alias': f"{host.split('.')[1].upper()} - {remote}", + 'alias': f"{location} - {remote} ({interface_name})", }) return reduce(reduce_func, result, {}) @@ -303,19 +308,10 @@ def get_panel_fields(panel, panel_type, datasource): egress = ['Egress Traffic', 'Egress 95th Percentile'] is_v6 = panel_type == 'IPv6' - is_multicast = panel_type == 'multicast' is_error = panel_type == 'errors' - in_field = 'ingressv6' if is_v6 else \ - 'ingressMulticast' if is_multicast else 'ingress' + in_field = 'ingressv6' if is_v6 else 'ingress' - out_field = 'egressv6' if is_v6 else \ - 'egressMulticast' if is_multicast else 'egress' - - if is_multicast: - def add_multicast(label): - return 'Multicast ' + label - ingress = list(map(add_multicast, ingress)) - egress = list(map(add_multicast, egress)) + out_field = 'egressv6' if is_v6 else 'egress' fields = [*product(ingress, [in_field]), *product(egress, [out_field])] @@ -343,8 +339,6 @@ def get_dashboard_data(data, datasource, tag, errors=False): if panel.get('has_v6', False): result.append(get_panel_fields( {**panel, **next(gridPos)}, 'IPv6', datasource)) - result.append(get_panel_fields( - {**panel, **next(gridPos)}, 'multicast', datasource)) if errors: result.append(get_panel_fields( {**panel, **next(gridPos)}, 'errors', datasource)) @@ -417,7 +411,7 @@ def get_aggregate_dashboard_data(title, targets, datasource, tag): gridPos = gridPos_generator(id_gen, agg=True) panels = [] - all_targets = targets.get('EVERYSINGLEPANEL', []) + all_targets = targets.get('EVERYSINGLETARGET', []) ingress, egress = create_aggregate_panel( title, gridPos, all_targets, datasource) @@ -428,8 +422,8 @@ def get_aggregate_dashboard_data(title, targets, datasource, tag): totals_title, gridPos, all_targets, datasource) panels.extend([t_in, t_eg]) - if 'EVERYSINGLEPANEL' in targets: - del targets['EVERYSINGLEPANEL'] + if 'EVERYSINGLETARGET' in targets: + del targets['EVERYSINGLETARGET'] for target in targets: _in, _out = create_aggregate_panel( diff --git a/brian_dashboard_manager/templating/nren_access.py b/brian_dashboard_manager/templating/nren_access.py index f9bf4d9baceae1860ded4372059ca65a41817be3..17bb8ebcf2c6f04b319606f778fad182645418a0 100644 --- a/brian_dashboard_manager/templating/nren_access.py +++ b/brian_dashboard_manager/templating/nren_access.py @@ -25,11 +25,12 @@ def get_nrens(interfaces): router = host.replace('.geant.net', '') panel_title = f"{router} - {{}} - {interface_name} - {description}" + location = host.split('.')[1].upper() if is_aggregate_interface(interface): nren['AGGREGATES'].append({ 'interface': interface_name, 'hostname': host, - 'alias': f"{host.split('.')[1].upper()} - {nren_name}" + 'alias': f"{location} - {nren_name} ({interface_name})" }) # link aggregates are also shown @@ -73,8 +74,6 @@ def get_panel_definitions(panels, datasource, errors=False): if panel.get('has_v6', False): result.append(get_panel_fields( {**panel, **next(gridPos)}, 'IPv6', datasource)) - result.append(get_panel_fields( - {**panel, **next(gridPos)}, 'multicast', datasource)) if errors: result.append(get_panel_fields( {**panel, **next(gridPos)}, 'errors', datasource)) diff --git a/brian_dashboard_manager/dashboards/home.json b/brian_dashboard_manager/templating/templates/homedashboard.json.j2 old mode 100755 new mode 100644 similarity index 83% rename from brian_dashboard_manager/dashboards/home.json rename to brian_dashboard_manager/templating/templates/homedashboard.json.j2 index 15fa12fd39b2d2a601962f669fc0ac70b28aff68..7e2b37a51257ea8c25aa47d9b168a38b4e672cb4 --- a/brian_dashboard_manager/dashboards/home.json +++ b/brian_dashboard_manager/templating/templates/homedashboard.json.j2 @@ -1,7 +1,7 @@ { "annotations": { "list": [ - { + { "builtIn": 1, "datasource": "-- Grafana --", "enable": true, @@ -16,50 +16,52 @@ "gnetId": null, "graphTooltip": 0, "id": 49, + "uid": "home", "iteration": 1595947519970, "links": [ - { - "asDropdown": true, - "icon": "external link", - "tags": [ - "services" - ], - "targetBlank": true, - "title": "Services", - "type": "dashboards" - }, - { - "asDropdown": true, - "icon": "external link", - "tags": [ - "infrastructure" - ], - "targetBlank": true, - "title": "Infrastructure", - "type": "dashboards" - }, - { - "asDropdown": true, - "icon": "external link", - "tags": [ - "customers" - ], - "targetBlank": true, - "title": "NREN Access", - "type": "dashboards" - }, - { - "asDropdown": true, - "icon": "external link", - "tags": [ - "peers" - ], - "targetBlank": true, - "title": "Peers", - "type": "dashboards" - } + { + "asDropdown": true, + "icon": "external link", + "tags": [ + "services" + ], + "targetBlank": true, + "title": "Services", + "type": "dashboards" + }, + { + "asDropdown": true, + "icon": "external link", + "tags": [ + "infrastructure" + ], + "targetBlank": true, + "title": "Infrastructure", + "type": "dashboards" + }, + { + "asDropdown": true, + "icon": "external link", + "tags": [ + "customers" + ], + "targetBlank": true, + "title": "NREN Access", + "type": "dashboards" + }, + { + "asDropdown": true, + "icon": "external link", + "tags": [ + "peers" + ], + "targetBlank": true, + "title": "Peers", + "type": "dashboards" + } ], "panels": [ + {% if staff %} { "aliasColors": {}, "bars": false, @@ -636,23 +638,110 @@ "alignLevel": null } } + {% else %} + { + "datasource": "PollerInfluxDB", + "fieldConfig": { + "defaults": { + "custom": { + "align": null, + "filterable": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "folderId": null, + "gridPos": { + "h": 24, + "w": 24, + "x": 0, + "y": 0 + }, + "headings": true, + "id": 2, + "limit": 100, + "pluginVersion": "7.2.1", + "query": "", + "recent": false, + "repeat": null, + "search": true, + "starred": true, + "tags": [], + "targets": [ + { + "groupBy": [ + { + "params": [ + "$__interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "orderByTime": "ASC", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Dashboards", + "type": "dashlist" + } + {% endif %} ], "schemaVersion": 26, "style": "dark", "tags": [], "templating": { "list": [ + {% if staff %} { "allValue": null, "datasource": "PollerInfluxDB", - "definition": "SHOW TAG VALUES ON poller WITH KEY=hostname", + "definition": "SHOW TAG VALUES WITH KEY=hostname", "hide": 0, "includeAll": false, "label": "Router:", "multi": false, "name": "hostname", "options": [], - "query": "SHOW TAG VALUES ON poller WITH KEY=hostname", + "query": "SHOW TAG VALUES WITH KEY=hostname", "refresh": 1, "regex": "", "skipUrlSync": false, @@ -666,14 +755,14 @@ { "allValue": null, "datasource": "PollerInfluxDB", - "definition": "SHOW TAG VALUES ON poller WITH KEY IN (interface_name) WHERE hostname =~ /$hostname/ ", + "definition": "SHOW TAG VALUES WITH KEY IN (interface_name) WHERE hostname =~ /$hostname/ ", "hide": 0, "includeAll": false, "label": "Interface :", "multi": false, "name": "interface_name", "options": [], - "query": "SHOW TAG VALUES ON poller WITH KEY IN (interface_name) WHERE hostname =~ /$hostname/ ", + "query": "SHOW TAG VALUES WITH KEY IN (interface_name) WHERE hostname =~ /$hostname/ ", "refresh": 1, "regex": "", "skipUrlSync": false, @@ -684,6 +773,7 @@ "type": "query", "useTags": false } + {% endif %} ] }, "time": { @@ -706,4 +796,4 @@ "timezone": "", "title": "Home", "version": 1 -} +} \ No newline at end of file diff --git a/changelog.md b/changelog.md index 2e836cdfaff01648d21415a47d9822e22d7660d1..4d8c33ee2ae625eb6f714520138ab2b1a869bfdd 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,12 @@ All notable changes to this project will be documented in this file. +## [0.8] - 2021-04-09 +- Templated home dashboard to provision different one for each organization +- Add interface names to aggregate graph target aliases +- Add lab router dashboard +- Remove multicast panels + ## [0.7] - 2021-03-25 - Added better support for excluding dashboards under specific paths - Added version endpoint diff --git a/setup.py b/setup.py index 8b120a493a117b512dd4126e44eb6961ae9924d2..5d80ee809949711ef64c637fd451722a1c9a3e75 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages setup( name='brian-dashboard-manager', - version="0.7", + version="0.8", author='GEANT', author_email='swd@geant.org', description='', diff --git a/test/test_update.py b/test/test_update.py index 68c3d10124e61f58e6b68895c27beebd701b74b6..4b63f49b01417950305bac3131167e0ce5620607 100644 --- a/test/test_update.py +++ b/test/test_update.py @@ -366,6 +366,30 @@ def test_provision(data_config, mocker, client): url=f"http://{data_config['hostname']}/api/datasources", callback=datasources) + def createdashboard(request): + return 200, {}, json.dumps({'id': 666}) + + responses.add_callback( + method=responses.POST, + url=f"http://{data_config['hostname']}/api/dashboards/db", + callback=createdashboard) + + def preferences(request): + return 200, {}, json.dumps({'message': 'Preferences updated'}) + + responses.add_callback( + method=responses.PUT, + url=f"http://{data_config['hostname']}/api/org/preferences", + callback=preferences) + + def homedashboard(request): + return 404, {}, '' + + responses.add_callback( + method=responses.GET, + url=f"http://{data_config['hostname']}/api/dashboards/uid/home", + callback=homedashboard) + PROVISIONED_ORGANIZATION = { 'name': data_config['organizations'][0], 'id': 0 @@ -416,7 +440,7 @@ def test_provision(data_config, mocker, client): 'brian_dashboard_manager.grafana.provision.create_dashboard') # we dont care about this, just mark it created # we dont care about this, tested separately - _mocked_create_dashboard.return_value = None + _mocked_create_dashboard.return_value = {'id': 666} _mocked_delete_api_token = mocker.patch( 'brian_dashboard_manager.grafana.provision.delete_api_token')