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

First version

parent eeb16213
No related branches found
No related tags found
1 merge request!168Draft: Resolve "(TID) Add support to NBI to export the device inventory items"
Showing
with 470 additions and 3 deletions
......@@ -24,6 +24,8 @@ service DeviceService {
rpc DeleteDevice (context.DeviceId ) returns (context.Empty ) {}
rpc GetInitialConfig(context.DeviceId ) returns (context.DeviceConfig) {}
rpc MonitorDeviceKpi(MonitoringSettings) returns (context.Empty ) {}
rpc DeviceInventory (context.DeviceId) returns (context.Empty ) {}
}
message MonitoringSettings {
......
......@@ -24,6 +24,7 @@ from .rest_server.nbi_plugins.debug_api import register_debug_api
from .rest_server.nbi_plugins.etsi_bwm import register_etsi_bwm_api
from .rest_server.nbi_plugins.ietf_l2vpn import register_ietf_l2vpn
from .rest_server.nbi_plugins.ietf_network_slice import register_ietf_nss
from .rest_server.nbi_plugins.ietf_inventory import register_ietf_inventory
terminate = threading.Event()
LOGGER = None
......@@ -64,6 +65,7 @@ def main():
register_etsi_bwm_api(rest_server)
register_ietf_l2vpn(rest_server) # Registering L2VPN entrypoint
register_ietf_nss(rest_server) # Registering NSS entrypoint
register_ietf_inventory(rest_server) # Registering inventories
rest_server.start()
# Wait for Ctrl+C or termination signal
......
# 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.
DEFAULT_MTU = 1512
DEFAULT_ADDRESS_FAMILIES = ['IPV4']
DEFAULT_BGP_AS = 65000
DEFAULT_BGP_ROUTE_TARGET = '{:d}:{:d}'.format(DEFAULT_BGP_AS, 333)
# TODO: improve definition of bearer mappings
# Bearer mappings:
# device_uuid:endpoint_uuid => (
# device_uuid, endpoint_uuid, router_id, route_dist, sub_if_index,
# address_ip, address_prefix, remote_router, circuit_id)
BEARER_MAPPINGS = {
# OFC'22
'R1-EMU:13/1/2': ('R1-EMU', '13/1/2', '10.10.10.1', '65000:100', 400, '3.3.2.1', 24, None, None),
'R2-EMU:13/1/2': ('R2-EMU', '13/1/2', '12.12.12.1', '65000:120', 450, '3.4.2.1', 24, None, None),
'R3-EMU:13/1/2': ('R3-EMU', '13/1/2', '20.20.20.1', '65000:200', 500, '3.3.1.1', 24, None, None),
'R4-EMU:13/1/2': ('R4-EMU', '13/1/2', '22.22.22.1', '65000:220', 550, '3.4.1.1', 24, None, None),
# OECC/PSC'22 - domain 1
'R1@D1:3/1' : ('R1@D1', '3/1', '10.0.1.1', '65001:101', 100, '1.1.3.1', 24, None, None),
'R1@D1:3/2' : ('R1@D1', '3/2', '10.0.1.1', '65001:101', 100, '1.1.3.2', 24, None, None),
'R1@D1:3/3' : ('R1@D1', '3/3', '10.0.1.1', '65001:101', 100, '1.1.3.3', 24, None, None),
'R2@D1:3/1' : ('R2@D1', '3/1', '10.0.1.2', '65001:102', 100, '1.2.3.1', 24, None, None),
'R2@D1:3/2' : ('R2@D1', '3/2', '10.0.1.2', '65001:102', 100, '1.2.3.2', 24, None, None),
'R2@D1:3/3' : ('R2@D1', '3/3', '10.0.1.2', '65001:102', 100, '1.2.3.3', 24, None, None),
'R3@D1:3/1' : ('R3@D1', '3/1', '10.0.1.3', '65001:103', 100, '1.3.3.1', 24, None, None),
'R3@D1:3/2' : ('R3@D1', '3/2', '10.0.1.3', '65001:103', 100, '1.3.3.2', 24, None, None),
'R3@D1:3/3' : ('R3@D1', '3/3', '10.0.1.3', '65001:103', 100, '1.3.3.3', 24, None, None),
'R4@D1:3/1' : ('R4@D1', '3/1', '10.0.1.4', '65001:104', 100, '1.4.3.1', 24, None, None),
'R4@D1:3/2' : ('R4@D1', '3/2', '10.0.1.4', '65001:104', 100, '1.4.3.2', 24, None, None),
'R4@D1:3/3' : ('R4@D1', '3/3', '10.0.1.4', '65001:104', 100, '1.4.3.3', 24, None, None),
# OECC/PSC'22 - domain 2
'R1@D2:3/1' : ('R1@D2', '3/1', '10.0.2.1', '65002:101', 100, '2.1.3.1', 24, None, None),
'R1@D2:3/2' : ('R1@D2', '3/2', '10.0.2.1', '65002:101', 100, '2.1.3.2', 24, None, None),
'R1@D2:3/3' : ('R1@D2', '3/3', '10.0.2.1', '65002:101', 100, '2.1.3.3', 24, None, None),
'R2@D2:3/1' : ('R2@D2', '3/1', '10.0.2.2', '65002:102', 100, '2.2.3.1', 24, None, None),
'R2@D2:3/2' : ('R2@D2', '3/2', '10.0.2.2', '65002:102', 100, '2.2.3.2', 24, None, None),
'R2@D2:3/3' : ('R2@D2', '3/3', '10.0.2.2', '65002:102', 100, '2.2.3.3', 24, None, None),
'R3@D2:3/1' : ('R3@D2', '3/1', '10.0.2.3', '65002:103', 100, '2.3.3.1', 24, None, None),
'R3@D2:3/2' : ('R3@D2', '3/2', '10.0.2.3', '65002:103', 100, '2.3.3.2', 24, None, None),
'R3@D2:3/3' : ('R3@D2', '3/3', '10.0.2.3', '65002:103', 100, '2.3.3.3', 24, None, None),
'R4@D2:3/1' : ('R4@D2', '3/1', '10.0.2.4', '65002:104', 100, '2.4.3.1', 24, None, None),
'R4@D2:3/2' : ('R4@D2', '3/2', '10.0.2.4', '65002:104', 100, '2.4.3.2', 24, None, None),
'R4@D2:3/3' : ('R4@D2', '3/3', '10.0.2.4', '65002:104', 100, '2.4.3.3', 24, None, None),
# ECOC'22
'DC1-GW:CS1-GW1': ('CS1-GW1', '10/1', '5.5.1.1', None, 0, None, None, '5.5.2.1', 111),
'DC1-GW:CS1-GW2': ('CS1-GW2', '10/1', '5.5.1.2', None, 0, None, None, '5.5.2.2', 222),
'DC2-GW:CS2-GW1': ('CS2-GW1', '10/1', '5.5.2.1', None, 0, None, None, '5.5.1.1', 111),
'DC2-GW:CS2-GW2': ('CS2-GW2', '10/1', '5.5.2.2', None, 0, None, None, '5.5.1.2', 222),
# NetworkX'22
'R1:1/2': ('R1', '1/2', '5.1.1.2', None, 0, None, None, None, None),
'R1:1/3': ('R1', '1/3', '5.1.1.3', None, 0, None, None, None, None),
'R2:1/2': ('R2', '1/2', '5.2.1.2', None, 0, None, None, None, None),
'R2:1/3': ('R2', '1/3', '5.2.1.3', None, 0, None, None, None, None),
'R3:1/2': ('R3', '1/2', '5.3.1.2', None, 0, None, None, None, None),
'R3:1/3': ('R3', '1/3', '5.3.1.3', None, 0, None, None, None, None),
'R4:1/2': ('R4', '1/2', '5.4.1.2', None, 0, None, None, None, None),
'R4:1/3': ('R4', '1/3', '5.4.1.3', None, 0, None, None, None, None),
# OFC'23
'PE1:1/1': ('PE1', '1/1', '10.1.1.1', None, 0, None, None, None, None),
'PE1:1/2': ('PE1', '1/2', '10.1.1.2', None, 0, None, None, None, None),
'PE2:1/1': ('PE2', '1/1', '10.2.1.1', None, 0, None, None, None, None),
'PE2:1/2': ('PE2', '1/2', '10.2.1.2', None, 0, None, None, None, None),
'PE3:1/1': ('PE3', '1/1', '10.3.1.1', None, 0, None, None, None, None),
'PE3:1/2': ('PE3', '1/2', '10.3.1.2', None, 0, None, None, None, None),
'PE4:1/1': ('PE4', '1/1', '10.4.1.1', None, 0, None, None, None, None),
'PE4:1/2': ('PE4', '1/2', '10.4.1.2', None, 0, None, None, None, None),
'R149:eth-1/0/22': ('R149', 'eth-1/0/22', '5.5.5.5', None, 0, None, None, '5.5.5.1', '100'),
'R155:eth-1/0/22': ('R155', 'eth-1/0/22', '5.5.5.1', None, 0, None, None, '5.5.5.5', '100'),
'R199:eth-1/0/21': ('R199', 'eth-1/0/21', '5.5.5.6', None, 0, None, None, '5.5.5.5', '100'),
}
# 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.
import grpc, logging
from common.Constants import ServiceNameEnum
from common.Settings import get_service_host, get_service_port_grpc
from common.proto.context_pb2 import Device, DeviceConfig, DeviceId, Empty
from common.proto.device_pb2 import MonitoringSettings
from common.proto.device_pb2_grpc import DeviceServiceStub
from common.tools.client.RetryDecorator import retry, delay_exponential
from common.tools.grpc.Tools import grpc_message_to_json_string
LOGGER = logging.getLogger(__name__)
MAX_RETRIES = 15
DELAY_FUNCTION = delay_exponential(initial=0.01, increment=2.0, maximum=5.0)
RETRY_DECORATOR = retry(max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect')
class DeviceClient:
def __init__(self, host=None, port=None):
if not host: host = get_service_host(ServiceNameEnum.DEVICE)
if not port: port = get_service_port_grpc(ServiceNameEnum.DEVICE)
self.endpoint = '{:s}:{:s}'.format(str(host), str(port))
LOGGER.debug('Creating channel to {:s}...'.format(str(self.endpoint)))
self.channel = None
self.stub = None
self.connect()
LOGGER.debug('Channel created')
def connect(self):
self.channel = grpc.insecure_channel(self.endpoint)
self.stub = DeviceServiceStub(self.channel)
def close(self):
if self.channel is not None: self.channel.close()
self.channel = None
self.stub = None
@RETRY_DECORATOR
def AddDevice(self, request : Device) -> DeviceId:
LOGGER.debug('AddDevice request: {:s}'.format(grpc_message_to_json_string(request)))
response = self.stub.AddDevice(request)
LOGGER.debug('AddDevice result: {:s}'.format(grpc_message_to_json_string(response)))
return response
@RETRY_DECORATOR
def ConfigureDevice(self, request : Device) -> DeviceId:
LOGGER.debug('ConfigureDevice request: {:s}'.format(grpc_message_to_json_string(request)))
response = self.stub.ConfigureDevice(request)
LOGGER.debug('ConfigureDevice result: {:s}'.format(grpc_message_to_json_string(response)))
return response
@RETRY_DECORATOR
def DeleteDevice(self, request : DeviceId) -> Empty:
LOGGER.debug('DeleteDevice request: {:s}'.format(grpc_message_to_json_string(request)))
response = self.stub.DeleteDevice(request)
LOGGER.debug('DeleteDevice result: {:s}'.format(grpc_message_to_json_string(response)))
return response
@RETRY_DECORATOR
def GetInitialConfig(self, request : DeviceId) -> DeviceConfig:
LOGGER.debug('GetInitialConfig request: {:s}'.format(grpc_message_to_json_string(request)))
response = self.stub.GetInitialConfig(request)
LOGGER.debug('GetInitialConfig result: {:s}'.format(grpc_message_to_json_string(response)))
return response
@RETRY_DECORATOR
def MonitorDeviceKpi(self, request : MonitoringSettings) -> Empty:
LOGGER.debug('MonitorDeviceKpi request: {:s}'.format(grpc_message_to_json_string(request)))
response = self.stub.MonitorDeviceKpi(request)
LOGGER.debug('MonitorDeviceKpi result: {:s}'.format(grpc_message_to_json_string(response)))
return response
@RETRY_DECORATOR
def DeviceInventory(self, request : MonitoringSettings) -> Empty:
LOGGER.debug('DeviceInventory request: {:s}'.format(grpc_message_to_json_string(request)))
response = self.stub.DeviceInventory(request)
LOGGER.debug('DeviceInventory result: {:s}'.format(grpc_message_to_json_string(response)))
return response
# @RETRY_DECORATOR
# def DeleteDevice(self, request : DeviceId) -> Empty:
# LOGGER.debug('DeleteDevice request: {:s}'.format(grpc_message_to_json_string(request)))
# response = self.stub.DeleteDevice(request)
# LOGGER.debug('DeleteDevice result: {:s}'.format(grpc_message_to_json_string(response)))
# return response
\ No newline at end of file
# 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.
import logging
from typing import Dict, List
from flask import request
from flask.json import jsonify
from flask_restful import Resource
from werkzeug.exceptions import UnsupportedMediaType
from common.Constants import DEFAULT_CONTEXT_NAME
from common.proto.context_pb2 import Device, DeviceConfig, DeviceId, Empty
from .DeviceClient import DeviceClient
from .schemas.device_inventory import SCHEMA_DEVICE_INVENTORY
from compute.service.rest_server.nbi_plugins.tools.HttpStatusCodes import HTTP_CREATED, HTTP_SERVERERROR
from compute.service.rest_server.nbi_plugins.tools.Validator import validate_message
from compute.service.rest_server.nbi_plugins.tools.Authentication import HTTP_AUTH
LOGGER = logging.getLogger(__name__)
class IETF_Inventories(Resource):
@HTTP_AUTH.login_required
def get(self):
return {}
@HTTP_AUTH.login_required
def post(self):
if not request.is_json: raise UnsupportedMediaType('JSON payload is required')
request_data : Dict = request.json
LOGGER.debug('Request: {:s}'.format(str(request_data)))
validate_message(SCHEMA_DEVICE_INVENTORY, request_data)
inventories : List[Dict] = request_data['ietf-inventory:dev-inventory']
for inventory in inventories:
try:
# pylint: disable=no-member
inventory_request = Device()
inventory_request.slice_id.context_id.context_uuid.uuid = DEFAULT_CONTEXT_NAME
inventory_request.slice_id.slice_uuid.uuid = inventory['component_uuid']
inventory_client = DeviceClient()
inventory_client.DeviceInventory()
response = jsonify({})
response.status_code = HTTP_CREATED
except Exception as e: # pylint: disable=broad-except
LOGGER.exception('Something went wrong Creating Service {:s}'.format(str(request)))
response = jsonify({'error': str(e)})
response.status_code = HTTP_SERVERERROR
return response
# 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.
import logging
from flask import request
from flask.json import jsonify
from flask_restful import Resource
from common.tools.context_queries.Device import get_device
from context.client.ContextClient import ContextClient
from ..tools.Authentication import HTTP_AUTH
from ..tools.HttpStatusCodes import HTTP_GATEWAYTIMEOUT, HTTP_NOCONTENT, HTTP_OK, HTTP_SERVERERROR
LOGGER = logging.getLogger(__name__)
class IETF_Inventory(Resource):
@HTTP_AUTH.login_required
def get(self, device_id : str):
LOGGER.debug('Device_id: {:s}'.format(str(device_id)))
LOGGER.debug('Request: {:s}'.format(str(request)))
try:
context_client = ContextClient()
target = get_device(context_client, device_id, rw_copy=True)
if target is None:
raise Exception('Device({:s}) not found in database'.format(str(device_id)))
if target.device_id.device_uuid.uuid != device_id: # pylint: disable=no-member
raise Exception('Inventory retrieval failed. Wrong Device Id was returned')
response = jsonify({})
response.status_code = HTTP_OK
except Exception as e: # pylint: disable=broad-except
LOGGER.exception('Something went wrong Retrieving Device Inventory({:s})'.format(str(device_id)))
response = jsonify({'error': str(e)})
response.status_code = HTTP_SERVERERROR
return response
# 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.
# RFC 8466 - L2VPN Service Model (L2SM)
# Ref: https://datatracker.ietf.org/doc/html/rfc8466
from flask_restful import Resource
from compute.service.rest_server.RestServer import RestServer
from .IETF_Inventories import IETF_Inventories
from .IETF_Inventory import IETF_Inventory
URL_PREFIX = '/data/inventory'
def _add_resource(rest_server : RestServer, resource : Resource, *urls, **kwargs):
urls = [(URL_PREFIX + url) for url in urls]
rest_server.add_resource(resource, *urls, **kwargs)
def register_ietf_inventory(rest_server : RestServer):
_add_resource(rest_server, IETF_Inventories,
'/device-inventories')
_add_resource(rest_server, IETF_Inventory,
'/device-inventories/device-inventory=<device_id>', '/device-inventories/device-inventory=<device_id>')
# 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.
# String pattern for UUIDs such as '3fd942ee-2dc3-41d1-aeec-65aa85d117b2'
REGEX_UUID = r'[a-fA-F0-9]{8}\-[a-fA-F0-9]{4}\-[a-fA-F0-9]{4}\-[a-fA-F0-9]{4}\-[a-fA-F0-9]{12}'
# 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.
# 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.
# Example request:
# request = {'ietf-l2vpn-svc:vpn-service': [{
# 'vpn-id': 'c6270231-f1de-4687-b2ed-7b58f9105775',
# 'vpn-svc-type': 'vpws',
# 'svc-topo': 'any-to-any',
# 'customer-name': 'osm'
# }]}
from .Common import REGEX_UUID
SCHEMA_DEVICE_INVENTORY = {
'$schema': 'https://json-schema.org/draft/2020-12/schema',
'type': 'object',
'properties': {
'Component': {
'type': 'array',
'items': {
'type': 'object',
'required': ['component_uuid', 'name', 'type', 'attributes', 'parent'],
'properties': {
'component_uuid': {'type': 'string', 'pattern': REGEX_UUID},
'name': {'type': 'string'},
'type': {'type': 'string'},
'attributes': {
'type': 'object',
'patternProperties': {
'^.*$': {'type': 'string'},
},
},
'parent': {'type': 'string'},
},
},
}
}
}
......@@ -80,3 +80,18 @@ class DeviceClient:
response = self.stub.MonitorDeviceKpi(request)
LOGGER.debug('MonitorDeviceKpi result: {:s}'.format(grpc_message_to_json_string(response)))
return response
@RETRY_DECORATOR
def DeviceInventory(self, request : MonitoringSettings) -> Empty:
LOGGER.debug('DeviceInventory request: {:s}'.format(grpc_message_to_json_string(request)))
response = self.stub.DeviceInventory(request)
LOGGER.debug('DeviceInventory result: {:s}'.format(grpc_message_to_json_string(response)))
return response
# @RETRY_DECORATOR
# def DeleteDevice(self, request : DeviceId) -> Empty:
# LOGGER.debug('DeleteDevice request: {:s}'.format(grpc_message_to_json_string(request)))
# response = self.stub.DeleteDevice(request)
# LOGGER.debug('DeleteDevice result: {:s}'.format(grpc_message_to_json_string(response)))
# return response
\ No newline at end of file
......@@ -33,7 +33,7 @@ from .ErrorMessages import ERROR_MISSING_DRIVER, ERROR_MISSING_KPI
from .Tools import (
check_connect_rules, check_no_endpoints, compute_rules_to_add_delete, configure_rules, deconfigure_rules,
get_device_controller_uuid, populate_config_rules, populate_endpoint_monitoring_resources, populate_endpoints,
populate_initial_config_rules, subscribe_kpi, unsubscribe_kpi, update_endpoints)
populate_initial_config_rules, subscribe_kpi, unsubscribe_kpi, update_endpoints, populate_inventory)
LOGGER = logging.getLogger(__name__)
......@@ -115,7 +115,7 @@ class DeviceServiceServicerImpl(DeviceServiceServicer):
else:
t_pop_config_rules = None
# TODO: populate components
# TODO: populate components Borrar components de la lista
if len(errors) > 0:
for error in errors: LOGGER.error(error)
......@@ -365,3 +365,31 @@ class DeviceServiceServicerImpl(DeviceServiceServicer):
return Empty()
finally:
self.mutex_queues.signal_done(device_uuid)
@safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
def DeviceInventory(self, request : DeviceId, context : grpc.ServicerContext) -> DeviceConfig:
device_uuid = request.device_uuid.uuid
self.mutex_queues.wait_my_turn(device_uuid)
try:
context_client = ContextClient()
device = get_device(
context_client, device_uuid, rw_copy=False, include_endpoints=False, include_components=True,
include_config_rules=False)
if device is None:
raise NotFoundException('Device', device_uuid, extra_details='loading in DeleteDevice')
driver : _Driver = get_driver(self.driver_instance_cache, device)
if driver is None:
msg = ERROR_MISSING_DRIVER.format(device_uuid=str(device_uuid))
raise OperationFailedException('GetInitialConfig', extra_details=msg)
device_config = DeviceConfig()
populate_inventory(device_uuid, device_config, driver)
return device_config
finally:
self.mutex_queues.signal_done(device_uuid)
......@@ -21,7 +21,7 @@ from common.proto.device_pb2 import MonitoringSettings
from common.proto.kpi_sample_types_pb2 import KpiSampleType
from common.tools.grpc.ConfigRules import update_config_rule_custom
from common.tools.grpc.Tools import grpc_message_to_json
from .driver_api._Driver import _Driver, RESOURCE_ENDPOINTS
from .driver_api._Driver import _Driver, RESOURCE_ENDPOINTS, RESOURCE_INVENTORY
from .monitoring.MonitoringLoops import MonitoringLoops
from .ErrorMessages import (
ERROR_BAD_RESOURCE, ERROR_DELETE, ERROR_GET, ERROR_GET_INIT, ERROR_MISSING_KPI, ERROR_SAMPLETYPE, ERROR_SET,
......@@ -434,3 +434,14 @@ def update_endpoints(src_device : Device, dst_device : Device) -> None:
dst_topology_id = dst_endpoint_id.topology_id
if len(src_topology_uuid) > 0: dst_topology_id.topology_uuid.uuid = src_topology_uuid
if len(src_context_uuid) > 0: dst_topology_id.context_id.context_uuid.uuid = src_context_uuid
def populate_inventory(
device : Device, driver : _Driver, monitoring_loops : MonitoringLoops,
new_sub_devices : Dict[str, Device], new_sub_links : Dict[str, Link]
) -> List[str]:
device_uuid = device.device_id.device_uuid.uuid
device_name = device.name
resources_to_get = [RESOURCE_INVENTORY]
results_getInventory = driver.GetConfig(resources_to_get)
LOGGER.debug('results_get_inventory = {:s}'.format(str(results_getInventory)))
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