Skip to content
Snippets Groups Projects
Commit e9e63c13 authored by Saket Agrahari's avatar Saket Agrahari
Browse files

[COMP-354][COMP-352] : Ops & Network Automation

parent a2d31fc0
No related branches found
No related tags found
1 merge request!108[COMP-354][COMP-352] : Ops & Network Automation
......@@ -25,6 +25,8 @@ import NetworkPertTeam from "./pages/NetworkPertTeam";
import PassiveMonitoringPage from "./pages/PaasiveMonitoring";
import NetworkAlienWavePage from "./pages/NetworkAlienWave";
import NetworkAlienWaveInternalPage from "./pages/NetworkAlienWaveInternal";
import OPsAutomationPage from "./pages/OPsAutomation";
import NetworkAutomationPage from "./pages/NetworkAutomation";
const router = createBrowserRouter([
{ path: "/budget", element: <BudgetPage /> },
......@@ -61,6 +63,8 @@ const router = createBrowserRouter([
{ path: "/passive-monitoring", element: <PassiveMonitoringPage /> },
{ path: "/alien-wave", element: <NetworkAlienWavePage /> },
{ path: "/alien-wave-internal", element: <NetworkAlienWaveInternalPage /> },
{ path: "/ops-automation", element: <OPsAutomationPage /> },
{ path: "/network-automation", element: <NetworkAutomationPage /> },
{ path: "*", element: <Landing /> },
]);
......
......@@ -55,6 +55,16 @@ export interface AlienWave extends NrenAndYearDatapoint {
nr_of_alien_wave_third_party_services: (string | null),
}
export interface OPsAutomation extends NrenAndYearDatapoint {
ops_automation: (string | null),
ops_automation_specifics: (string | null),
}
export interface NetworkAutomation extends NrenAndYearDatapoint {
network_automation: (string | null),
network_automation_specifics: (string | null),
}
export interface AlienWaveInternal extends NrenAndYearDatapoint {
alien_wave_internal: (string | null)
}
......
import React from "react";
function ColorPill({ year, active, tooltip }) {
function ColorPill({ year, active, tooltip, rounded=false }) {
const pillStyle = {
width: rounded ? "30px" : "75px",
height: "30px",
margin: "2px"
};
return (
<div className="d-inline-block" key={year}>
{active && tooltip ? (
<div
className={`rounded-pill color-of-the-year-${year % 9} bottom-tooltip pill-shadow`}
style={{ width: "75px", height: "30px", margin: "2px" }}
style={pillStyle}
data-description={tooltip}
></div>
) : active ? (
<div
className={`rounded-pill color-of-the-year-${year % 9}`}
style={{ width: "75px", height: "30px", margin: "2px" }}
style={pillStyle}
></div>
): (
<div
className={`rounded-pill color-of-the-year-blank`}
style={{ width: "75px", height: "30px", margin: "2px" }}
style={pillStyle}
></div>
)}
</div>
......
......@@ -51,6 +51,16 @@ const NetworkSidebar = () => {
<h6 className="section-title" >Capacity</h6>
<hr className="fake-divider" />
<h6 className="section-title" >Software-Defined Networking (SDN) & Network Function Virtualisation(NFV)</h6>
<Row>
<Link to="/ops-automation" className="link-text-underline">
<span>NREN Automation of Operational Processes</span>
</Link>
</Row>
<Row>
<Link to="/network-automation" className="link-text-underline">
<span>Network Tasks for which NRENs Use Automation </span>
</Link>
</Row>
</Sidebar>
)
......
......@@ -172,7 +172,17 @@ function CompendiumData(): ReactElement {
<Link to="/alien-wave-internal" className="link-text-underline">
<span>Internal NREN Use of Alien Waves</span>
</Link>
</Row>
</Row>
<Row>
<Link to="/ops-automation" className="link-text-underline">
<span>NREN Automation of Operational Processes</span>
</Link>
</Row>
<Row>
<Link to="/network-automation" className="link-text-underline">
<span>Network Tasks for which NRENs Use Automation </span>
</Link>
</Row>
</div>
</CollapsibleBox>
<CollapsibleBox title={Sections.Services} startCollapsed>
......
import React, { useContext } from "react";
import { Table } from "react-bootstrap";
import { NetworkAutomation } from "../Schema";
import { createMatrixDataLookupForArrayColumnType } from "../helpers/dataconversion";
import ColorPill from "../components/ColorPill";
import DataPage from "../components/DataPage";
import Filter from "../components/graphing/Filter";
import { Sections } from "../helpers/constants";
import { FilterSelectionContext } from "../helpers/FilterSelectionProvider";
import ChartContainer from "../components/graphing/ChartContainer";
import { useData } from "../helpers/useData";
function NetworkAutomationPage(): React.ReactElement {
const { filterSelection, setFilterSelection } = useContext(FilterSelectionContext);
const { data: pertTeamData, years, nrens } = useData<NetworkAutomation>('/api/network/network-automation', setFilterSelection);
const selectedData = (pertTeamData).filter(data =>
filterSelection.selectedYears.includes(data.year) && filterSelection.selectedNrens.includes(data.nren)
);
const dataLookup = createMatrixDataLookupForArrayColumnType(selectedData, 'network_automation_specifics');
console.log('dataLookup-->', dataLookup);
const filterNode = <Filter
filterOptions={{ availableYears: [...years], availableNrens: [...nrens.values()] }}
filterSelection={filterSelection}
setFilterSelection={setFilterSelection}
coloredYears
/>
const showYears = [...filterSelection.selectedYears.filter(year => years.has(year))].sort();
return (
<DataPage title="Network Tasks for which NRENs Use Automation "
description="The table below shows which NRENs have, or plan to, automate their
operational processes, with specification of which processes, and the names of
software and tools used for this given when appropriate."
category={Sections.Network} filter={filterNode}
data={selectedData} filename="network_automation_nrens_per_year">
<>
<ChartContainer>
<Table className="charging-struct-table" striped bordered responsive>
<colgroup>
<col span={1} style={{ width: "16%" }} />
<col span={2} style={{ width: "14%" }} />
<col span={2} style={{ width: "14%" }} />
<col span={2} style={{ width: "14%" }} />
<col span={2} style={{ width: "14%" }} />
<col span={2} style={{ width: "14%" }} />
<col span={2} style={{ width: "14%" }} />
</colgroup>
<thead>
<tr>
<th></th>
<th colSpan={2}>Device Provisioning</th>
<th colSpan={2}>Data Collection</th>
<th colSpan={2}>Configuration Management</th>
<th colSpan={2}>Compliance</th>
<th colSpan={2}>Reporting</th>
<th colSpan={2}>Troubleshooting</th>
</tr>
<tr>
<th></th>
<th>Yes</th>
<th>Planned</th>
<th>Yes</th>
<th>Planned</th>
<th>Yes</th>
<th>Planned</th>
<th>Yes</th>
<th>Planned</th>
<th>Yes</th>
<th>Planned</th>
<th>Yes</th>
<th>Planned</th>
</tr>
</thead>
<tbody>
{Array.from(dataLookup.entries()).map(([nren, nrenMap]) => (
<tr key={nren}>
<td>{nren}</td>
{["Device Provisioning", "Data Collection", "Configuration Management", "Compliance", "Reporting", "Troubleshooting"].map(column_key => (
<>
<td key={`${column_key}-yes`}>
{nrenMap.has(column_key) &&
showYears.map(year => {
const chargingYears = nrenMap.get(column_key)!;
const serviceInfo = chargingYears.get(year);
return (
<ColorPill
key={year}
year={year}
active={chargingYears.has(year)&& serviceInfo && serviceInfo.network_automation =='yes'}
tooltip={""}
rounded
/>
);
})
}
</td>
<td key={`${column_key}-planned`}>
{nrenMap.has(column_key) &&
showYears.map(year => {
const chargingYears = nrenMap.get(column_key)!;
const serviceInfo = chargingYears.get(year);
return (
<ColorPill
key={year}
year={year}
active={chargingYears.has(year)&& serviceInfo && serviceInfo.network_automation =='planned'}
tooltip={""}
rounded
/>
);
})
}
</td>
</>
))}
</tr>
))}
</tbody>
</Table>
</ChartContainer>
</>
</DataPage>
);
}
export default NetworkAutomationPage;
import React, { useContext } from "react";
import { Table } from "react-bootstrap";
import { OPsAutomation } from "../Schema";
import { createMatrixDataLookup } from "../helpers/dataconversion";
import ColorPill from "../components/ColorPill";
import DataPage from "../components/DataPage";
import Filter from "../components/graphing/Filter";
import { Sections } from "../helpers/constants";
import { FilterSelectionContext } from "../helpers/FilterSelectionProvider";
import ChartContainer from "../components/graphing/ChartContainer";
import { useData } from "../helpers/useData";
function OPsAutomationPage(): React.ReactElement {
const { filterSelection, setFilterSelection } = useContext(FilterSelectionContext);
const { data: pertTeamData, years, nrens } = useData<OPsAutomation>('/api/network/ops-automation', setFilterSelection);
const selectedData = (pertTeamData).filter(data =>
filterSelection.selectedYears.includes(data.year) && filterSelection.selectedNrens.includes(data.nren)
);
const dataLookup = createMatrixDataLookup(selectedData, 'ops_automation');
const filterNode = <Filter
filterOptions={{ availableYears: [...years], availableNrens: [...nrens.values()] }}
filterSelection={filterSelection}
setFilterSelection={setFilterSelection}
coloredYears
/>
const showYears = [...filterSelection.selectedYears.filter(year => years.has(year))].sort();
return (
<DataPage title="NREN Automation of Operational Processes"
description="The table below shows which NRENs have, or plan to, automate their
operational processes, with specification of which processes, and the names of
software and tools used for this given when appropriate."
category={Sections.Network} filter={filterNode}
data={selectedData} filename="ops_automation_nrens_per_year">
<>
<ChartContainer>
<Table className="charging-struct-table" striped bordered responsive>
<colgroup>
<col span={1} style={{ width: "25%" }} />
<col span={1} style={{ width: "25%" }} />
<col span={1} style={{ width: "25%" }} />
<col span={1} style={{ width: "25%" }} />
</colgroup>
<thead>
<tr>
<th></th>
<th>Yes</th>
<th>No</th>
<th>Planned</th>
</tr>
</thead>
<tbody>
{Array.from(dataLookup.entries()).map(([nren, nrenMap]) => (
<tr key={nren}>
<td>{nren}</td>
{["yes",
"no",
"planned"].map(column_key => (
<td key={column_key}>
{nrenMap.has(column_key) &&
showYears.map(year => {
const chargingYears = nrenMap.get(column_key)!;
const serviceInfo = chargingYears.get(year);
return <ColorPill key={year} year={year} active={chargingYears.has(year)} tooltip={serviceInfo?.ops_automation_specifics} rounded/>;
})
}
</td>
))}
</tr>
))}
</tbody>
</Table>
</ChartContainer>
</>
</DataPage>
);
}
export default OPsAutomationPage;
......@@ -104,12 +104,12 @@
.fake-divider {
border: none;
border-top: 1px solid #939393;
margin: 20px 0;
margin: 2px 0;
}
.section-title {
color: #939393;
margin-top: 20px;
margin-top: 10px;
}
.link-text-underline:hover {
......
from typing import Any
from compendium_v2.db.presentation_models import PertTeam, PassiveMonitoring, AlienWave
from compendium_v2.db.presentation_models import PertTeam, PassiveMonitoring, AlienWave, OpsAutomation, NetworkAutomation
from compendium_v2.routes import common
from flask import Blueprint, jsonify
......@@ -66,6 +66,46 @@ ALIEN_WAVE_RESPONSE_SCHEMA = {
'items': {'$ref': '#/definitions/alien_wave'}
}
OPS_AUTOMATION_RESPONSE_SCHEMA = {
'$schema': 'http://json-schema.org/draft-07/schema#',
'definitions': {
'alien_wave': {
'type': 'object',
'properties': {
'nren': {'type': 'string'},
'nren_country': {'type': 'string'},
'year': {'type': 'integer'},
'ops_automation': {'type': 'string'},
'ops_automation_specifics': {'type': 'string'},
},
'required': ['nren', 'nren_country', 'year'],
'additionalProperties': False
}
},
'type': 'array',
'items': {'$ref': '#/definitions/alien_wave'}
}
NETWORK_AUTOMATION_RESPONSE_SCHEMA = {
'$schema': 'http://json-schema.org/draft-07/schema#',
'definitions': {
'alien_wave': {
'type': 'object',
'properties': {
'nren': {'type': 'string'},
'nren_country': {'type': 'string'},
'year': {'type': 'integer'},
'ops_automation': {'type': 'string'},
'ops_automation_specifics': {'type': 'string'},
},
'required': ['nren', 'nren_country', 'year'],
'additionalProperties': False
}
},
'type': 'array',
'items': {'$ref': '#/definitions/alien_wave'}
}
def pert_team_extract_data(pert_team: PertTeam) -> dict:
return {
......@@ -175,3 +215,77 @@ def alien_wave_view() -> Any:
entries.append(alien_wave_extract_data(entry))
return jsonify(entries)
def ops_automation_extract_data(ops_automation: OpsAutomation) -> dict:
return {
'nren': ops_automation.nren.name,
'nren_country': ops_automation.nren.country,
'year': int(ops_automation.year),
'ops_automation': ops_automation.ops_automation.value
if ops_automation.ops_automation is not None else None,
'ops_automation_specifics': ops_automation.ops_automation_specifics
}
@routes.route('/ops-automation', methods=['GET'])
@common.require_accepts_json
def ops_automation_view() -> Any:
"""
handler for /api/network/ops-automation requests
Endpoint for getting the fibre operation models the NREN.
This endpoint retrieves fibre operation model that of the NREN.
response will be formatted as:
.. asjson::
compendium_v2.routes.network.OPS_AUTOMATION_RESPONSE_SCHEMA
:return:
"""
entries = []
records = common.get_data(OpsAutomation)
for entry in records:
entries.append(ops_automation_extract_data(entry))
return jsonify(entries)
def network_automation_extract_data(network_automation: NetworkAutomation) -> dict:
return {
'nren': network_automation.nren.name,
'nren_country': network_automation.nren.country,
'year': int(network_automation.year),
'network_automation': network_automation.network_automation.value
if network_automation.network_automation is not None else None,
'network_automation_specifics': network_automation.network_automation_specifics
}
@routes.route('/network-automation', methods=['GET'])
@common.require_accepts_json
def network_automation_extract_data_view() -> Any:
"""
handler for /api/network/network-automation requests
Endpoint for getting the fibre operation models the NREN.
This endpoint retrieves fibre operation model that of the NREN.
response will be formatted as:
.. asjson::
compendium_v2.routes.network.NETWORK_AUTOMATION_RESPONSE_SCHEMA
:return:
"""
entries = []
records = common.get_data(NetworkAutomation)
for entry in records:
entries.append(network_automation_extract_data(entry))
return jsonify(entries)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment