Skip to content
Snippets Groups Projects
Commit 739b80ee authored by Maryam Mokhtarifar's avatar Maryam Mokhtarifar
Browse files

Merge branch 'feature/POL1-877-add-vlans-dashboard' into 'develop'

Implement get_router_dashboard_data and _provision_vlan_dashboards

See merge request !16
parents 4497440e b8f41a7c
Branches
Tags
1 merge request!16Implement get_router_dashboard_data and _provision_vlan_dashboards
......@@ -58,7 +58,8 @@ DEFAULT_ORGANIZATIONS = [
"excluded_folders": {
"Aggregates": ["CAE1"],
"EUMETSAT Multicast": True,
"NREN Access LEGACY": True
"NREN Access LEGACY": True,
"VLAN Interfaces": True,
}
},
{
......@@ -90,7 +91,8 @@ DEFAULT_ORGANIZATIONS = [
"GWS Direct": True,
"GWS Indirect": True,
"EUMETSAT Multicast": True,
"NREN Access LEGACY": True
"NREN Access LEGACY": True,
"VLAN Interfaces": True,
}
},
{
......@@ -111,7 +113,8 @@ DEFAULT_ORGANIZATIONS = [
],
"excluded_folders": {
"EUMETSAT Multicast": True,
"NREN Access LEGACY": True
"NREN Access LEGACY": True,
"VLAN Interfaces": True,
}
},
{
......@@ -141,7 +144,8 @@ DEFAULT_ORGANIZATIONS = [
"IAS UPSTREAM": True,
"GWS PHY Upstream": True,
"EUMETSAT Multicast": True,
"NREN Access LEGACY": True
"NREN Access LEGACY": True,
"VLAN Interfaces": True,
}
}
]
......
......@@ -33,7 +33,7 @@ from brian_dashboard_manager.templating.helpers import \
get_nren_interface_data, get_dashboard_data, \
get_nren_dashboard_data, get_aggregate_interface_data, \
get_nren_interface_data_old, get_re_peer_dashboard_data, get_re_peer_interface_data, get_service_data, \
get_service_dashboard_data, get_aggregate_service_data
get_service_dashboard_data, get_aggregate_service_data, get_router_dashboard_data, get_dashboard_data_dropdown
from brian_dashboard_manager.templating.gws import generate_gws, generate_indirect
from brian_dashboard_manager.templating.eumetsat import generate_eumetsat_multicast
......@@ -501,8 +501,25 @@ def _provision_vlan_dashboards(thread_executor: ThreadPoolExecutor, config, org_
folder_name = "VLAN Interfaces" # hardcoded, keep this in sync with the folder name specified in folders_to_keep
logger.info(f'Provisioning {org_config["name"]}/{folder_name} dashboards')
excluded_folders = org_config.get('excluded_folders', {})
if is_excluded_folder(excluded_folders, folder_name):
delete_folder(token, title=folder_name)
else:
folder = find_folder(token, title=folder_name)
if not folder:
raise Exception(f'Folder {folder_name} not found')
folder_dashboards_by_name = list_folder_dashboards(token, folder['uid'])
yield
vlan_data = get_router_dashboard_data(interfaces)
provisioned = []
for dashboard in get_dashboard_data_dropdown(vlan_data, ds_name, 'vlandash'):
rendered = render_simple_dashboard(**dashboard)
provisioned.append(
thread_executor.submit(create_dashboard, token, rendered, folder['id'], folder_dashboards_by_name)
)
yield from provisioned
def _provision_gws_indirect(thread_executor: ThreadPoolExecutor, config, org_config, ds_name, token):
......
......@@ -543,9 +543,33 @@ def get_router_dashboard_data(interfaces):
:return: dictionary of routers (dashboards) and their interface data.
"""
# TODO: implement
result = {}
filtered_interfaces = [interface for interface in interfaces if interface.get('vlan_type') in {'TRUNK', 'VLAN'}]
sorted_interfaces = sorted(filtered_interfaces, key=lambda x: x['name'])
for interface in sorted_interfaces:
description = interface['description'].strip()
interface_name = interface['name']
host = interface['router']
return {}
router = host.replace('.geant.net', '')
panel_title = f'{router} - {{}} - {interface_name} - {description}'
dashboard_name = interface['router']
dashboard = result.setdefault(dashboard_name, {})
base_interface = interface_name.split('.')[0]
dropdown = dashboard.setdefault(base_interface, [])
dropdown.append({
'title': panel_title,
'interface': interface_name,
'hostname': host
})
return result
def get_interface_data(interfaces):
......@@ -1130,7 +1154,6 @@ def get_dashboard_data_dropdown(
def get_nren_dashboard_data(data, datasource, tag):
func = partial(
get_dashboard_with_agg_data_single,
datasource=datasource,
......
# flake8: noqa
import pytest
import responses
from concurrent.futures import ThreadPoolExecutor
......@@ -11,7 +12,7 @@ TEST_INTERFACES = [
"name": "ge-0/0/8",
"bundle": [],
"bundle-parents": [],
"description": "PHY CUSTOMER GEANT CORPORATE SRF000001 | GEANT Corporate to MX1.LON - Via Vodafone", # noqa: E501
"description": "PHY CUSTOMER GEANT CORPORATE SRF000001 | GEANT Corporate to MX1.LON - Via Vodafone",
"circuits": [
{
"id": 679232,
......@@ -41,7 +42,7 @@ TEST_INTERFACES = [
"name": "ge-0/0/8.10",
"bundle": [],
"bundle-parents": [],
"description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_CORPORATE-ViaVodafone | GEANT Corporate to mx1.lon - Via Vodafone ", # noqa: E501
"description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_CORPORATE-ViaVodafone | GEANT Corporate to mx1.lon - Via Vodafone ",
"circuits": [
{
"id": 679360,
......@@ -75,7 +76,7 @@ TEST_INTERFACES = [
"name": "ge-0/0/8.11",
"bundle": [],
"bundle-parents": [],
"description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_CORPORATE_ViaVodafone-VRF | GEANT Corporate to mx1.lon - Via Vodafone - for VRF", # noqa: E501
"description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_CORPORATE_ViaVodafone-VRF | GEANT Corporate to mx1.lon - Via Vodafone - for VRF",
"circuits": [
{
"id": 712144,
......@@ -107,11 +108,11 @@ TEST_INTERFACES = [
"name": "ge-0/0/8.12",
"bundle": [],
"bundle-parents": [],
"description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_CORPORATE_ViaVodafone-VRF-TEST | GEANT Corporate to mx1.lon - Via Vodafone - DASHBOARD BGP TEST VLAN", # noqa: E501
"description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_CORPORATE_ViaVodafone-VRF-TEST | GEANT Corporate to mx1.lon - Via Vodafone - DASHBOARD BGP TEST VLAN",
"circuits": [
{
"id": 678920,
"name": "GEANT_CORPORATE_VIAVODAFONE-VRF-TEST (DO NOT OPEN A TICKET)", # noqa: E501
"name": "GEANT_CORPORATE_VIAVODAFONE-VRF-TEST (DO NOT OPEN A TICKET)",
"type": "GEANT IP",
"status": "non-monitored"
}
......@@ -139,7 +140,7 @@ TEST_INTERFACES = [
"name": "ge-0/0/8.996",
"bundle": [],
"bundle-parents": [],
"description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_OPERATIONS_LabConnectivity | GEANT MX1.LON Infinera VRF to Operations Lab", # noqa: E501
"description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_OPERATIONS_LabConnectivity | GEANT MX1.LON Infinera VRF to Operations Lab",
"circuits": [
{
"id": 678999,
......@@ -221,7 +222,7 @@ TEST_INTERFACES = [
"name": "ge-0/2/1.0",
"bundle": [],
"bundle-parents": [],
"description": "SRV_L2CIRCUIT INFRASTRUCTURE GEANT GEANT #AMS-ZAG OPENFLOW |", # noqa: E501
"description": "SRV_L2CIRCUIT INFRASTRUCTURE GEANT GEANT #AMS-ZAG OPENFLOW |",
"circuits": [],
"snmp-index": 687,
"dashboards": [
......@@ -243,7 +244,7 @@ TEST_INTERFACES = [
"name": "ge-0/2/2.0",
"bundle": [],
"bundle-parents": [],
"description": "SRV_L2CIRCUIT INFRASTRUCTURE GEANT GEANT #AMS-VIE OPENFLOW |", # noqa: E501
"description": "SRV_L2CIRCUIT INFRASTRUCTURE GEANT GEANT #AMS-VIE OPENFLOW |",
"circuits": [],
"snmp-index": 711,
"dashboards": [
......@@ -265,7 +266,7 @@ TEST_INTERFACES = [
"name": "ge-0/2/4.0",
"bundle": [],
"bundle-parents": [],
"description": "SRV_L2CIRCUIT INFRASTRUCTURE GEANT GEANT #AMS-FRA OPENFLOW |", # noqa: E501
"description": "SRV_L2CIRCUIT INFRASTRUCTURE GEANT GEANT #AMS-FRA OPENFLOW |",
"circuits": [],
"snmp-index": 718,
"dashboards": [
......@@ -283,7 +284,6 @@ TEST_INTERFACES = [
"ipv6": []
},
{
"router": "rt1.fra.de.geant.net",
"name": "xe-11/2/5.300",
"bundle": [],
......@@ -326,7 +326,7 @@ NREN_INTERFACES = [
"ae10"
],
"bundle-parents": [],
"description": "PHY CUSTOMER HEANET P_AE10 SRF9948758 | HEANET-AP2-LL3", # noqa: E501
"description": "PHY CUSTOMER HEANET P_AE10 SRF9948758 | HEANET-AP2-LL3",
"circuits": [],
"snmp-index": 554,
"dashboards": [
......@@ -351,7 +351,7 @@ NREN_INTERFACES = [
"ae10"
],
"bundle-parents": [],
"description": "PHY CUSTOMER HEANET P_AE10 SRF0000001 | HEANET-AP2-LL2", # noqa: E501
"description": "PHY CUSTOMER HEANET P_AE10 SRF0000001 | HEANET-AP2-LL2",
"circuits": [],
"snmp-index": 527,
"dashboards": [
......@@ -376,7 +376,7 @@ NREN_INTERFACES = [
"ae10"
],
"bundle-parents": [],
"description": "PHY CUSTOMER HEANET P_AE10 SRF9925903 | HEANET-AP2-LL1", # noqa: E501
"description": "PHY CUSTOMER HEANET P_AE10 SRF9925903 | HEANET-AP2-LL1",
"circuits": [],
"snmp-index": 528,
"dashboards": [
......@@ -468,7 +468,7 @@ NREN_INTERFACES = [
"xe-1/0/1",
"xe-1/1/0"
],
"description": "SRV_MDVPN CUSTOMER HEANET AP2 #HEANET-BGP-LU-CoC-1 |", # noqa: E501
"description": "SRV_MDVPN CUSTOMER HEANET AP2 #HEANET-BGP-LU-CoC-1 |",
"circuits": [
{
"id": 663160,
......@@ -504,7 +504,7 @@ NREN_INTERFACES = [
"xe-1/0/1",
"xe-1/1/0"
],
"description": "SRV_IAS CUSTOMER HEANET #HEANET-AP2-IAS IASPS | ASN1213 ", # noqa: E501
"description": "SRV_IAS CUSTOMER HEANET #HEANET-AP2-IAS IASPS | ASN1213 ",
"circuits": [
{
"id": 663214,
......@@ -542,7 +542,7 @@ NREN_INTERFACES = [
"xe-1/0/1",
"xe-1/1/0"
],
"description": "SRV_L2CIRCUIT CUSTOMER HEANET GEANT #ams-dub2-HEANET-RARE-21061 |", # noqa: E501
"description": "SRV_L2CIRCUIT CUSTOMER HEANET GEANT #ams-dub2-HEANET-RARE-21061 |",
"circuits": [
{
"id": 713335,
......@@ -569,9 +569,7 @@ NREN_INTERFACES = [
"ipv4": [],
"ipv6": []
},
{
"router": "rt1.fra.de.geant.net",
{"router": "rt1.fra.de.geant.net",
"name": "xe-11/2/5.300",
"bundle": [],
"bundle-parents": [],
......@@ -602,48 +600,48 @@ NREN_INTERFACES = [
"port_type": "SERVICE",
"ipv4": [],
"ipv6": []
}
}
]
EUMETSAT_MULTICAST = [
{
'router': 'mx1.ams.nl.geant.net',
'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.1.193.17.9.3.255.255.255.255', # noqa: E501
'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.1.193.17.9.3.255.255.255.255',
'community': '0pBiFbD',
'subscription': '232.223.222.1',
'endpoint': '193.17.9.3'
},
{
'router': 'mx1.ams.nl.geant.net',
'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.2.193.17.9.3.255.255.255.255', # noqa: E501
'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.2.193.17.9.3.255.255.255.255',
'community': '0pBiFbD',
'subscription': '232.223.222.2',
'endpoint': '193.17.9.3'
},
{
'router': 'mx1.lon.uk.geant.net',
'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.1.193.17.9.3.255.255.255.255', # noqa: E501
'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.1.193.17.9.3.255.255.255.255',
'community': '0pBiFbD',
'subscription': '232.223.222.1',
'endpoint': '193.17.9.3'
},
{
'router': 'mx1.lon.uk.geant.net',
'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.2.193.17.9.3.255.255.255.255', # noqa: E501
'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.2.193.17.9.3.255.255.255.255',
'community': '0pBiFbD',
'subscription': '232.223.222.2',
'endpoint': '193.17.9.3'
},
{
'router': 'mx1.fra.de.geant.net',
'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.1.193.17.9.3.255.255.255.255', # noqa: E501
'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.1.193.17.9.3.255.255.255.255',
'community': '0pBiFbD',
'subscription': '232.223.222.1',
'endpoint': '193.17.9.3'
},
{
'router': 'mx1.fra.de.geant.net',
'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.2.193.17.9.3.255.255.255.255', # noqa: E501
'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.2.193.17.9.3.255.255.255.255',
'community': '0pBiFbD',
'subscription': '232.223.222.2',
'endpoint': '193.17.9.3'
......@@ -848,7 +846,7 @@ def test_provision_re_peer_dashboard(
{
"router": "mx1.dub2.ie.geant.net",
"name": "xe-0/0/0.1",
"description": "PHY SVC P_AE10 SRF9948758 | HEANET-AP2-LL3", # noqa: E501
"description": "PHY SVC P_AE10 SRF9948758 | HEANET-AP2-LL3",
"dashboards": ["RE_PEER"],
"dashboard_info": {"name": "ESNET", "interface_type": "LOGICAL"},
"dashboards_info": [{"name": "ESNET", "interface_type": "LOGICAL"}],
......@@ -891,6 +889,102 @@ def test_provision_re_peer_dashboard(
assert len(panels[-1]['panels'][0]) > 0
@responses.activate
def test_vlan_interfaces(mocker, data_config, mock_grafana, reporting_provider, populate_inventory
):
interfaces = [
{'bundle': ['et-4/0/0', 'et-5/0/5', 'et-8/1/2', 'et-8/1/5'],
'bundle-parents': ['et-4/0/0', 'et-5/0/5', 'et-8/1/2', 'et-8/1/5'], 'circuits': [],
'dashboard_info': {'interface_type': 'AGGREGATE', 'name': 'REDIRIS'}, 'dashboards': ['NREN', 'RE_CUST'],
'dashboards_info': [{'interface_type': 'AGGREGATE', 'name': 'REDIRIS'}],
'description': 'LAG CUSTOMER REDIRIS SRF21114 $GA-01800 |', 'ipv4': [], 'ipv6': [], 'name': 'ae16',
'port_type': 'ACCESS', 'router': 'mx1.mad.es.geant.net', 'snmp-index': 654, 'vlan_type': 'TRUNK'}, {'bundle': [], 'bundle-parents': ['et-4/0/0', 'et-5/0/5', 'et-8/1/2', 'et-8/1/5'], 'circuits': [
{'id': 739804, 'name': 'UC3M-REDIRIS-BELNET-SLICES-IMEC', 'status': 'non-monitored', 'type': 'GEANT PLUS'}],
'dashboard_info': {'interface_type': 'LOGICAL', 'name': 'REDIRIS'},
'dashboards': ["VLAN Interfaces"],
'dashboards_info': [{'interface_type': 'LOGICAL', 'name': 'REDIRIS'},
{'interface_type': 'LOGICAL', 'name': 'BELNET'}],
'description': 'SRV_L2CIRCUIT CUSTOMER REDIRIS BELNET #UC3M-RedIRIS-BELNET-SLICES-IMEC $GS-02514 |',
'ipv4': [], 'ipv6': [], 'name': 'ae16.975', 'port_type': 'SERVICE', 'router': 'mx1.mad.es.geant.net',
'snmp-index': 818, 'vlan_type': 'VLAN'}, {'bundle': [], 'bundle-parents': ['et-4/0/0', 'et-5/0/5', 'et-8/1/2', 'et-8/1/5'], 'circuits': [
{'id': 732759, 'name': 'FRA-MAD-RARE-REDIRIS-23017-VL201', 'status': 'non-monitored',
'type': 'GEANT PLUS'}], 'dashboard_info': {'interface_type': 'LOGICAL', 'name': 'RARE'},
'dashboards': ['L2_CIRCUIT'], 'dashboards_info': [{'interface_type': 'LOGICAL', 'name': 'RARE'},
{'interface_type': 'LOGICAL', 'name': 'REDIRIS'}],
'description': 'SRV_L2CIRCUIT CUSTOMER RARE REDIRIS #fra-mad-RARE-REDIRIS-23017-VL201 $GS-02274', 'ipv4': [],
'ipv6': [], 'name': 'ae16.201', 'port_type': 'SERVICE', 'router': 'mx1.mad.es.geant.net', 'snmp-index': 642,
'vlan_type': 'VLAN'}, {'bundle': [], 'bundle-parents': [], 'circuits': [
{'id': 729417, 'name': 'PAR-LON2-SUPERPOP-QFX-2-GEANT', 'status': 'operational', 'type': 'GEANT - GBS'}],
'dashboard_info': {'interface_type': 'LOGICAL', 'name': 'GEANT-IT'}, 'dashboards': ['GBS_10G'],
'dashboards_info': [{'interface_type': 'LOGICAL', 'name': 'GEANT-IT'}],
'description': 'SRV_10GGBS CUSTOMER GEANT-IT #par-lon2-SUPERPOP-QFX-2-GEANT $GS-00081 |', 'ipv4': [],
'ipv6': [], 'name': 'xe-2/2/7.0', 'port_type': 'SERVICE', 'router': 'mx1.lon2.uk.geant.net', 'snmp-index': 613,
'vlan_type': 'VLAN'}, {'bundle': ['xe-0/1/0', 'xe-0/1/1'], 'bundle-parents': ['xe-0/1/0', 'xe-0/1/1'], 'circuits': [],
'dashboard_info': {'interface_type': 'AGGREGATE', 'name': 'LITNET'}, 'dashboards': ['NREN', 'RE_CUST'],
'dashboards_info': [{'interface_type': 'AGGREGATE', 'name': 'LITNET'}],
'description': 'LAG CUSTOMER LITNET AP2 #LITNET-AP2-LAG $GA-02071 |', 'ipv4': [], 'ipv6': [], 'name': 'ae10',
'port_type': 'ACCESS', 'router': 'art1.kau.lt.geant.net', 'snmp-index': 588, 'vlan_type': 'TRUNK'}, {'bundle': [], 'bundle-parents': ['et-0/0/2'], 'circuits': [
{'id': 679356, 'name': 'LAT-AP1-IPV6', 'status': 'operational', 'type': 'GEANT IP'}],
'dashboard_info': {'interface_type': 'LOGICAL', 'name': 'LAT'},
'dashboards': ['NREN', 'RE_CUST'],
'dashboards_info': [{'interface_type': 'LOGICAL', 'name': 'LAT'}],
'description': 'SRV_GLOBAL CUSTOMER LAT #LAT-AP1 $GS-00484 | ASN5538',
'ipv4': ['62.40.124.237/30'], 'ipv6': ['2001:798:99:1::51/126'], 'name': 'ae10.83',
'port_type': 'SERVICE', 'router': 'art1.kau.lt.geant.net', 'snmp-index': 604,
'vlan_type': 'VLAN'}, {'bundle': [], 'bundle-parents': ['et-2/1/2', 'et-2/1/5', 'et-11/1/0'], 'circuits': [
{'id': 707643, 'name': 'GARR-UDMILANO_EXPRESSROUTE_VLAN4086', 'status': 'operational',
'type': 'EXPRESS ROUTE'}], 'dashboard_info': {'interface_type': 'LOGICAL', 'name': 'GARR'},
'dashboards': ['GCS'], 'dashboards_info': [{'interface_type': 'LOGICAL', 'name': 'GARR'}],
'description': 'SRV_GCS CUSTOMER GARR MICROSOFT #GARR-UDMilano_ExpressRoute_Vlan4086 $GS-01148 | UNIT CONFIGURATION HAS BEEN SYSTEM GENERATED',
'ipv4': [], 'ipv6': [], 'name': 'ae10.4086', 'port_type': 'SERVICE', 'router': 'art1.kau.lt.geant.net',
'snmp-index': 795, 'vlan_type': 'VLAN'}, {'bundle': [], 'bundle-parents': [], 'circuits': [],
'dashboard_info': {'interface_type': 'PHYSICAL', 'name': 'BUD-ZAG'}, 'dashboards': ['INFRASTRUCTURE_BACKBONE'],
'dashboards_info': [{'interface_type': 'PHYSICAL', 'name': 'BUD-ZAG'}],
'description': 'PHY INFRASTRUCTURE BACKBONE P_ae5 | BUD-ZAG', 'ipv4': [], 'ipv6': [], 'name': 'et-7/0/2',
'port_type': 'UNKNOWN', 'router': 'mx1.bud.hu.geant.net', 'snmp-index': 1133, 'vlan_type': 'ACCESS'},
]
populate_inventory(
{
"/poller/interfaces": interfaces,
"/data/interfaces": interfaces,
"/poller/eumetsat-multicast": EUMETSAT_MULTICAST,
"/poller/regions": NREN_REGIONS,
}
)
_mocked_gws = mocker.patch(
"brian_dashboard_manager.grafana.provision.get_gws_direct"
)
_mocked_gws.return_value = []
_mocked_gws_indirect = mocker.patch(
"brian_dashboard_manager.grafana.provision.get_gws_indirect"
)
_mocked_gws_indirect.return_value = []
data_config["organizations"] = [
{"name": "Testorg1", "excluded_nrens": ["GEANT"], "excluded_dashboards": []},
]
provision(data_config)
folder_uid = "VLAN_Interfaces"
result = mock_grafana.dashboards_by_folder_uid[folder_uid]
assert len(result) == 3
assert result[0]["tags"][0] == "vlandash"
dashboards = mock_grafana.dashboards_by_folder_uid[folder_uid]
panels = []
for dashboard in dashboards:
panels.extend(dashboard["panels"])
expected_types = ["text", "row", "text", "row", "text", "row"]
assert [p["type"] for p in panels] == expected_types
assert "INFO" in panels[0]["options"]["content"]
assert "ae10" in set(p['title'] for p in panels)
panel_ae10 = [p for p in panels if p['title'] == 'ae10'][0]
assert len(panel_ae10["panels"]) == 3
@responses.activate
@pytest.mark.parametrize(
"folder_name, dashboard_id, expected_dashboard_count",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment