Commit 3e1df037 authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

Device component - gNMI OpenConfig driver:

- Updated Component Handler
- Updated Interface Handler
- Updated InterfaceCounter Handler
- Partial update of NetworkInstance Handler
- Updated Tools
- Added scripts to collect OpenConfig data model and build yang model bindings
- Minor cosmetic changes
- Updated test_gnmi.py and test_gnmi.sh script
- Updated requirements.in
parent daed600d
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@

anytree==2.8.0
APScheduler==3.10.1
bitarray==2.8.*
cryptography==36.0.2
#fastcache==1.1.0
Jinja2==3.0.3
@@ -32,7 +33,7 @@ tabulate
ipaddress
macaddress
yattag
pyang
pyang==2.6.*
git+https://github.com/robshakir/pyangbind.git
websockets==10.4

+27 −0
Original line number Diff line number Diff line
#!/bin/bash
# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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.

BASE_PATH=~/tfs-ctrl/src/device/service/drivers/gnmi_openconfig
GIT_BASE_PATH=${BASE_PATH}/git/openconfig

rm -rf ${GIT_BASE_PATH}

OC_PUBLIC_PATH=${GIT_BASE_PATH}/public
mkdir -p ${OC_PUBLIC_PATH}
git clone https://github.com/openconfig/public.git ${OC_PUBLIC_PATH}

#OC_HERCULES_PATH=${GIT_BASE_PATH}/hercules
#mkdir -p ${OC_HERCULES_PATH}
#git clone https://github.com/openconfig/hercules.git ${OC_HERCULES_PATH}
+106 −0
Original line number Diff line number Diff line
#!/bin/bash
# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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.

BASE_PATH=~/tfs-ctrl/src/device/service/drivers/gnmi_openconfig
GIT_BASE_PATH=${BASE_PATH}/git/openconfig
OC_PUBLIC_MODELS_PATH=${GIT_BASE_PATH}/public/release/models
IETF_MODELS_PATH=${GIT_BASE_PATH}/public/third_party/ietf
#OC_HERCULES_MODELS_PATH=${GIT_BASE_PATH}/hercules/yang

OUT_FOLDER=openconfig
OUT_PATH=${BASE_PATH}/handlers
cd ${OUT_PATH}
export PYBINDPLUGIN=`/usr/bin/env python -c 'import pyangbind; import os; print ("{}/plugin".format(os.path.dirname(pyangbind.__file__)))'`

# -p ${OC_HERCULES_MODELS_PATH}/
# --split-class-dir openconfig_hercules
pyang --plugindir $PYBINDPLUGIN -p ${OC_PUBLIC_MODELS_PATH}/ -f pybind --split-class-dir ${OUT_FOLDER} \
    ${IETF_MODELS_PATH}/iana-if-type.yang                                               \
    ${IETF_MODELS_PATH}/ietf-interfaces.yang                                            \
    ${IETF_MODELS_PATH}/ietf-yang-types.yang                                            \
    ${OC_PUBLIC_MODELS_PATH}/acl/openconfig-icmpv4-types.yang                           \
    ${OC_PUBLIC_MODELS_PATH}/acl/openconfig-icmpv6-types.yang                           \
    ${OC_PUBLIC_MODELS_PATH}/acl/openconfig-packet-match-types.yang                     \
    ${OC_PUBLIC_MODELS_PATH}/acl/openconfig-packet-match.yang                           \
    ${OC_PUBLIC_MODELS_PATH}/defined-sets/openconfig-defined-sets.yang                  \
    ${OC_PUBLIC_MODELS_PATH}/interfaces/openconfig-if-aggregate.yang                    \
    ${OC_PUBLIC_MODELS_PATH}/interfaces/openconfig-if-ethernet.yang                     \
    ${OC_PUBLIC_MODELS_PATH}/interfaces/openconfig-if-ip.yang                           \
    ${OC_PUBLIC_MODELS_PATH}/interfaces/openconfig-interfaces.yang                      \
    ${OC_PUBLIC_MODELS_PATH}/mpls/openconfig-mpls-types.yang                            \
    ${OC_PUBLIC_MODELS_PATH}/openconfig-extensions.yang                                 \
    ${OC_PUBLIC_MODELS_PATH}/optical-transport/openconfig-transport-types.yang          \
    ${OC_PUBLIC_MODELS_PATH}/platform/openconfig-platform-common.yang                   \
    ${OC_PUBLIC_MODELS_PATH}/platform/openconfig-platform-controller-card.yang          \
    ${OC_PUBLIC_MODELS_PATH}/platform/openconfig-platform-cpu.yang                      \
    ${OC_PUBLIC_MODELS_PATH}/platform/openconfig-platform-ext.yang                      \
    ${OC_PUBLIC_MODELS_PATH}/platform/openconfig-platform-fabric.yang                   \
    ${OC_PUBLIC_MODELS_PATH}/platform/openconfig-platform-fan.yang                      \
    ${OC_PUBLIC_MODELS_PATH}/platform/openconfig-platform-healthz.yang                  \
    ${OC_PUBLIC_MODELS_PATH}/platform/openconfig-platform-integrated-circuit.yang       \
    ${OC_PUBLIC_MODELS_PATH}/platform/openconfig-platform-linecard.yang                 \
    ${OC_PUBLIC_MODELS_PATH}/platform/openconfig-platform-pipeline-counters.yang        \
    ${OC_PUBLIC_MODELS_PATH}/platform/openconfig-platform-port.yang                     \
    ${OC_PUBLIC_MODELS_PATH}/platform/openconfig-platform-psu.yang                      \
    ${OC_PUBLIC_MODELS_PATH}/platform/openconfig-platform-software.yang                 \
    ${OC_PUBLIC_MODELS_PATH}/platform/openconfig-platform-transceiver.yang              \
    ${OC_PUBLIC_MODELS_PATH}/platform/openconfig-platform-types.yang                    \
    ${OC_PUBLIC_MODELS_PATH}/platform/openconfig-platform.yang                          \
    ${OC_PUBLIC_MODELS_PATH}/qos/openconfig-qos-elements.yang                           \
    ${OC_PUBLIC_MODELS_PATH}/qos/openconfig-qos-interfaces.yang                         \
    ${OC_PUBLIC_MODELS_PATH}/qos/openconfig-qos-mem-mgmt.yang                           \
    ${OC_PUBLIC_MODELS_PATH}/qos/openconfig-qos-types.yang                              \
    ${OC_PUBLIC_MODELS_PATH}/qos/openconfig-qos.yang                                    \
    ${OC_PUBLIC_MODELS_PATH}/system/openconfig-alarm-types.yang                         \
    ${OC_PUBLIC_MODELS_PATH}/types/openconfig-inet-types.yang                           \
    ${OC_PUBLIC_MODELS_PATH}/types/openconfig-types.yang                                \
    ${OC_PUBLIC_MODELS_PATH}/types/openconfig-yang-types.yang                           \
    ${OC_PUBLIC_MODELS_PATH}/vlan/openconfig-vlan-types.yang                            \
    ${OC_PUBLIC_MODELS_PATH}/vlan/openconfig-vlan.yang                                  \
    ${OC_PUBLIC_MODELS_PATH}/network-instance/openconfig-network-instance.yang          \
    ${OC_PUBLIC_MODELS_PATH}/network-instance/openconfig-network-instance-l2.yang       \
    ${OC_PUBLIC_MODELS_PATH}/network-instance/openconfig-network-instance-l3.yang       \
    ${OC_PUBLIC_MODELS_PATH}/network-instance/openconfig-network-instance-types.yang    \
    ${OC_PUBLIC_MODELS_PATH}/network-instance/openconfig-evpn.yang                      \
    ${OC_PUBLIC_MODELS_PATH}/network-instance/openconfig-evpn-types.yang                \
    ${OC_PUBLIC_MODELS_PATH}/bgp/openconfig-bgp-types.yang                              \
    ${OC_PUBLIC_MODELS_PATH}/bgp/openconfig-bgp-errors.yang                             \


openconfig-aft
openconfig-bgp
openconfig-igmp
openconfig-isis
openconfig-local-routing
openconfig-mpls
openconfig-ospfv2
openconfig-pcep
openconfig-pim
openconfig-policy-forwarding
openconfig-policy-types
openconfig-routing-policy
openconfig-segment-routing




#    ${OC_HERCULES_MODELS_PATH}/openconfig-hercules-interfaces.yang             \
#    ${OC_HERCULES_MODELS_PATH}/openconfig-hercules-platform-chassis.yang       \
#    ${OC_HERCULES_MODELS_PATH}/openconfig-hercules-platform-linecard.yang      \
#    ${OC_HERCULES_MODELS_PATH}/openconfig-hercules-platform-node.yang          \
#    ${OC_HERCULES_MODELS_PATH}/openconfig-hercules-platform-port.yang          \
#    ${OC_HERCULES_MODELS_PATH}/openconfig-hercules-platform.yang               \
#    ${OC_HERCULES_MODELS_PATH}/openconfig-hercules-qos.yang                    \
#    ${OC_HERCULES_MODELS_PATH}/openconfig-hercules.yang                        \
+2 −2
Original line number Diff line number Diff line
@@ -132,8 +132,8 @@ class GnmiSessionHandler:
                    #resource_key_tuple[2] = True
                    results.extend(parse(str_path, value))
                except Exception as e: # pylint: disable=broad-except
                    MSG = 'Exception processing notification {:s}'
                    self._logger.exception(MSG.format(grpc_message_to_json_string(notification)))
                    MSG = 'Exception processing update {:s}'
                    self._logger.exception(MSG.format(grpc_message_to_json_string(update)))
                    results.append((str_path, e)) # if validation fails, store the exception

        #_results = sorted(results.items(), key=lambda x: x[1][0])
+22 −20
Original line number Diff line number Diff line
@@ -12,45 +12,45 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import logging
import logging #, json
import pyangbind.lib.pybindJSON as pybindJSON
from typing import Any, Dict, List, Tuple
from common.proto.kpi_sample_types_pb2 import KpiSampleType
from . import openconfig
from ._Handler import _Handler

LOGGER = logging.getLogger(__name__)

PATH_IF_CTR = "/interfaces/interface[name={:s}]/state/counters/{:s}"
PATH_IF_CTR = "/openconfig-interfaces:interfaces/interface[name={:s}]/state/counters/{:s}"

#pylint: disable=abstract-method
class ComponentHandler(_Handler):
    def get_resource_key(self) -> str: return '/endpoints/endpoint'
    def get_path(self) -> str: return '/components/component'
    def get_path(self) -> str: return '/openconfig-platform:components'

    def parse(self, json_data : Dict) -> List[Tuple[str, Dict[str, Any]]]:
        #LOGGER.info('json_data = {:s}'.format(json.dumps(json_data)))
        json_component_list : List[Dict] = json_data.get('component', [])
        response = []
        for json_component in json_component_list:
            #LOGGER.info('json_component = {:s}'.format(json.dumps(json_component)))

            endpoint = {}
        oc_components = pybindJSON.loads_ietf(json_data, openconfig.components, 'components')
        #LOGGER.info('oc_components = {:s}'.format(pybindJSON.dumps(oc_components, mode='ietf')))

            component_type = json_component.get('state', {}).get('type')
            if component_type is None: continue
            component_type = component_type.replace('oc-platform-types:', '')
            component_type = component_type.replace('openconfig-platform-types:', '')
            if component_type not in {'PORT'}: continue
            endpoint['type'] = '-'
        entries = []
        for component_key, oc_component in oc_components.component.items():
            #LOGGER.info('component_key={:s} oc_component={:s}'.format(
            #    component_key, pybindJSON.dumps(oc_component, mode='ietf')
            #))

            #LOGGER.info('PORT json_component = {:s}'.format(json.dumps(json_component)))
            component_name = oc_component.config.name

            component_name = json_component.get('name')
            if component_name is None: continue
            component_type = oc_component.state.type
            component_type = component_type.split(':')[-1]
            if component_type not in {'PORT'}: continue

            # TODO: improve mapping between interface name and component name
            # By now, computed by time for the sake of saving time for the Hackfest.
            interface_name = component_name.lower().replace('-port', '')

            endpoint['uuid'] = interface_name
            endpoint = {'uuid': interface_name, 'type': '-'}
            endpoint['sample_types'] = {
                KpiSampleType.KPISAMPLETYPE_BYTES_RECEIVED     : PATH_IF_CTR.format(interface_name, 'in-octets' ),
                KpiSampleType.KPISAMPLETYPE_BYTES_TRANSMITTED  : PATH_IF_CTR.format(interface_name, 'out-octets'),
@@ -59,5 +59,7 @@ class ComponentHandler(_Handler):
            }

            if len(endpoint) == 0: continue
            response.append(('/endpoints/endpoint[{:s}]'.format(endpoint['uuid']), endpoint))
        return response

            entries.append(('/endpoints/endpoint[{:s}]'.format(endpoint['uuid']), endpoint))
    
        return entries
Loading