From acf8948c6cd40c0d0d411fcabbe476ea329b8470 Mon Sep 17 00:00:00 2001 From: Iuri Malinoski Date: Thu, 24 Oct 2024 13:03:37 -0300 Subject: [PATCH 1/3] collecting data --- networkapi/api_interface/views.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/networkapi/api_interface/views.py b/networkapi/api_interface/views.py index 7d6d92c4b..e200fb64f 100644 --- a/networkapi/api_interface/views.py +++ b/networkapi/api_interface/views.py @@ -327,6 +327,10 @@ class InterfaceV3View(CustomAPIView): def get(self, request, *args, **kwargs): """URL: api/v3/interface/""" + log.info('InterfaceV3View GET') + log.info('kwargs: %s', kwargs) + log.info('search: %s', self.search) + if not kwargs.get('obj_ids'): obj_model = facade.get_interface_by_search(self.search) interfaces = obj_model['query_set'] @@ -354,6 +358,8 @@ def get(self, request, *args, **kwargs): only_main_property=only_main_property ) + log.info('get interfaces response: %s', data) + return Response(data, status=status.HTTP_200_OK) @logs_method_apiview @@ -369,8 +375,29 @@ def post(self, request, *args, **kwargs): response = list() interfaces = request.DATA + log.info('InterfaceV3View POST') + log.info('interfaces: %s', interfaces) + log.info('kwargs: %s', kwargs) json_validate(SPECS.get('interface_post')).validate(interfaces) + for interface in interfaces.get('interfaces'): + + # User interface input,ex.: + # eth1, eth1/1, 1, Gi1/5, FF:FF:FF:FF:FF:F, int1, mgmt0, ethernet1/12, .. + interface_input = interface['interface'] + log.debug('interface_input: %s', interface_input) + + # Equipments from input interface + equipment_id = interface['equipment'] + log.info('equipment_id: %s', equipment_id) + obj_model = facade.get_interface_by_search( + {'extends_search': [], 'start_record': 0, 'custom_search': equipment_id, 'end_record': 1000, 'asorting_cols': ['id'], 'searchable_columns': ['equipamento__id']} + ) + equipment_list = obj_model['query_set'] + log.info("equipment_list %s", equipment_list) + for equipment_interface in equipment_list: + log.info('equipment_interface: %s', equipment_interface.interface) + for i in interfaces.get('interfaces'): try: interface = facade.create_interface(i) From 556c5f77bd850ccb3aa171640b09f24154c95f67 Mon Sep 17 00:00:00 2001 From: Iuri Malinoski Date: Thu, 24 Oct 2024 13:55:28 -0300 Subject: [PATCH 2/3] code clean --- networkapi/api_interface/views.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/networkapi/api_interface/views.py b/networkapi/api_interface/views.py index e200fb64f..6779e5eb6 100644 --- a/networkapi/api_interface/views.py +++ b/networkapi/api_interface/views.py @@ -380,23 +380,24 @@ def post(self, request, *args, **kwargs): log.info('kwargs: %s', kwargs) json_validate(SPECS.get('interface_post')).validate(interfaces) + # Validate input user interface for interface in interfaces.get('interfaces'): - # User interface input,ex.: - # eth1, eth1/1, 1, Gi1/5, FF:FF:FF:FF:FF:F, int1, mgmt0, ethernet1/12, .. + # User interface input, ex.: + # ex.: eth1, eth1/1, 1, Gi1/5, FF:FF:FF:FF:FF:F, int1, mgmt0, ethernet1/12, .. interface_input = interface['interface'] log.debug('interface_input: %s', interface_input) # Equipments from input interface equipment_id = interface['equipment'] - log.info('equipment_id: %s', equipment_id) + log.debug('equipment_id: %s', equipment_id) obj_model = facade.get_interface_by_search( {'extends_search': [], 'start_record': 0, 'custom_search': equipment_id, 'end_record': 1000, 'asorting_cols': ['id'], 'searchable_columns': ['equipamento__id']} ) equipment_list = obj_model['query_set'] - log.info("equipment_list %s", equipment_list) + log.debug("equipment_list %s", equipment_list) for equipment_interface in equipment_list: - log.info('equipment_interface: %s', equipment_interface.interface) + log.debug('equipment_interface: %s', equipment_interface.interface) for i in interfaces.get('interfaces'): try: From 451b2f9cdd1d02efc74bf7087c88da668322b9e2 Mon Sep 17 00:00:00 2001 From: Iuri Malinoski Date: Wed, 30 Oct 2024 11:23:03 -0300 Subject: [PATCH 3/3] Adding overrides validator to POST interfaces. --- networkapi/api_interface/views.py | 15 +++-- networkapi/util/interface_validate.py | 87 +++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 networkapi/util/interface_validate.py diff --git a/networkapi/api_interface/views.py b/networkapi/api_interface/views.py index 6779e5eb6..c7b1408ad 100644 --- a/networkapi/api_interface/views.py +++ b/networkapi/api_interface/views.py @@ -41,6 +41,7 @@ from networkapi.util.decorators import prepare_search from networkapi.util.json_validate import json_validate from networkapi.util.json_validate import raise_json_validate +from networkapi.util.interface_validate import InterfaceOverrideValidator from networkapi.util.geral import create_lock from networkapi.util.geral import destroy_lock from networkapi.util.geral import render_to_json @@ -380,24 +381,30 @@ def post(self, request, *args, **kwargs): log.info('kwargs: %s', kwargs) json_validate(SPECS.get('interface_post')).validate(interfaces) - # Validate input user interface + user_interface_str_list = [] + equipmemnt_interface_str_list = [] for interface in interfaces.get('interfaces'): # User interface input, ex.: # ex.: eth1, eth1/1, 1, Gi1/5, FF:FF:FF:FF:FF:F, int1, mgmt0, ethernet1/12, .. interface_input = interface['interface'] - log.debug('interface_input: %s', interface_input) + user_interface_str_list.append(interface_input) # Equipments from input interface equipment_id = interface['equipment'] - log.debug('equipment_id: %s', equipment_id) obj_model = facade.get_interface_by_search( {'extends_search': [], 'start_record': 0, 'custom_search': equipment_id, 'end_record': 1000, 'asorting_cols': ['id'], 'searchable_columns': ['equipamento__id']} ) equipment_list = obj_model['query_set'] log.debug("equipment_list %s", equipment_list) for equipment_interface in equipment_list: - log.debug('equipment_interface: %s', equipment_interface.interface) + equipmemnt_interface_str_list.append(equipment_interface.interface) + + # Validate interface overrinding + InterfaceOverrideValidator().check_overriding( + source_interface_str_list=user_interface_str_list, + target_interface_str_list=equipmemnt_interface_str_list + ) for i in interfaces.get('interfaces'): try: diff --git a/networkapi/util/interface_validate.py b/networkapi/util/interface_validate.py new file mode 100644 index 000000000..d045681a3 --- /dev/null +++ b/networkapi/util/interface_validate.py @@ -0,0 +1,87 @@ +""" +Interface validator module +""" +import re +import logging +from networkapi.api_rest.exceptions import NetworkAPIException + +log = logging.getLogger(__name__) + + +class InterfaceOverrideValidator: + """ + Class responsible to interfaces (or ports) valitions. + """ + + def check_overriding(self, source_interface_str_list, target_interface_str_list): + """ + Public method to check if source interface overides target interfaces. + + Allowed interfaces sample: + source_interface_str_list = ['eth1/1', 'eth3/2'] + target_interface_str_list = ['eth2', 'eth3/1'] + + Prohibited interfaces sample: + source_interface_str_list = ['eth1/1', 'eth3/2'] + target_interface_str_list = ['eth1', 'eth1/1', 'eth3'] + + :param source_interface_str_list str list: String array of interfaces, ex.: ['eth1', 'eth2', 'eth2/1'] + :param target_interface_str_list str list: String array of interfaces, ex.: ['eth2/1/3', 'eth2/1/2/1'] + :return first prohibited interface as False, otherwise, allowed interface as True: + """ + + try: + + log.info('check_overriding START') + log.info('source_interface_str_list: %s', source_interface_str_list) + log.info('target_interface_str_list: %s', target_interface_str_list) + + # Validate + for source_interface_str in source_interface_str_list: + for target_interface_str in target_interface_str_list: + + log.info("Validating '%s' with '%s'", source_interface_str, source_interface_str) + source_interface_array = [int(num) for num in re.findall(r'\d+', source_interface_str)] + target_interface_array = [int(num) for num in re.findall(r'\d+', target_interface_str)] + response = self._is_overriding( + source_list=source_interface_array, + target_list=target_interface_array) + if not response: + raise NetworkAPIException("A interface requisitada '{}' sobrepoe a interface '{}' do equipamento".format( + source_interface_str, target_interface_str + ) + ) + + except Exception as ex: + raise NetworkAPIException(str(ex)) + + def _is_overriding(self, source_list, target_list, lvl=0): + """ + Private method check if source interface overides target interfaces. + The interfaces are represented by array, ex. [1,1] is 'eth1/1'. + + :param source interfaces: Represented array of interfaces, ex.: [1,1] [1,2,1] [2] + :param source interfaces: Represented array of interfaces, ex.: [1] [1,2,3] [4] + :param recursive level control. + :return first prohibited interface as False, otherwise, allowed interface as True: + """ + + try: + # Identical + if source_list == target_list: + log.info('*** PROHIBITED ***') + return False + elif not source_list or not target_list: + log.info('**** PROHIBITED ****') + return False + elif source_list and target_list and source_list[0] == target_list[0]: + return self._is_overriding( + source_list=source_list[1:], + target_list=target_list[1:], + lvl=lvl+1 + ) + else: + log.info('**** ALLOWED ****') + return True + except Exception as ex: + raise NetworkAPIException(str(ex))