Commit 98e65662 authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

Tests - Tools - SIMAP Server - Client:

- Added support for SIMAP telemetry
parent f122bd02
Loading
Loading
Loading
Loading
+109 −1
Original line number Diff line number Diff line
@@ -13,7 +13,7 @@
# limitations under the License.


from typing import Dict, List, Tuple
from typing import Dict, List, Optional, Tuple
from common.tools.rest_conf.client.RestConfClient import RestConfClient


@@ -62,6 +62,51 @@ class TerminationPoint:
        endpoint = TerminationPoint.ENDPOINT_ID.format(self._network_id, self._node_id, self._tp_id)
        self._restconf_client.delete(endpoint)


class NodeTelemetry:
    ENDPOINT = '/ietf-network:networks/network={:s}/node={:s}/simap-telemetry:simap-telemetry'

    def __init__(self, restconf_client : RestConfClient, network_id : str, node_id : str):
        self._restconf_client = restconf_client
        self._network_id = network_id
        self._node_id = node_id

    def create(
        self, cpu_utilization : float, related_service_ids : List[str] = []
    ) -> None:
        endpoint = NodeTelemetry.ENDPOINT.format(self._network_id, self._node_id)
        telemetry = {
            'cpu-utilization': '{:.2f}'.format(cpu_utilization),
        }
        if len(related_service_ids) > 0: telemetry['related-service-ids'] = related_service_ids
        node = {'node-id': self._node_id, 'simap-telemetry:simap-telemetry': telemetry}
        network = {'network-id': self._network_id, 'node': [node]}
        payload  = {'ietf-network:networks': {'network': [network]}}
        self._restconf_client.post(endpoint, payload)

    def get(self) -> Dict:
        endpoint = NodeTelemetry.ENDPOINT.format(self._network_id, self._node_id)
        telemetry : Dict = self._restconf_client.get(endpoint)
        return telemetry

    def update(
        self, cpu_utilization : float, related_service_ids : List[str] = []
    ) -> None:
        endpoint = NodeTelemetry.ENDPOINT.format(self._network_id, self._node_id)
        telemetry = {
            'cpu-utilization': '{:.2f}'.format(cpu_utilization),
        }
        if len(related_service_ids) > 0: telemetry['related-service-ids'] = related_service_ids
        node = {'node-id': self._node_id, 'simap-telemetry:simap-telemetry': telemetry}
        network = {'network-id': self._network_id, 'node': [node]}
        payload  = {'ietf-network:networks': {'network': [network]}}
        self._restconf_client.patch(endpoint, payload)

    def delete(self) -> None:
        endpoint = NodeTelemetry.ENDPOINT.format(self._network_id, self._node_id)
        self._restconf_client.delete(endpoint)


class Node:
    ENDPOINT_NO_ID = '/ietf-network:networks/network={:s}'
    ENDPOINT_ID    = ENDPOINT_NO_ID + '/node={:s}'
@@ -71,6 +116,13 @@ class Node:
        self._network_id = network_id
        self._node_id = node_id
        self._tps : Dict[str, TerminationPoint] = dict()
        self._telemetry : Optional[NodeTelemetry] = None

    @property
    def telemetry(self) -> NodeTelemetry:
        if self._telemetry is None:
            self._telemetry = NodeTelemetry(self._restconf_client, self._network_id, self._node_id)
        return self._telemetry

    def termination_points(self) -> List[Dict]:
        tps : Dict = self._restconf_client.get(TerminationPoint.ENDPOINT_NO_ID)
@@ -119,6 +171,55 @@ class Node:
        endpoint = Node.ENDPOINT_ID.format(self._network_id, self._node_id)
        self._restconf_client.delete(endpoint)


class LinkTelemetry:
    ENDPOINT = '/ietf-network:networks/network={:s}/ietf-network-topology:link={:s}/simap-telemetry:simap-telemetry'

    def __init__(self, restconf_client : RestConfClient, network_id : str, link_id : str):
        self._restconf_client = restconf_client
        self._network_id = network_id
        self._link_id = link_id

    def create(
        self, bandwidth_utilization : float, latency : float,
        related_service_ids : List[str] = []
    ) -> None:
        endpoint = LinkTelemetry.ENDPOINT.format(self._network_id, self._link_id)
        telemetry = {
            'bandwidth-utilization': bandwidth_utilization,
            'latency'              : latency,
        }
        if len(related_service_ids) > 0: telemetry['related-service-ids'] = related_service_ids
        link = {'link-id': self._link_id, 'simap-telemetry:simap-telemetry': telemetry}
        network = {'network-id': self._network_id, 'ietf-network-topology:link': [link]}
        payload  = {'ietf-network:networks': {'network': [network]}}
        self._restconf_client.post(endpoint, payload)

    def get(self) -> Dict:
        endpoint = LinkTelemetry.ENDPOINT.format(self._network_id, self._link_id)
        telemetry : Dict = self._restconf_client.get(endpoint)
        return telemetry

    def update(
        self, bandwidth_utilization : float, latency : float,
        related_service_ids : List[str] = []
    ) -> None:
        endpoint = LinkTelemetry.ENDPOINT.format(self._network_id, self._link_id)
        telemetry = {
            'bandwidth-utilization': '{:.2f}'.format(bandwidth_utilization),
            'latency'              : '{:.3f}'.format(latency),
        }
        if len(related_service_ids) > 0: telemetry['related-service-ids'] = related_service_ids
        link = {'link-id': self._link_id, 'simap-telemetry:simap-telemetry': telemetry}
        network = {'network-id': self._network_id, 'ietf-network-topology:link': [link]}
        payload  = {'ietf-network:networks': {'network': [network]}}
        self._restconf_client.patch(endpoint, payload)

    def delete(self) -> None:
        endpoint = LinkTelemetry.ENDPOINT.format(self._network_id, self._link_id)
        self._restconf_client.delete(endpoint)


class Link:
    ENDPOINT_NO_ID = '/ietf-network:networks/network={:s}'
    ENDPOINT_ID    = ENDPOINT_NO_ID + '/ietf-network-topology:link={:s}'
@@ -127,6 +228,13 @@ class Link:
        self._restconf_client = restconf_client
        self._network_id = network_id
        self._link_id = link_id
        self._telemetry : Optional[LinkTelemetry] = None

    @property
    def telemetry(self) -> LinkTelemetry:
        if self._telemetry is None:
            self._telemetry = LinkTelemetry(self._restconf_client, self._network_id, self._link_id)
        return self._telemetry

    def create(
        self, src_node_id : str, src_tp_id : str, dst_node_id : str, dst_tp_id : str,
+109 −0
Original line number Diff line number Diff line
# Copyright 2022-2025 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from .SimapClient import SimapClient

def create_simap_te(simap_client : SimapClient) -> None:
    te_topo = simap_client.network('te')
    te_topo.create()

    te_topo.node('ONT1').create(termination_point_ids=['200', '500'])
    te_topo.node('ONT2').create(termination_point_ids=['200', '500'])
    te_topo.node('OLT' ).create(termination_point_ids=['200', '201', '500', '501'])
    te_topo.link('L1').create('ONT1', '500', 'OLT', '200')
    te_topo.link('L2').create('ONT2', '500', 'OLT', '201')

    te_topo.node('PE1').create(termination_point_ids=['200', '500', '501'])
    te_topo.node('P1' ).create(termination_point_ids=['500', '501'])
    te_topo.node('P2' ).create(termination_point_ids=['500', '501'])
    te_topo.node('PE2').create(termination_point_ids=['200', '500', '501'])
    te_topo.link('L5' ).create('PE1', '500', 'P1',  '500')
    te_topo.link('L6' ).create('PE1', '501', 'P2',  '500')
    te_topo.link('L9' ).create('P1',  '501', 'PE2', '500')
    te_topo.link('L10').create('P2',  '501', 'PE2', '501')

    te_topo.node('OA'  ).create(termination_point_ids=['200', '500', '501'])
    te_topo.node('OTN1').create(termination_point_ids=['500', '501'])
    te_topo.node('OTN2').create(termination_point_ids=['500', '501'])
    te_topo.node('OE'  ).create(termination_point_ids=['200', '500', '501'])
    te_topo.link('L7'  ).create('OA',   '500', 'OTN1', '500')
    te_topo.link('L8'  ).create('OA',   '501', 'OTN2', '500')
    te_topo.link('L11' ).create('OTN1', '501', 'OE',   '500')
    te_topo.link('L12' ).create('OTN2', '501', 'OE',   '501')

    te_topo.link('L3').create('OLT', '500', 'PE1', '200')
    te_topo.link('L4').create('OLT', '501', 'OA',  '200')

    te_topo.node('POP1').create(termination_point_ids=['200', '201', '500'])
    te_topo.link('L13').create('PE2', '200', 'POP1', '500')

    te_topo.node('POP2').create(termination_point_ids=['200', '201', '500'])
    te_topo.link('L14').create('OE', '200', 'POP2', '500')


def create_simap_trans(simap_client : SimapClient) -> None:
    simap_trans = simap_client.network('simap-trans')
    simap_trans.create(supporting_network_ids=['te'])

    site_1 = simap_trans.node('site1')
    site_1.create(supporting_node_ids=[('te', 'PE1')])
    site_1.termination_point('200').create(supporting_termination_point_ids=[('te', 'PE1', '200')])
    site_1.termination_point('500').create(supporting_termination_point_ids=[('te', 'PE1', '500')])
    site_1.termination_point('501').create(supporting_termination_point_ids=[('te', 'PE1', '501')])

    site_2 = simap_trans.node('site2')
    site_2.create(supporting_node_ids=[('te', 'PE2')])
    site_2.termination_point('200').create(supporting_termination_point_ids=[('te', 'PE2', '200')])
    site_2.termination_point('500').create(supporting_termination_point_ids=[('te', 'PE2', '500')])
    site_2.termination_point('501').create(supporting_termination_point_ids=[('te', 'PE2', '501')])

    simap_trans.link('Trans-L1').create('site1', '500', 'site2', '500', supporting_link_ids=[('te', 'L5'), ('te', 'L9')])


def create_simap_aggnet(simap_client : SimapClient) -> None:
    simap_aggnet = simap_client.network('simap-aggnet')
    simap_aggnet.create(supporting_network_ids=['te', 'simap-trans'])

    sdp_1 = simap_aggnet.node('sdp1')
    sdp_1.create(supporting_node_ids=[('te', 'OLT')])
    sdp_1.termination_point('200').create(supporting_termination_point_ids=[('te', 'OLT', '200')])
    sdp_1.termination_point('201').create(supporting_termination_point_ids=[('te', 'OLT', '201')])
    sdp_1.termination_point('500').create(supporting_termination_point_ids=[('te', 'OLT', '500')])
    sdp_1.termination_point('501').create(supporting_termination_point_ids=[('te', 'OLT', '501')])

    sdp_2 = simap_aggnet.node('sdp2')
    sdp_2.create(supporting_node_ids=[('te', 'POP1')])
    sdp_2.termination_point('200').create(supporting_termination_point_ids=[('te', 'POP1', '200')])
    sdp_2.termination_point('201').create(supporting_termination_point_ids=[('te', 'POP1', '201')])
    sdp_2.termination_point('500').create(supporting_termination_point_ids=[('te', 'POP1', '500')])

    simap_aggnet.link('AggNet-L1').create('sdp1', '500', 'sdp2', '500', supporting_link_ids=[('te', 'L3'), ('simap-trans', 'Trans-L1'), ('te', 'L13')])


def create_simap_e2enet(simap_client : SimapClient) -> None:
    simap_e2e = simap_client.network('simap-e2e')
    simap_e2e.create(supporting_network_ids=['te', 'simap-trans'])

    sdp_1 = simap_e2e.node('sdp1')
    sdp_1.create(supporting_node_ids=[('te', 'ONT1')])
    sdp_1.termination_point('200').create(supporting_termination_point_ids=[('te', 'ONT1', '200')])
    sdp_1.termination_point('500').create(supporting_termination_point_ids=[('te', 'ONT1', '500')])

    sdp_2 = simap_e2e.node('sdp2')
    sdp_2.create(supporting_node_ids=[('te', 'POP1')])
    sdp_2.termination_point('200').create(supporting_termination_point_ids=[('te', 'POP1', '200')])
    sdp_2.termination_point('201').create(supporting_termination_point_ids=[('te', 'POP1', '201')])
    sdp_2.termination_point('500').create(supporting_termination_point_ids=[('te', 'POP1', '500')])

    simap_e2e.link('E2E-L1').create('sdp1', '500', 'sdp2', '500', supporting_link_ids=[('te', 'L1'), ('simap-aggnet', 'AggNet-L1')])
+21 −92
Original line number Diff line number Diff line
@@ -13,14 +13,16 @@
# limitations under the License.


import json, logging
import json, logging, time
from common.tools.rest_conf.client.RestConfClient import RestConfClient
from .SimapClient import SimapClient
from .Tools import create_simap_aggnet, create_simap_e2enet, create_simap_te, create_simap_trans


logging.basicConfig(level=logging.INFO)
logging.getLogger('RestConfClient').setLevel(logging.WARN)
LOGGER = logging.getLogger(__name__)

logging.getLogger('RestConfClient').setLevel(logging.WARN)

def main() -> None:
    restconf_client = RestConfClient(
@@ -29,103 +31,30 @@ def main() -> None:
    )
    simap_client = SimapClient(restconf_client)

    te_topo = simap_client.network('te')
    te_topo.create()

    te_topo.node('ONT1').create(termination_point_ids=['200', '500'])
    te_topo.node('ONT2').create(termination_point_ids=['200', '500'])
    te_topo.node('OLT' ).create(termination_point_ids=['200', '201', '500', '501'])
    te_topo.link('L1').create('ONT1', '500', 'OLT', '200')
    te_topo.link('L2').create('ONT2', '500', 'OLT', '201')

    te_topo.node('PE1').create(termination_point_ids=['200', '500', '501'])
    te_topo.node('P1' ).create(termination_point_ids=['500', '501'])
    te_topo.node('P2' ).create(termination_point_ids=['500', '501'])
    te_topo.node('PE2').create(termination_point_ids=['200', '500', '501'])
    te_topo.link('L5' ).create('PE1', '500', 'P1',  '500')
    te_topo.link('L6' ).create('PE1', '501', 'P2',  '500')
    te_topo.link('L9' ).create('P1',  '501', 'PE2', '500')
    te_topo.link('L10').create('P2',  '501', 'PE2', '501')

    te_topo.node('OA'  ).create(termination_point_ids=['200', '500', '501'])
    te_topo.node('OTN1').create(termination_point_ids=['500', '501'])
    te_topo.node('OTN2').create(termination_point_ids=['500', '501'])
    te_topo.node('OE'  ).create(termination_point_ids=['200', '500', '501'])
    te_topo.link('L7'  ).create('OA',   '500', 'OTN1', '500')
    te_topo.link('L8'  ).create('OA',   '501', 'OTN2', '500')
    te_topo.link('L11' ).create('OTN1', '501', 'OE',   '500')
    te_topo.link('L12' ).create('OTN2', '501', 'OE',   '501')

    te_topo.link('L3').create('OLT', '500', 'PE1', '200')
    te_topo.link('L4').create('OLT', '501', 'OA',  '200')

    te_topo.node('POP1').create(termination_point_ids=['200', '201', '500'])
    te_topo.link('L13').create('PE2', '200', 'POP1', '500')

    te_topo.node('POP2').create(termination_point_ids=['200', '201', '500'])
    te_topo.link('L14').create('OE', '200', 'POP2', '500')



    simap_trans = simap_client.network('simap-trans')
    simap_trans.create(supporting_network_ids=['te'])

    site_1 = simap_trans.node('site1')
    site_1.create(supporting_node_ids=[('te', 'PE1')])
    site_1.termination_point('200').create(supporting_termination_point_ids=[('te', 'PE1', '200')])
    site_1.termination_point('500').create(supporting_termination_point_ids=[('te', 'PE1', '500')])
    site_1.termination_point('501').create(supporting_termination_point_ids=[('te', 'PE1', '501')])

    site_2 = simap_trans.node('site2')
    site_2.create(supporting_node_ids=[('te', 'PE2')])
    site_2.termination_point('200').create(supporting_termination_point_ids=[('te', 'PE2', '200')])
    site_2.termination_point('500').create(supporting_termination_point_ids=[('te', 'PE2', '500')])
    site_2.termination_point('501').create(supporting_termination_point_ids=[('te', 'PE2', '501')])

    simap_trans.link('Trans-L1').create('site1', '500', 'site2', '500', supporting_link_ids=[('te', 'L5'), ('te', 'L9')])




    simap_aggnet = simap_client.network('simap-aggnet')
    simap_aggnet.create(supporting_network_ids=['te', 'simap-trans'])

    sdp_1 = simap_aggnet.node('sdp1')
    sdp_1.create(supporting_node_ids=[('te', 'OLT')])
    sdp_1.termination_point('200').create(supporting_termination_point_ids=[('te', 'OLT', '200')])
    sdp_1.termination_point('201').create(supporting_termination_point_ids=[('te', 'OLT', '201')])
    sdp_1.termination_point('500').create(supporting_termination_point_ids=[('te', 'OLT', '500')])
    sdp_1.termination_point('501').create(supporting_termination_point_ids=[('te', 'OLT', '501')])

    sdp_2 = simap_aggnet.node('sdp2')
    sdp_2.create(supporting_node_ids=[('te', 'POP1')])
    sdp_2.termination_point('200').create(supporting_termination_point_ids=[('te', 'POP1', '200')])
    sdp_2.termination_point('201').create(supporting_termination_point_ids=[('te', 'POP1', '201')])
    sdp_2.termination_point('500').create(supporting_termination_point_ids=[('te', 'POP1', '500')])

    simap_aggnet.link('AggNet-L1').create('sdp1', '500', 'sdp2', '500', supporting_link_ids=[('te', 'L3'), ('simap-trans', 'Trans-L1'), ('te', 'L13')])


    create_simap_te(simap_client)
    create_simap_trans(simap_client)
    create_simap_aggnet(simap_client)
    create_simap_e2enet(simap_client)

    print('networks=', json.dumps(simap_client.networks()))

    simap_e2e = simap_client.network('simap-e2e')
    simap_e2e.create(supporting_network_ids=['te', 'simap-trans'])
    trans_link = simap_client.network('simap-trans').link('Trans-L1')
    trans_node_site1 = simap_client.network('simap-trans').node('site1')
    trans_node_site2 = simap_client.network('simap-trans').node('site2')

    sdp_1 = simap_e2e.node('sdp1')
    sdp_1.create(supporting_node_ids=[('te', 'ONT1')])
    sdp_1.termination_point('200').create(supporting_termination_point_ids=[('te', 'ONT1', '200')])
    sdp_1.termination_point('500').create(supporting_termination_point_ids=[('te', 'ONT1', '500')])
    related_service_ids = ['trans-svc1', 'trans-svc2', 'trans-svc3']

    sdp_2 = simap_e2e.node('sdp2')
    sdp_2.create(supporting_node_ids=[('te', 'POP1')])
    sdp_2.termination_point('200').create(supporting_termination_point_ids=[('te', 'POP1', '200')])
    sdp_2.termination_point('201').create(supporting_termination_point_ids=[('te', 'POP1', '201')])
    sdp_2.termination_point('500').create(supporting_termination_point_ids=[('te', 'POP1', '500')])
    for i in range(1000):
        trans_link.telemetry.update(float(i), float(i), related_service_ids=related_service_ids)
        trans_node_site1.telemetry.update(float(i), related_service_ids=related_service_ids)
        trans_node_site2.telemetry.update(float(i), related_service_ids=related_service_ids)

    simap_e2e.link('E2E-L1').create('sdp1', '500', 'sdp2', '500', supporting_link_ids=[('te', 'L1'), ('simap-aggnet', 'AggNet-L1')])
        print('trans link  telemetry =', json.dumps(trans_link.telemetry.get()))
        print('trans site1 telemetry =', json.dumps(trans_node_site1.telemetry.get()))
        print('trans site2 telemetry =', json.dumps(trans_node_site2.telemetry.get()))

        time.sleep(10)

    print('networks=', json.dumps(simap_client.networks()))

if __name__ == '__main__':
    main()