Skip to content
Snippets Groups Projects
Commit c4e904f4 authored by Pablo Armingol's avatar Pablo Armingol
Browse files

Merge branch 'develop' of https://labs.etsi.org/rep/tfs/controller into...

Merge branch 'develop' of https://labs.etsi.org/rep/tfs/controller into feat/174-tid-add-support-to-nbi-to-export-the-l3-inventory
parents 140c73ed 3d16843b
No related branches found
No related tags found
2 merge requests!294Release TeraFlowSDN 4.0,!252Resolve "(TID) Add support to NBI to export the L3 inventory"
Showing
with 136 additions and 185 deletions
......@@ -45,6 +45,9 @@ include:
#- local: '/src/dlt/.gitlab-ci.yml'
- local: '/src/load_generator/.gitlab-ci.yml'
- local: '/src/bgpls_speaker/.gitlab-ci.yml'
- local: '/src/kpi_manager/.gitlab-ci.yml'
- local: '/src/kpi_value_api/.gitlab-ci.yml'
- local: '/src/kpi_value_writer/.gitlab-ci.yml'
# This should be last one: end-to-end integration tests
- local: '/src/tests/.gitlab-ci.yml'
......@@ -340,7 +340,7 @@ for COMPONENT in $TFS_COMPONENTS; do
echo " Deploying '$COMPONENT' component to Kubernetes..."
DEPLOY_LOG="$TMP_LOGS_FOLDER/deploy_${COMPONENT}.log"
kubectl --namespace $TFS_K8S_NAMESPACE apply -f "$MANIFEST" > "$DEPLOY_LOG"
COMPONENT_OBJNAME=$(echo "${COMPONENT}" | sed "s/\_/-/")
COMPONENT_OBJNAME=$(echo "${COMPONENT}" | sed "s/\_/-/g")
#kubectl --namespace $TFS_K8S_NAMESPACE scale deployment --replicas=0 ${COMPONENT_OBJNAME}service >> "$DEPLOY_LOG"
#kubectl --namespace $TFS_K8S_NAMESPACE scale deployment --replicas=1 ${COMPONENT_OBJNAME}service >> "$DEPLOY_LOG"
......@@ -391,7 +391,7 @@ printf "\n"
for COMPONENT in $TFS_COMPONENTS; do
echo "Waiting for '$COMPONENT' component..."
COMPONENT_OBJNAME=$(echo "${COMPONENT}" | sed "s/\_/-/")
COMPONENT_OBJNAME=$(echo "${COMPONENT}" | sed "s/\_/-/g")
kubectl wait --namespace $TFS_K8S_NAMESPACE \
--for='condition=available' --timeout=90s deployment/${COMPONENT_OBJNAME}service
WAIT_EXIT_CODE=$?
......
......@@ -24,5 +24,7 @@ cd $PROJECTDIR/src
# python3 kpi_manager/tests/test_unitary.py
RCFILE=$PROJECTDIR/coverage/.coveragerc
CRDB_SQL_ADDRESS=$(kubectl --namespace ${CRDB_NAMESPACE} get service cockroachdb-public -o 'jsonpath={.spec.clusterIP}')
export CRDB_URI="cockroachdb://tfs:tfs123@${CRDB_SQL_ADDRESS}:26257/tfs_kpi_mgmt?sslmode=require"
python3 -m pytest --log-level=DEBUG --log-cli-level=DEBUG --verbose \
kpi_manager/tests/test_kpi_db.py
......@@ -24,5 +24,7 @@ cd $PROJECTDIR/src
# python3 kpi_manager/tests/test_unitary.py
RCFILE=$PROJECTDIR/coverage/.coveragerc
CRDB_SQL_ADDRESS=$(kubectl --namespace ${CRDB_NAMESPACE} get service cockroachdb-public -o 'jsonpath={.spec.clusterIP}')
export CRDB_URI="cockroachdb://tfs:tfs123@${CRDB_SQL_ADDRESS}:26257/tfs_kpi_mgmt?sslmode=require"
python3 -m pytest --log-level=DEBUG --log-cli-level=DEBUG --verbose \
kpi_manager/tests/test_kpi_manager.py
......@@ -19,5 +19,7 @@ PROJECTDIR=`pwd`
cd $PROJECTDIR/src
RCFILE=$PROJECTDIR/coverage/.coveragerc
CRDB_SQL_ADDRESS=$(kubectl --namespace ${CRDB_NAMESPACE} get service cockroachdb-public -o 'jsonpath={.spec.clusterIP}')
export CRDB_URI="cockroachdb://tfs:tfs123@${CRDB_SQL_ADDRESS}:26257/tfs_kpi_mgmt?sslmode=require"
python3 -m pytest --log-level=DEBUG --log-cli-level=DEBUG --verbose \
kpi_value_writer/tests/test_metric_writer_to_prom.py
......@@ -15,7 +15,7 @@
# Build, tag, and push the Docker image to the GitLab Docker registry
build kpi-manager:
variables:
IMAGE_NAME: 'kpi-manager' # name of the microservice
IMAGE_NAME: 'kpi_manager' # name of the microservice
IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
stage: build
before_script:
......@@ -41,7 +41,7 @@ build kpi-manager:
# Apply unit test to the component
unit_test kpi-manager:
variables:
IMAGE_NAME: 'kpi-manager' # name of the microservice
IMAGE_NAME: 'kpi_manager' # name of the microservice
IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
stage: unit_test
needs:
......@@ -68,8 +68,6 @@ unit_test kpi-manager:
- docker ps -a
- CRDB_ADDRESS=$(docker inspect crdb --format "{{.NetworkSettings.Networks.teraflowbridge.IPAddress}}")
- echo $CRDB_ADDRESS
- NATS_ADDRESS=$(docker inspect nats --format "{{.NetworkSettings.Networks.teraflowbridge.IPAddress}}")
- echo $NATS_ADDRESS
- >
docker run --name $IMAGE_NAME -d -p 30010:30010
--env "CRDB_URI=cockroachdb://tfs:tfs123@${CRDB_ADDRESS}:26257/tfs_test?sslmode=require"
......
......@@ -27,11 +27,11 @@ class KpiEngine:
if crdb_uri is None:
CRDB_NAMESPACE = get_setting('CRDB_NAMESPACE')
CRDB_SQL_PORT = get_setting('CRDB_SQL_PORT')
CRDB_DATABASE = get_setting('CRDB_DATABASE')
CRDB_DATABASE = 'tfs_kpi_mgmt' # TODO: define variable get_setting('CRDB_DATABASE_KPI_MGMT')
CRDB_USERNAME = get_setting('CRDB_USERNAME')
CRDB_PASSWORD = get_setting('CRDB_PASSWORD')
CRDB_SSLMODE = get_setting('CRDB_SSLMODE')
crdb_uri = CRDB_URI_TEMPLATE.format(
crdb_uri = CRDB_URI_TEMPLATE.format(
CRDB_USERNAME, CRDB_PASSWORD, CRDB_NAMESPACE, CRDB_SQL_PORT, CRDB_DATABASE, CRDB_SSLMODE)
# crdb_uri = CRDB_URI_TEMPLATE.format(
# CRDB_USERNAME, CRDB_PASSWORD, CRDB_SQL_PORT, CRDB_DATABASE, CRDB_SSLMODE)
......
......@@ -18,10 +18,10 @@ from sqlalchemy.orm import sessionmaker
from kpi_manager.database.KpiEngine import KpiEngine
from kpi_manager.database.KpiModel import Kpi as KpiModel
from common.method_wrappers.ServiceExceptions import (
AlreadyExistsException, OperationFailedException)
AlreadyExistsException, OperationFailedException , NotFoundException)
LOGGER = logging.getLogger(__name__)
DB_NAME = "kpi"
DB_NAME = "tfs_kpi_mgmt"
class KpiDB:
def __init__(self):
......@@ -85,7 +85,8 @@ class KpiDB:
# LOGGER.debug(f"{model.__name__} ID found: {str(entity)}")
return entity
else:
LOGGER.debug(f"{model.__name__} ID not found: {str(id_to_search)}")
LOGGER.debug(f"{model.__name__} ID not found, No matching row: {str(id_to_search)}")
print("{:} ID not found, No matching row: {:}".format(model.__name__, id_to_search))
return None
except Exception as e:
session.rollback()
......
......@@ -52,13 +52,13 @@ class KpiManagerServiceServicerImpl(KpiManagerServiceServicer):
try:
kpi_id_to_search = request.kpi_id.uuid
row = self.kpi_db_obj.search_db_row_by_id(KpiModel, 'kpi_id', kpi_id_to_search)
if row is not None:
response = KpiModel.convert_row_to_KpiDescriptor(row)
return response
if row is None:
print ('No matching row found for kpi id: {:}'.format(kpi_id_to_search))
LOGGER.info('No matching row found kpi id: {:}'.format(kpi_id_to_search))
return Empty()
else:
response = KpiModel.convert_row_to_KpiDescriptor(row)
return response
except Exception as e:
print ('Unable to search kpi id. {:}'.format(e))
LOGGER.info('Unable to search kpi id. {:}'.format(e))
......
......@@ -37,7 +37,7 @@ from kpi_manager.tests.test_messages import create_kpi_descriptor_request, creat
from kpi_manager.service.KpiManagerService import KpiManagerService
from kpi_manager.client.KpiManagerClient import KpiManagerClient
from kpi_manager.tests.test_messages import create_kpi_descriptor_request
from kpi_value_writer.tests.test_messages import create_kpi_id_request
from kpi_manager.tests.test_messages import create_kpi_id_request
#from monitoring.service.NameMapping import NameMapping
......
......@@ -18,6 +18,12 @@ from common.proto.kpi_sample_types_pb2 import KpiSampleType
from common.proto.context_pb2 import DeviceId, LinkId, ServiceId, SliceId,\
ConnectionId, EndPointId
def create_kpi_id_request():
_create_kpi_id = kpi_manager_pb2.KpiId()
_create_kpi_id.kpi_id.uuid = str(uuid.uuid4())
return _create_kpi_id
def create_kpi_descriptor_request(descriptor_name: str = "Test_name"):
_create_kpi_request = kpi_manager_pb2.KpiDescriptor()
_create_kpi_request.kpi_id.kpi_id.uuid = str(uuid.uuid4())
......
......@@ -15,7 +15,7 @@
# Build, tag, and push the Docker image to the GitLab Docker registry
build kpi-value-api:
variables:
IMAGE_NAME: 'kpi-value-api' # name of the microservice
IMAGE_NAME: 'kpi_value_api' # name of the microservice
IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
stage: build
before_script:
......@@ -41,7 +41,7 @@ build kpi-value-api:
# Apply unit test to the component
unit_test kpi-value-api:
variables:
IMAGE_NAME: 'kpi-value-api' # name of the microservice
IMAGE_NAME: 'kpi_value_api' # name of the microservice
IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
stage: unit_test
needs:
......
......@@ -13,7 +13,6 @@
# limitations under the License.
import logging, signal, sys, threading
from prometheus_client import start_http_server
from common.Settings import get_log_level
from .KpiValueApiService import KpiValueApiService
......
......@@ -15,7 +15,7 @@
# Build, tag, and push the Docker image to the GitLab Docker registry
build kpi-value-writer:
variables:
IMAGE_NAME: 'kpi-value-writer' # name of the microservice
IMAGE_NAME: 'kpi_value_writer' # name of the microservice
IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
stage: build
before_script:
......@@ -41,7 +41,7 @@ build kpi-value-writer:
# Apply unit test to the component
unit_test kpi-value-writer:
variables:
IMAGE_NAME: 'kpi-value-writer' # name of the microservice
IMAGE_NAME: 'kpi_value_writer' # name of the microservice
IMAGE_TAG: 'latest' # tag of the container image (production, development, etc)
stage: unit_test
needs:
......
......@@ -17,20 +17,29 @@ import threading
from common.tools.kafka.Variables import KafkaConfig, KafkaTopic
from common.proto.kpi_value_api_pb2 import KpiValue
from common.proto.kpi_manager_pb2 import KpiDescriptor, KpiId
from common.Settings import get_service_port_grpc
from common.Constants import ServiceNameEnum
from common.tools.service.GenericGrpcService import GenericGrpcService
from confluent_kafka import KafkaError
from confluent_kafka import Consumer as KafkaConsumer
from kpi_manager.client.KpiManagerClient import KpiManagerClient
# -- test import --
from kpi_value_writer.tests.test_messages import create_kpi_descriptor_request
# from kpi_value_writer.tests.test_messages import create_kpi_descriptor_request
from .MetricWriterToPrometheus import MetricWriterToPrometheus
LOGGER = logging.getLogger(__name__)
ACTIVE_CONSUMERS = []
METRIC_WRITER = MetricWriterToPrometheus()
class KpiValueWriter(GenericGrpcService):
def __init__(self, cls_name : str = __name__) -> None:
port = get_service_port_grpc(ServiceNameEnum.KPIVALUEWRITER)
super().__init__(port, cls_name=cls_name)
class KpiValueWriter:
@staticmethod
def RunKafkaConsumer():
thread = threading.Thread(target=KpiValueWriter.KafkaConsumer, args=())
......@@ -44,11 +53,7 @@ class KpiValueWriter:
'group.id' : __class__,
'auto.offset.reset' : 'latest'}
)
metric_writer_to_prom = MetricWriterToPrometheus()
kpi_manager_client = KpiManagerClient()
print("Kpi manger client created: {:}".format(kpi_manager_client))
kafka_consumer.subscribe([KafkaTopic.VALUE.value])
LOGGER.debug("Kafka Consumer start listenng on topic: {:}".format(KafkaTopic.VALUE.value))
print("Kafka Consumer start listenng on topic: {:}".format(KafkaTopic.VALUE.value))
......@@ -84,15 +89,15 @@ class KpiValueWriter:
try:
kpi_descriptor_object = KpiDescriptor()
kpi_descriptor_object = kpi_manager_client.GetKpiDescriptor(kpi_id)
print("kpi descriptor received: {:}".format(kpi_descriptor_object))
if isinstance (kpi_descriptor_object, KpiDescriptor):
if kpi_descriptor_object.kpi_id.kpi_id.uuid == kpi_id.kpi_id.uuid:
# print("kpi descriptor received: {:}".format(kpi_descriptor_object))
# if isinstance (kpi_descriptor_object, KpiDescriptor):
LOGGER.info("Extracted KpiDescriptor: {:}".format(kpi_descriptor_object))
print("Extracted KpiDescriptor: {:}".format(kpi_descriptor_object))
MetricWriterToPrometheus.create_and_expose_cooked_kpi(kpi_descriptor_object, kpi_value)
METRIC_WRITER.create_and_expose_cooked_kpi(kpi_descriptor_object, kpi_value)
else:
LOGGER.info("Error in extracting KpiDescriptor {:}".format(kpi_descriptor_object))
print("Error in extracting KpiDescriptor {:}".format(kpi_descriptor_object))
LOGGER.info("No KPI Descriptor found in DB for Kpi ID: {:}".format(kpi_id))
print("No KPI Descriptor found in DB for Kpi ID: {:}".format(kpi_id))
except Exception as e:
LOGGER.info("Unable to get KpiDescriptor. Error: {:}".format(e))
print ("Unable to get KpiDescriptor. Error: {:}".format(e))
# Copyright 2022-2024 ETSI OSG/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.
# read Kafka stream from Kafka topic
import ast
import time
import threading
from confluent_kafka import KafkaError
from prometheus_client import start_http_server, Gauge, CollectorRegistry
from confluent_kafka import Consumer as KafkaConsumer
KAFKA_SERVER_IP = '127.0.0.1:9092'
KAFKA_TOPICS = {'request' : 'topic_request', 'response': 'topic_response',
'raw' : 'topic_raw' , 'labeled' : 'topic_labeled'}
CONSUMER_CONFIG = {'bootstrap.servers' : KAFKA_SERVER_IP,
'group.id' : 'kpi_writer',
'auto.offset.reset' : 'latest'}
KPIs_TO_SEARCH = ["node_network_receive_packets_total",
"node_network_receive_bytes_total",
"node_network_transmit_bytes_total",
"process_open_fds"]
PROM_METRICS = {}
KAFKA_REGISTERY = CollectorRegistry()
class KpiWriter:
def __init__(self) -> None:
pass
@staticmethod
def kpi_writer():
KpiWriter.create_prom_metrics_name()
threading.Thread(target=KpiWriter.kafka_listener, args=()).start()
@staticmethod
def kafka_listener():
"""
listener for events on Kafka topic.
"""
# Start up the server to expose the metrics at port number mention below.
start_http_server(8101, registry=KAFKA_REGISTERY)
kafka_consumer = KafkaConsumer(CONSUMER_CONFIG)
kafka_consumer.subscribe([KAFKA_TOPICS['labeled']])
while True:
receive_msg = kafka_consumer.poll(2.0)
if receive_msg is None:
# print (" - Telemetry frontend listening on Kafka Topic: ", KAFKA_TOPICS['raw']) # added for debugging purposes
continue
elif receive_msg.error():
if receive_msg.error().code() == KafkaError._PARTITION_EOF:
continue
else:
print("Consumer error: {}".format(receive_msg.error()))
continue
try:
new_event = receive_msg.value().decode('utf-8')
# print("New event on topic '{:}' is {:}".format(KAFKA_TOPICS['raw'], new_event))
# LOGGER.info("New event on topic '{:}' is {:}".format(KAFKA_TOPICS['raw'], new_event))
KpiWriter.write_metric_to_promtheus(new_event)
except Exception as e:
print(f"Error to consume event from topic: {KAFKA_TOPICS['labeled']}. Error detail: {str(e)}")
continue
# send metric to Prometheus
@staticmethod
def write_metric_to_promtheus(event):
event = ast.literal_eval(event) # converted into dict
print("New recevied event: {:}".format(event))
event_kpi_name = event['kpi_description']
if event_kpi_name in KPIs_TO_SEARCH:
PROM_METRICS[event_kpi_name].labels(
kpi_id = event['kpi_id'],
kpi_sample_type = event['kpi_sample_type'],
device_id = event['device_id'],
endpoint_id = event['endpoint_id'],
service_id = event['service_id'],
slice_id = event['slice_id'],
connection_id = event['connection_id'],
link_id = event['link_id']
).set(float(event['kpi_value']))
time.sleep(0.05)
@staticmethod
def create_prom_metrics_name():
metric_tags = ['kpi_id','kpi_sample_type','device_id',
'endpoint_id','service_id','slice_id','connection_id','link_id']
for metric_key in KPIs_TO_SEARCH:
metric_name = metric_key
metric_description = "description of " + str(metric_key)
try:
PROM_METRICS[metric_key] = Gauge (
metric_name, metric_description, metric_tags,
registry=KAFKA_REGISTERY )
# print("Metric pushed to Prometheus: {:}".format(PROM_METRICS[metric_key]))
except ValueError as e:
if 'Duplicated timeseries' in str(e):
print("Metric {:} is already registered. Skipping.".format(metric_name))
......@@ -50,4 +50,4 @@ class Hardware(Resource):
LOGGER.exception(MSG.format(str(device_uuid)))
response = jsonify({'error': str(e)})
response.status_code = HTTP_SERVERERROR
return response
\ No newline at end of file
return response
# Copyright 2022-2024 ETSI OSG/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.
import logging
from flask import request
from flask.json import jsonify
from flask_restful import Resource
from common.proto.context_pb2 import Empty
from context.client.ContextClient import ContextClient
from ..tools.Authentication import HTTP_AUTH
from ..tools.HttpStatusCodes import HTTP_OK, HTTP_SERVERERROR
from .YangHandler import YangHandler
LOGGER = logging.getLogger(__name__)
class HardwareMultipleDevices(Resource):
@HTTP_AUTH.login_required
def get(self):
LOGGER.debug('Request: {:s}'.format(str(request)))
try:
context_client = ContextClient()
list_devices = context_client.ListDevices(Empty())
LOGGER.info('Request: {:s}'.format(str(list_devices)))
hardware_list_reply = []
yang_handler = YangHandler()
for device in list_devices.devices:
hardware_reply = yang_handler.compose(device)
hardware_list_reply.append(hardware_reply)
yang_handler.destroy()
response = jsonify(hardware_list_reply)
response.status_code = HTTP_OK
except Exception as e: # pylint: disable=broad-except
MSG = 'Something went wrong Retrieving Hardware of Devices({:s})'
response = jsonify({'error': str(e)})
response.status_code = HTTP_SERVERERROR
return response
......@@ -44,63 +44,51 @@ class YangHandler:
dnode.free()
return message
@staticmethod
def convert_to_iso_date(date_str: str) -> Optional[str]:
date_str = date_str.strip('"')
# Define the regex pattern for ISO 8601 date format
pattern = r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[\+\-]\d{2}:\d{2})"
# Check if the input date string matches the pattern
if re.match(pattern, date_str):
return date_str # Already in ISO format
return date_str
else:
try:
# Parse the input date string as a datetime object
datetime_obj = datetime.datetime.strptime(date_str, "%Y-%m-%d")
# Convert to ISO format
iso_date = datetime_obj.isoformat() + "Z"
return iso_date
except ValueError:
return None # Invalid date format
return None
def compose(self, device : Device) -> Dict:
# compose device iterating through the components
hardware = self._yang_context.create_data_path('/ietf-hardware:hardware')
hardware = self._yang_context.create_data_path('/ietf-network-hardware-inventory:network-hardware-inventory')
network_elements = hardware.create_path('network-elements')
network_element = network_elements.create_path('network-element[uuid="{:s}"]'.format(device.device_id.device_uuid.uuid))
network_element.create_path('uuid', device.device_id.device_uuid.uuid)
network_element.create_path('name', device.name)
components = network_element.create_path('components')
physical_index = 1
for component in device.components:
attributes = component.attributes
component_new = hardware.create_path('component[name="{:s}"]'.format(component.name))
component_new = components.create_path('component[uuid="{:s}"]'.format(component.component_uuid.uuid))
component_new.create_path('name', component.name)
#Cambiar las clases especiales, su formato y añadir isfru
component_type = component.type
if component_type == "TRANSCEIVER" :
component_type = "module"
if component_type == "FRU" :
component_type = "slack"
component_new.create_path('is-fru', True)
else :
component_new.create_path('is-fru', False)
component_type = component_type.replace("_", "-").lower()
component_type = 'iana-hardware:' + component_type
component_new.create_path('class', component_type)
#Añadir resto de atributos en IETF
physical_index += 1
component_new.create_path('physical-index', physical_index)
component_new.create_path('description', attributes["description"])
component_new.create_path('parent', component.parent)
component_new.create_path('description', attributes["description"].replace('/"',""))
if "CHASSIS" not in component.type:
parent_component_references = component_new.create_path('parent-component-references')
parent = parent_component_references.create_path('component-reference[index="{:d}"]'.format(physical_index))
for component_parent in device.components:
if component.parent == component_parent.name :
parent.create_path('uuid', component_parent.component_uuid.uuid)
break
if attributes["mfg-date"] != "":
mfg_date = self.convert_to_iso_date(attributes["mfg-date"])
LOGGER.info('component[name="{:s}"]'.format(attributes["mfg-date"]))
......@@ -111,22 +99,23 @@ class YangHandler:
component_new.create_path('firmware-rev', attributes["firmware-version"])
component_new.create_path('serial-num', attributes["serial-num"])
component_new.create_path('mfg-name', attributes["mfg-name"])
if attributes["removable"]:
removable = attributes["removable"].lower()
if 'true' in removable:
component_new.create_path('is-fru', True)
elif 'false' in removable:
component_new.create_path('is-fru', False)
if attributes["id"]:
component_new.create_path('parent-rel-pos', attributes["id"])
component_new.create_path('uri', component.name)
component_new.create_path('uuid', component.component_uuid.uuid)
contains_child = []
for component2 in device.components:
if component.name == component2.parent :
contains_child.append(component2.name)
component_new.create_path('contains-child', contains_child)
for child in device.components:
if component.name == child.parent :
component_new.create_path('contained-child', child.component_uuid.uuid)
return json.loads(hardware.print_mem('json'))
def destroy(self) -> None:
self._yang_context.destroy()
\ No newline at end of file
self._yang_context.destroy()
......@@ -15,7 +15,9 @@
from nbi.service.rest_server.nbi_plugins.ietf_hardware.Hardware import Hardware
from nbi.service.rest_server.RestServer import RestServer
URL_PREFIX = "/restconf/data/device=<path:device_uuid>/ietf-hardware:hardware"
URL_PREFIX_DEVICE = "/restconf/data/device=<path:device_uuid>/ietf-network-hardware-inventory:network-hardware-inventory"
URL_PREFIX_HARDWARE = "/restconf/data/ietf-network-hardware-inventory:network-hardware-inventory"
def register_ietf_hardware(rest_server: RestServer):
rest_server.add_resource(Hardware, URL_PREFIX)
\ No newline at end of file
rest_server.add_resource(Hardware, URL_PREFIX_DEVICE)
rest_server.add_resource(HardwareMultipleDevices, URL_PREFIX_HARDWARE)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment