From 9e7aed6242a4381046e489c1753712379bdba93b Mon Sep 17 00:00:00 2001 From: srividhya Date: Tue, 14 Jul 2020 23:34:10 -0700 Subject: [PATCH] Removed reduntant code from virtual-machine-interface for AE allocation closes-jira-bug: CEM-15158 1. AE-ID allocation log is now moved from virtual-machine-interface resource class to virtual-port-group resource class 2. PEP-8 fixes 3. New UTs to cover ae-id alloc/dealloc for backward compatability Change-Id: I16902fee2dd5d54b83da9f7a310c5b44bfb91be8 --- .../resources/virtual_machine_interface.py | 212 +----- .../resources/virtual_port_group.py | 85 ++- .../resources/test_virtual_port_group.py | 637 +++++++++++++----- 3 files changed, 535 insertions(+), 399 deletions(-) diff --git a/src/config/api-server/vnc_cfg_api_server/resources/virtual_machine_interface.py b/src/config/api-server/vnc_cfg_api_server/resources/virtual_machine_interface.py index 7f42e105a61..d14309832ea 100644 --- a/src/config/api-server/vnc_cfg_api_server/resources/virtual_machine_interface.py +++ b/src/config/api-server/vnc_cfg_api_server/resources/virtual_machine_interface.py @@ -17,7 +17,6 @@ from vnc_api.gen.resource_common import VirtualPortGroup from vnc_api.gen.resource_xsd import MacAddressesType from vnc_api.gen.resource_xsd import PolicyBasedForwardingRuleType -from vnc_api.gen.resource_xsd import VpgInterfaceParametersType from vnc_cfg_api_server.context import get_context from vnc_cfg_api_server.resources._resource_base import ResourceMixin @@ -830,78 +829,6 @@ def pre_dbe_update(cls, id, fq_name, obj_dict, db_conn, return True, ret_dict - @classmethod - def _notify_ae_id_modified(cls, obj_dict=None, notify=False): - - if (obj_dict.get('deallocated_ae_id') and - len(obj_dict.get('deallocated_ae_id'))): - dealloc_dict_list = obj_dict.get('deallocated_ae_id') - for dealloc_dict in dealloc_dict_list: - ae_id = dealloc_dict.get('ae_id') - vpg_name = dealloc_dict.get('vpg_name') - prouter_name = dealloc_dict.get('prouter_name') - cls.vnc_zk_client.free_ae_id( - prouter_name, ae_id, - vpg_name, notify=notify) - - if (obj_dict.get('allocated_ae_id') and - len(obj_dict.get('allocated_ae_id'))): - alloc_dict_list = obj_dict.get('allocated_ae_id') - for alloc_dict in alloc_dict_list: - ae_id = alloc_dict.get('ae_id') - vpg_name = alloc_dict.get('vpg_name') - prouter_name = alloc_dict.get('prouter_name') - cls.vnc_zk_client.alloc_ae_id(prouter_name, vpg_name, ae_id, - notify=True) - - # Allocate ae_id: - # 1. Get the ae_id from the old PI ref which is already assoc with PR - # 2. If not, then check if it got already generated on this api call - # from the other PI that belongs to the same PR. - # 3. Else allocate the new ae_id. Id allocation is per PR 0-127 and key - # is the vpg name. - @classmethod - def _check_and_alloc_ae_id(cls, links, prouter_name, - vpg_name, old_pi_to_pr_dict): - if not len(links) > 1: - return None, None - - for pr in old_pi_to_pr_dict.values(): - if (pr.get('prouter_name') == prouter_name and - pr.get('ae_id') is not None): - attr_obj = VpgInterfaceParametersType(pr.get('ae_id')) - return attr_obj, pr.get('ae_id') - - ae_num = cls.vnc_zk_client.alloc_ae_id(prouter_name, vpg_name) - attr_obj = VpgInterfaceParametersType(ae_num) - - return attr_obj, ae_num - - # Free ae_id: - # 1. If the PI ref is getting deleted and there in no other PI left - # that belongs to the same PR. - # 2. Or if there is only one physical link to VPG. - @classmethod - def _check_and_free_ae_id(cls, links, prouter_dict, - vpg_name, pi_to_pr_dict): - prouter_list = [] - dealloc_dict = {} - for pr in pi_to_pr_dict.values(): - prouter_list.append(pr) - - prouter_name = prouter_dict.get('prouter_name') - if prouter_name not in prouter_list or len(links) < 2: - cls.vnc_zk_client.free_ae_id(prouter_name, - prouter_dict.get('ae_id'), - vpg_name) - dealloc_dict['ae_id'] = prouter_dict.get('ae_id') - dealloc_dict['prouter_name'] = prouter_dict.get('prouter_name') - dealloc_dict['vpg_name'] = vpg_name - prouter_dict['ae_id'] = None - return dealloc_dict - - return - @classmethod def _check_annotations( cls, api_server, obj_uuid, @@ -1574,7 +1501,6 @@ def _manage_vpg_association(cls, vmi_id, api_server, db_conn, phy_links, phy_interface_uuids = [] old_phy_interface_uuids = [] new_pi_to_pr_dict = {} - old_pi_to_pr_dict = {} for link in phy_links: if link.get('fabric'): if fabric_name is not None and fabric_name != link['fabric']: @@ -1593,23 +1519,6 @@ def _manage_vpg_association(cls, vmi_id, api_server, db_conn, phy_links, phy_interface_uuids.append(pi_uuid) new_pi_to_pr_dict[pi_uuid] = prouter_name - # check if new physical interfaces belongs to some other vpg - for uuid in set(phy_interface_uuids): - ok, phy_interface_dict = db_conn.dbe_read( - obj_type='physical-interface', - obj_id=uuid, - obj_fields=['name', 'virtual_port_group_back_refs']) - if not ok: - return (ok, 400, phy_interface_dict) - - vpg_refs = phy_interface_dict.get('virtual_port_group_back_refs') - if vpg_refs and vpg_refs[0]['to'][-1] != vpg_name: - msg = 'Physical interface %s already belong to the vpg %s' %\ - (phy_interface_dict.get( - 'name', phy_interface_dict['fq_name']), - vpg_refs[0]['to'][-1]) - return (False, (400, msg)) - if vpg_name: # read the vpg object vpg_fq_name = ['default-global-system-config', fabric_name, vpg_name] @@ -1717,59 +1626,38 @@ def vlanid_sanitizer(vlanid): return ok, result old_phy_interface_refs = vpg_dict.get('physical_interface_refs') - for ref in old_phy_interface_refs or []: - old_pi_to_pr_dict[ref['uuid']] = { - 'prouter_name': ref['to'][1], - 'ae_id': ref['attr'].get('ae_num') if ref['attr'] else None} - old_phy_interface_uuids.append(ref['uuid']) - + old_phy_interface_uuids = [ref['uuid'] for ref in + old_phy_interface_refs or []] ret_dict = {} - ret_dict['deallocated_ae_id'] = [] - ret_dict['allocated_ae_id'] = [] # delete old physical interfaces to the vpg - for uuid in set(old_phy_interface_uuids) - set(phy_interface_uuids): - prouter_dict = old_pi_to_pr_dict.get(uuid) - dealloc_dict = cls._check_and_free_ae_id( - phy_links, prouter_dict, - vpg_name, new_pi_to_pr_dict) - ret_dict['deallocated_ae_id'].append(dealloc_dict) - - api_server.internal_request_ref_update( - 'virtual-port-group', - vpg_uuid, - 'DELETE', - 'physical-interface', - uuid) + delete_pi_uuids = (set(old_phy_interface_uuids) - + set(phy_interface_uuids)) + for uuid in delete_pi_uuids: + try: + api_server.internal_request_ref_update( + 'virtual-port-group', + vpg_uuid, + 'DELETE', + 'physical-interface', + uuid) + except Exception as exc: + return False, (exc.status_code, exc.content) # add new physical interfaces to the vpg - pr_to_ae_id = {} - for uuid in phy_interface_uuids: - prouter_name = new_pi_to_pr_dict.get(uuid) - if pr_to_ae_id.get(prouter_name) is None: - attr_obj, ae_id = cls._check_and_alloc_ae_id( - phy_links, prouter_name, - vpg_name, old_pi_to_pr_dict) - pr_to_ae_id[prouter_name] = ae_id - - if len(phy_links) > 1 and ae_id is not None: - alloc_dict = {} - alloc_dict['ae_id'] = ae_id - alloc_dict['prouter_name'] = prouter_name - alloc_dict['vpg_name'] = vpg_name - ret_dict['allocated_ae_id'].append(alloc_dict) - else: - attr_obj = VpgInterfaceParametersType( - ae_num=pr_to_ae_id.get(prouter_name)) - - api_server.internal_request_ref_update( - 'virtual-port-group', - vpg_uuid, - 'ADD', - 'physical-interface', - uuid, - attr=attr_obj.__dict__ if attr_obj else None, - relax_ref_for_delete=True) + create_pi_uuids = (set(phy_interface_uuids) - + set(old_phy_interface_uuids)) + for uuid in create_pi_uuids: + try: + api_server.internal_request_ref_update( + 'virtual-port-group', + vpg_uuid, + 'ADD', + 'physical-interface', + uuid, + relax_ref_for_delete=True) + except Exception as exc: + return False, (exc.status_code, exc.content) # update intent-map with vn_id # read intent map object @@ -1839,29 +1727,6 @@ def pre_dbe_delete(cls, id, obj_dict, db_conn): delete_dict = {'virtual_machine_refs': []} cls._check_vrouter_link(obj_dict, kvp_dict, delete_dict, db_conn) - # Clean ae ids associated with VPG->PIs - for vpg_back_ref in obj_dict.get('virtual_port_group_back_refs', - []): - fqname = vpg_back_ref['to'] - vpg_uuid = db_conn.fq_name_to_uuid('virtual_port_group', fqname) - ok, vpg_dict = db_conn.dbe_read( - obj_type='virtual-port-group', - obj_id=vpg_uuid, - obj_fields=['physical_interface_refs']) - if not ok: - return ok, vpg_dict - - notify_dict = {} - notify_dict['deallocated_ae_id'] = [] - for pi_ref in vpg_dict.get('physical_interface_refs') or []: - if pi_ref['attr'] and pi_ref['attr'].get('ae_num') is not None: - dealloc_dict = {} - dealloc_dict['ae_id'] = pi_ref['attr'].get('ae_num') - dealloc_dict['prouter_name'] = pi_ref['to'][1] - dealloc_dict['vpg_name'] = fqname[2] - notify_dict['deallocated_ae_id'].append(dealloc_dict) - obj_dict.update(notify_dict) - return True, "", None @classmethod @@ -1948,27 +1813,4 @@ def post_dbe_delete(cls, id, obj_dict, db_conn): api_server.internal_request_delete('virtual_port_group', vpg_uuid) - # Clean ae ids associated with VPG->PIs - cls._notify_ae_id_modified(obj_dict) - return True, "" - - @classmethod - def dbe_create_notification(cls, db_conn, obj_id, obj_dict): - cls._notify_ae_id_modified(obj_dict) - - return True, '' - - @classmethod - def dbe_update_notification(cls, obj_id, extra_dict=None): - - if extra_dict is not None: - cls._notify_ae_id_modified(extra_dict, notify=True) - - return True, '' - - @classmethod - def dbe_delete_notification(cls, obj_id, obj_dict): - cls._notify_ae_id_modified(obj_dict, notify=True) - - return True, '' diff --git a/src/config/api-server/vnc_cfg_api_server/resources/virtual_port_group.py b/src/config/api-server/vnc_cfg_api_server/resources/virtual_port_group.py index a9eaf9b0307..5829de6e692 100644 --- a/src/config/api-server/vnc_cfg_api_server/resources/virtual_port_group.py +++ b/src/config/api-server/vnc_cfg_api_server/resources/virtual_port_group.py @@ -28,6 +28,9 @@ def _notify_ae_id_modified(cls, obj_dict=None, notify=False): cls.vnc_zk_client.free_ae_id( prouter_name, ae_id, vpg_name, notify=notify) + msg = "NOTIFY: Deallocated AE-ID (%s) at VPG(%s)/PR(%s)" % ( + ae_id, vpg_name, prouter_name) + cls.db_conn.config_log(msg, level=SandeshLevel.SYS_DEBUG) if (obj_dict.get('allocated_ae_id') and len(obj_dict.get('allocated_ae_id'))): alloc_dict_list = obj_dict.get('allocated_ae_id') @@ -37,15 +40,18 @@ def _notify_ae_id_modified(cls, obj_dict=None, notify=False): prouter_name = alloc_dict.get('prouter_name') cls.vnc_zk_client.alloc_ae_id(prouter_name, vpg_name, ae_id, notify=True) + msg = "NOTIFY: Allocated AE-ID (%s) at VPG(%s)/PR(%s)" % ( + ae_id, vpg_name, prouter_name) + cls.db_conn.config_log(msg, level=SandeshLevel.SYS_DEBUG) @classmethod def _alloc_ae_id(cls, prouter_name, vpg_name): try: pi_ae = cls.vnc_zk_client.alloc_ae_id(prouter_name, vpg_name) - except ResourceExhaustionError as exc: + except ResourceExhaustionError: err_msg = ('ResourceExhaustionError: when allocating AE-ID for ' 'virtual-port-group (%s) at physical-router (%s)' % ( - vpg_name, prouter_name)) + vpg_name, prouter_name)) return False, (400, err_msg) attr_obj = VpgInterfaceParametersType(pi_ae) attr_dict = attr_obj.__dict__ @@ -54,11 +60,17 @@ def _alloc_ae_id(cls, prouter_name, vpg_name): 'prouter_name': prouter_name, 'vpg_name': vpg_name, } + msg = "Allocated AE-ID (%s) at VPG(%s)/PR(%s)" % ( + pi_ae, vpg_name, prouter_name) + cls.db_conn.config_log(msg, level=SandeshLevel.SYS_DEBUG) return True, (attr_dict, alloc_dict) @classmethod def _dealloc_ae_id(cls, prouter_name, ae_id, vpg_name): cls.vnc_zk_client.free_ae_id(prouter_name, ae_id, vpg_name) + msg = "De-allocated AE-ID (%s) at VPG(%s)/PR(%s)" % ( + ae_id, vpg_name, prouter_name) + cls.db_conn.config_log(msg, level=SandeshLevel.SYS_DEBUG) dealloc_dict = { 'ae_id': ae_id, 'prouter_name': prouter_name, @@ -70,13 +82,10 @@ def _dealloc_ae_id(cls, prouter_name, ae_id, vpg_name): def _process_alloc_ae_id(cls, db_obj_dict, vpg_name, obj_dict=None): attr_dict = None alloc_dealloc_dict = {'allocated_ae_id': [], 'deallocated_ae_id': []} - alloc_list = [] - dealloc_list = [] curr_pr_dict = {} curr_pi_dict = {} db_pi_dict = {} db_pr_dict = {} - extra_deallocate_dict = {} vpg_uuid = db_obj_dict['uuid'] if not obj_dict: obj_dict = {} @@ -92,20 +101,30 @@ def _process_alloc_ae_id(cls, db_obj_dict, vpg_name, obj_dict=None): if not (ref['to'][1] in db_pr_dict and db_pr_dict[ref['to'][1]]): db_pr_dict[ref['to'][1]] = ref['attr'] - create_pi_uuids = list(set(curr_pi_dict.keys()) - set(db_pi_dict.keys())) - delete_pi_uuids = list(set(db_pi_dict.keys()) - set(curr_pi_dict.keys())) + create_pi_uuids = list(set(curr_pi_dict.keys()) - + set(db_pi_dict.keys())) + delete_pi_uuids = list(set(db_pi_dict.keys()) - + set(curr_pi_dict.keys())) # no PIs in db_obj_dict if len(create_pi_uuids) < 2 and len(db_pi_dict.keys()) == 0: + msg = "Skip AE-ID allocation as Creating PI len(%s) < 2" % ( + create_pi_uuids) + cls.db_conn.config_log(msg, level=SandeshLevel.SYS_DEBUG) return True, (attr_dict, alloc_dealloc_dict) # nothing to delete or add if len(create_pi_uuids) == len(delete_pi_uuids) == 0: + msg = "Skip AE-ID allocation as no PI to Create / Delete" + cls.db_conn.config_log(msg, level=SandeshLevel.SYS_DEBUG) return True, (attr_dict, alloc_dealloc_dict) # nothing to delete, because rest of PIs shares same PR if (len(create_pi_uuids) == 0 and len(delete_pi_uuids) == 1 and len(db_pr_dict.keys()) == 1 and len(db_pi_dict.keys()) > 2): + msg = "Skip AE-ID allocation as rest PI(%s) shares same PR(%s)" % ( + db_pi_dict.keys(), db_pr_dict.keys()) + cls.db_conn.config_log(msg, level=SandeshLevel.SYS_DEBUG) return True, (attr_dict, alloc_dealloc_dict) # allocate case @@ -120,31 +139,34 @@ def _process_alloc_ae_id(cls, db_obj_dict, vpg_name, obj_dict=None): return ok, result attr_dict, _alloc_dict = result alloc_dealloc_dict['allocated_ae_id'].append(_alloc_dict) - msg = "Allocating AE-ID(%s) for PI(%s) at VPG(%s)/PR(%s)" % ( + msg = "Allocated AE-ID(%s) for PI(%s) at VPG(%s)/PR(%s)" % ( attr_dict, pi_uuid, vpg_name, pi_pr) - cls.db_conn.config_log(msg, level=SandeshLevel.SYS_INFO) + cls.db_conn.config_log(msg, level=SandeshLevel.SYS_DEBUG) else: attr_dict = pi_ae # re-allocate existing single PI if any if (len(db_pi_dict.keys()) == 1 and len(create_pi_uuids) == 1): - db_pi_uuid = db_pi_dict.keys()[0] - if (db_pi_dict.values()[0] != curr_pi_dict.get(create_pi_uuids[0])): + db_pi_uuid = list(db_pi_dict.keys())[0] + if (list(db_pi_dict.values())[0] != + curr_pi_dict.get(create_pi_uuids[0])): # allocate a new ae-id as it belongs to different PR - db_pr = db_pi_dict.values()[0] + db_pr = list(db_pi_dict.values())[0] ok, result = cls._alloc_ae_id(db_pr, vpg_name) if not ok: return ok, result attr_dict_leftover_pi, _alloc_dict = result alloc_dealloc_dict['allocated_ae_id'].append(_alloc_dict) - msg = "Allocating AE-ID(%s) for PI(%s) at VPG(%s)/PR(%s)" % ( - attr_dict_leftover_pi, db_pi_uuid, vpg_name, db_pr) - cls.db_conn.config_log(msg, level=SandeshLevel.SYS_INFO) + msg = ("Allocated AE-ID(%s) for PI(%s) at " + "VPG(%s)/PR(%s)" % ( + attr_dict_leftover_pi, db_pi_uuid, + vpg_name, db_pr)) + cls.db_conn.config_log(msg, level=SandeshLevel.SYS_DEBUG) else: attr_dict_leftover_pi = attr_dict msg = "Re-using AE-ID(%s) for PI(%s) at VPG(%s)/PR(%s)" % ( attr_dict_leftover_pi, db_pi_uuid, vpg_name, pi_pr) - cls.db_conn.config_log(msg, level=SandeshLevel.SYS_INFO) + cls.db_conn.config_log(msg, level=SandeshLevel.SYS_DEBUG) (ok, result) = cls.db_conn.ref_update( 'virtual_port_group', vpg_uuid, @@ -157,14 +179,14 @@ def _process_alloc_ae_id(cls, db_obj_dict, vpg_name, obj_dict=None): relax_ref_for_delete=True) msg = "Updated AE-ID(%s) in PI(%s) ref to VPG(%s)" % ( attr_dict_leftover_pi, db_pi_uuid, vpg_name) - cls.db_conn.config_log(msg, level=SandeshLevel.SYS_INFO) + cls.db_conn.config_log(msg, level=SandeshLevel.SYS_DEBUG) # deallocate case _in_dealloc_list = [] for pi_uuid in delete_pi_uuids: pi_pr = db_pi_dict.get(pi_uuid) pi_ae = db_pr_dict.get(pi_pr) - db_pi_prs = db_pi_dict.values().count(pi_pr) + db_pi_prs = list(db_pi_dict.values()).count(pi_pr) # PR/VPG is already considered for deallocation, so no need # to dealloc again if '%s:%s' % (pi_pr, vpg_name) in _in_dealloc_list: @@ -179,15 +201,15 @@ def _process_alloc_ae_id(cls, db_obj_dict, vpg_name, obj_dict=None): _in_dealloc_list.append('%s:%s' % (pi_pr, vpg_name)) msg = "Deallocated AE-ID(%s) for PI(%s) at VPG(%s)/PR(%s)" % ( ae_id, pi_uuid, vpg_name, pi_pr) - cls.db_conn.config_log(msg, level=SandeshLevel.SYS_INFO) + cls.db_conn.config_log(msg, level=SandeshLevel.SYS_DEBUG) # de-allocate leftover single PI, if any # in delete case, whatever comes in curr_pi_dict are the # leftovers because for delete refs, ref to be deleted # will not be coming in payload if (len(curr_pi_dict.keys()) == 1 and - len(db_pi_dict.keys()) == len(delete_pi_uuids) + 1): - pi_uuid = curr_pi_dict.keys()[0] + len(db_pi_dict.keys()) == len(delete_pi_uuids) + 1): + pi_uuid = list(curr_pi_dict.keys())[0] pi_pr = curr_pi_dict.get(pi_uuid) pi_ae = curr_pr_dict.get(pi_pr) if '%s:%s' % (pi_pr, vpg_name) not in _in_dealloc_list: @@ -199,9 +221,9 @@ def _process_alloc_ae_id(cls, db_obj_dict, vpg_name, obj_dict=None): # record deallocated pr/vpg _in_dealloc_list.append('%s:%s' % (pi_pr, vpg_name)) msg = ("Deallocated AE-ID(%s) from leftover PI(%s) at " - "VPG(%s)/PR(%s)" % ( - ae_id, pi_uuid, vpg_name, pi_pr)) - cls.db_conn.config_log(msg, level=SandeshLevel.SYS_INFO) + "VPG(%s)/PR(%s)" % ( + ae_id, pi_uuid, vpg_name, pi_pr)) + cls.db_conn.config_log(msg, level=SandeshLevel.SYS_DEBUG) pi_ae = db_pr_dict.get(pi_pr) (ok, result) = cls.db_conn.ref_update( 'virtual_port_group', @@ -211,7 +233,6 @@ def _process_alloc_ae_id(cls, db_obj_dict, vpg_name, obj_dict=None): {'attr': None}, 'ADD', db_obj_dict.get('id_perms'), - attr_to_publish=None, relax_ref_for_delete=True) return True, (attr_dict, alloc_dealloc_dict) @@ -275,9 +296,9 @@ def update_physical_intf_type(cls, obj_dict=None, msg = "" for pi, vpgs in pis_attached_to_vpg.items(): for vpg in vpgs: - msg += ( - 'PI (%s) VPG-UUID (%s) VPG-FQNAME (%s); ' % ( - pi, vpg['uuid'], ":".join(vpg['to']))) + msg += ( + 'PI (%s) VPG-UUID (%s) VPG-FQNAME (%s); ' % ( + pi, vpg['uuid'], ":".join(vpg['to']))) return ( False, (400, "physical interfaces already added at other VPGs can not" @@ -372,11 +393,13 @@ def pre_dbe_update(cls, id, fq_name, obj_dict, db_conn, **kwargs): ok, res = cls.update_physical_intf_type(obj_dict, db_obj_dict) if not ok: return ok, res - ok, res = cls._process_alloc_ae_id(db_obj_dict, fq_name[-1], obj_dict) + # Allocate/Deallocate AE-IDs for the attached PIs + ok, res = cls._process_alloc_ae_id( + db_obj_dict, fq_name[-1], obj_dict) if not ok: return ok, res - if res[0] and kwargs.get('ref_args'): - kwargs['ref_args']['data']['attr'] = res[0] + if res[0] and kwargs.get('ref_update'): + kwargs['ref_update']['data']['attr'] = res[0] ret_val = res[1] return True, ret_val diff --git a/src/config/api-server/vnc_cfg_api_server/tests/resources/test_virtual_port_group.py b/src/config/api-server/vnc_cfg_api_server/tests/resources/test_virtual_port_group.py index fcb6fe7ba7c..e221719a3bb 100644 --- a/src/config/api-server/vnc_cfg_api_server/tests/resources/test_virtual_port_group.py +++ b/src/config/api-server/vnc_cfg_api_server/tests/resources/test_virtual_port_group.py @@ -5,6 +5,7 @@ from builtins import int from builtins import range from builtins import str +from collections import defaultdict import json import logging import os @@ -258,7 +259,7 @@ def _create_pi_objects(self, pr_objs, pi_names): for pi_name in pi_names: esi_id = self._get_nth_esi(esi_start_id, esi_count) pi = PhysicalInterface(name=pi_name, - parent_obj=pr_objs[esi_count-1], + parent_obj=pr_objs[esi_count - 1], ethernet_segment_identifier=esi_id) pi_uuid = self._vnc_lib.physical_interface_create(pi) pi_obj_dict[pi_name] = self._vnc_lib.physical_interface_read( @@ -287,7 +288,6 @@ def _create_vmis(self, vmi_infos): vmi_obj_dict = {} for vmi_info in vmi_infos: vmi_name = vmi_info.get('name') - vmi_id = vmi_info.get('vmi_id') vmi_parent = vmi_info.get('parent_obj') vmi_vn = vmi_info.get('vn') vmi_vpg_uuid = vmi_info.get('vpg') @@ -391,7 +391,10 @@ def test_add_and_delete_pis_at_vpg(self): proj_obj, fabric_obj, pr_objs = self._create_prerequisites( create_second_pr=True) test_id = self.id() - process_ae_ids = lambda x: [int(i) for i in sorted(x)] + + def process_ae_ids(x): + return [int(i) for i in sorted(x)] + def get_zk_ae_ids(prs=None): prefix = os.path.join( self.__class__.__name__, @@ -422,11 +425,12 @@ def get_zk_ae_ids(prs=None): # create ten VPGs vpg_count = 10 - vpg_names = ['vpg_%s_%s' % (test_id, i) for i in range(1, vpg_count+1)] + vpg_names = ['vpg_%s_%s' % (test_id, i) for i in range( + 1, vpg_count + 1)] vpg_objs = self._create_vpgs(fabric_obj, vpg_names) # record AE-IDs in ZK before creating any VPG - ae_ids = reduce(sum, get_zk_ae_ids().values()) + ae_ids = [x for x in get_zk_ae_ids().values() if x] self.assertEqual(len(ae_ids), 0) # Case 1 @@ -440,7 +444,7 @@ def get_zk_ae_ids(prs=None): vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) pi_refs = vpg_obj.get_physical_interface_refs() ae_ids[vpg_name] = {ref['href'].split('/')[-1]: ref['attr'].ae_num - for ref in pi_refs} + for ref in pi_refs} # verify PI-refs are correct self.assertEqual(len(pi_refs), 3) # verify all AE-IDs allocated per prouter are unique @@ -461,7 +465,7 @@ def get_zk_ae_ids(prs=None): vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) pi_refs = vpg_obj.get_physical_interface_refs() ae_ids[vpg_name] = {ref['href'].split('/')[-1]: ref['attr'].ae_num - for ref in pi_refs} + for ref in pi_refs} # verify PI-refs are correct self.assertEqual(len(pi_refs), 5) # verify all AE-IDs allocated per prouter are unique @@ -481,7 +485,7 @@ def get_zk_ae_ids(prs=None): vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) pi_refs = vpg_obj.get_physical_interface_refs() ae_ids[vpg_name] = {ref['href'].split('/')[-1]: ref['attr'].ae_num - for ref in pi_refs} + for ref in pi_refs} # verify PI-refs are correct self.assertEqual(len(pi_refs), 4) # verify all AE-IDs allocated per prouter are unique @@ -500,7 +504,7 @@ def get_zk_ae_ids(prs=None): for pi in range(5, 8): vpg.add_physical_interface(pi_objs[pr1_pi_names[pi]]) with ExpectedException(BadRequest): - vpg_uuid = self.api.virtual_port_group_create(vpg) + self.api.virtual_port_group_create(vpg) # verification at Physical Routers # No changes expected as VPG-99 should have failed @@ -520,7 +524,7 @@ def get_zk_ae_ids(prs=None): vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) pi_refs = vpg_obj.get_physical_interface_refs() ae_ids[vpg_name] = {ref['href'].split('/')[-1]: ref['attr'].ae_num - for ref in pi_refs} + for ref in pi_refs} # verify PI-refs are correct self.assertEqual(len(pi_refs), 4) # verify all AE-IDs allocated per prouter are unique @@ -547,7 +551,7 @@ def get_zk_ae_ids(prs=None): vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) pi_refs = vpg_obj.get_physical_interface_refs() ae_ids[vpg_name] = {ref['href'].split('/')[-1]: ref['attr'].ae_num - for ref in pi_refs} + for ref in pi_refs} # verify PI-refs are correct self.assertEqual(len(pi_refs), 3) # verify all AE-IDs allocated per prouter are unique @@ -574,7 +578,7 @@ def get_zk_ae_ids(prs=None): vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) pi_refs = vpg_obj.get_physical_interface_refs() ae_ids[vpg_name] = {ref['href'].split('/')[-1]: ref['attr'].ae_num - for ref in pi_refs} + for ref in pi_refs} # verify PI-refs are correct self.assertEqual(len(pi_refs), 2) # verify all AE-IDs allocated per prouter are unique @@ -602,7 +606,7 @@ def get_zk_ae_ids(prs=None): vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) pi_refs = vpg_obj.get_physical_interface_refs() ae_ids[vpg_name] = {ref['href'].split('/')[-1]: ref['attr'].ae_num - for ref in pi_refs} + for ref in pi_refs} # verify PI-refs are correct self.assertEqual(len(pi_refs), 2) # verify all AE-IDs allocated per prouter are unique @@ -623,13 +627,13 @@ def get_zk_ae_ids(prs=None): vpg_index = 3 vpg_name = vpg_names[vpg_index] vpg_obj = vpg_objs[vpg_names[vpg_index]] - for pi in range(4,6): + for pi in range(4, 6): vpg_obj.add_physical_interface(pr2_pi_objs[pr2_pi_names[pi]]) self.api.virtual_port_group_update(vpg_obj) vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) pi_refs = vpg_obj.get_physical_interface_refs() ae_ids[vpg_name] = {ref['href'].split('/')[-1]: ref['attr'].ae_num - for ref in pi_refs} + for ref in pi_refs} # verify PI-refs are correct self.assertEqual(len(pi_refs), 2) # verify all AE-IDs allocated per prouter are unique @@ -646,7 +650,7 @@ def get_zk_ae_ids(prs=None): self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[1].name]), [0, 1, 2]) # Case 10 - # Delete VPG-1 (ensure 0 is deallocated from PR-1 and PR-2 remains same) + # Delete VPG-1 (0 is deallocated from PR-1 and PR-2 remains same) vpg_index = 0 vpg_name = vpg_names[vpg_index] vpg_obj = vpg_objs[vpg_names[vpg_index]] @@ -672,13 +676,13 @@ def get_zk_ae_ids(prs=None): vpg_index = 4 vpg_name = vpg_names[vpg_index] vpg_obj = vpg_objs[vpg_names[vpg_index]] - for pi in range(6,8): + for pi in range(6, 8): vpg_obj.add_physical_interface(pr2_pi_objs[pr2_pi_names[pi]]) self.api.virtual_port_group_update(vpg_obj) vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) pi_refs = vpg_obj.get_physical_interface_refs() ae_ids[vpg_name] = {ref['href'].split('/')[-1]: ref['attr'].ae_num - for ref in pi_refs} + for ref in pi_refs} # verify PI-refs are correct self.assertEqual(len(pi_refs), 2) # verify all AE-IDs allocated per prouter are unique @@ -692,7 +696,8 @@ def get_zk_ae_ids(prs=None): self.assertEqual(len(pr_ae_ids[pr_objs[0].name]), 1) self.assertEqual(len(pr_ae_ids[pr_objs[1].name]), 4) self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[0].name]), [1]) - self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[1].name]), [0, 1, 2, 3]) + self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[1].name]), + [0, 1, 2, 3]) # Case 12 # Create VPG-6 with PI13/PR1 and PI9/PR2 and verify PR1 gets PR1/0,1 @@ -707,7 +712,7 @@ def get_zk_ae_ids(prs=None): vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) pi_refs = vpg_obj.get_physical_interface_refs() ae_ids[vpg_name] = {ref['href'].split('/')[-1]: ref['attr'].ae_num - for ref in pi_refs} + for ref in pi_refs} # verify PI-refs are correct self.assertEqual(len(pi_refs), 2) # verify all AE-IDs allocated per prouter are unique @@ -721,10 +726,12 @@ def get_zk_ae_ids(prs=None): self.assertEqual(len(pr_ae_ids[pr_objs[0].name]), 2) self.assertEqual(len(pr_ae_ids[pr_objs[1].name]), 5) self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[0].name]), [0, 1]) - self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[1].name]), [0, 1, 2, 3, 4]) + self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[1].name]), + [0, 1, 2, 3, 4]) # Case 13 - # Delete PI13/PR1 from VPG-6 verify both PI13/PR1 and PI9/PR2 loses ae-id + # Delete PI13/PR1 from VPG-6 verify both PI13/PR1 and + # PI9/PR2 loses ae-id vpg_index = 5 vpg_name = vpg_names[vpg_index] vpg_obj = vpg_objs[vpg_names[vpg_index]] @@ -735,7 +742,7 @@ def get_zk_ae_ids(prs=None): vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) pi_refs = vpg_obj.get_physical_interface_refs() ae_ids[vpg_name] = {ref['href'].split('/')[-1]: ref['attr'].ae_num - for ref in pi_refs} + for ref in pi_refs} # verify PI-refs are correct self.assertEqual(len(pi_refs), 1) # verify all AE-IDs allocated per prouter are unique @@ -748,20 +755,20 @@ def get_zk_ae_ids(prs=None): self.assertEqual(len(pr_ae_ids[pr_objs[0].name]), 1) self.assertEqual(len(pr_ae_ids[pr_objs[1].name]), 4) self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[0].name]), [1]) - self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[1].name]), [0, 1, 2, 3]) + self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[1].name]), + [0, 1, 2, 3]) # TO-Do cleanup def test_leftover_single_pi_deallocation(self): - ''' - This test case checks if a leftover single PI from - same PR is properly deallocated and the object is set - with None ae-id - ''' + """Leftover single PI from same PR is deallocated.""" proj_obj, fabric_obj, pr_objs = self._create_prerequisites( create_second_pr=True) test_id = self.id() - process_ae_ids = lambda x: [int(i) for i in sorted(x)] + + def process_ae_ids(x): + return [int(i) for i in sorted(x)] + def get_zk_ae_ids(prs=None): prefix = os.path.join( self.__class__.__name__, @@ -788,11 +795,12 @@ def get_zk_ae_ids(prs=None): # create one VPG vpg_count = 1 - vpg_names = ['vpg_%s_%s' % (test_id, i) for i in range(1, vpg_count+1)] + vpg_names = ['vpg_%s_%s' % (test_id, i) for + i in range(1, vpg_count + 1)] vpg_objs = self._create_vpgs(fabric_obj, vpg_names) # record AE-IDs in ZK before creating any VPG - ae_ids = reduce(sum, get_zk_ae_ids().values()) + ae_ids = [x for x in get_zk_ae_ids().values() if x] self.assertEqual(len(ae_ids), 0) # Attach PI1/PR1 and PI2/PR1 to VPG-1 @@ -804,8 +812,9 @@ def get_zk_ae_ids(prs=None): self.api.virtual_port_group_update(vpg_obj) vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) + pi_refs = vpg_obj.get_physical_interface_refs() ae_ids[vpg_name] = {ref['href'].split('/')[-1]: ref['attr'].ae_num - for ref in pi_refs} + for ref in pi_refs} # verify PI-refs are correct self.assertEqual(len(pi_refs), 2) # verify all AE-IDs allocated per prouter are unique @@ -818,8 +827,6 @@ def get_zk_ae_ids(prs=None): self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[0].name]), [0]) # Delete PI1/PR1 - #vpg_name = vpg_names[0] - #vpg_obj = vpg_objs[vpg_name] vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) vpg_obj.del_physical_interface(pr1_pi_objs[pr1_pi_names[0]]) self.api.virtual_port_group_update(vpg_obj) @@ -840,7 +847,10 @@ def test_delete_vpg_with_two_prs(self): proj_obj, fabric_obj, pr_objs = self._create_prerequisites( create_second_pr=True) test_id = self.id() - process_ae_ids = lambda x: [int(i) for i in sorted(x)] + + def process_ae_ids(x): + return [int(i) for i in sorted(x)] + def get_zk_ae_ids(prs=None): prefix = os.path.join( self.__class__.__name__, @@ -871,12 +881,13 @@ def get_zk_ae_ids(prs=None): # create two VPGs vpg_count = 2 - vpg_names = ['vpg_%s_%s' % (test_id, i) for i in range(1, vpg_count+1)] + vpg_names = ['vpg_%s_%s' % (test_id, i) for + i in range(1, vpg_count + 1)] vpg_objs = self._create_vpgs(fabric_obj, vpg_names) # record AE-IDs in ZK before creating any VPG - ae_id = reduce(sum, get_zk_ae_ids().values()) - self.assertEqual(len(ae_id), 0) + ae_ids = [x for x in get_zk_ae_ids().values() if x] + self.assertEqual(len(ae_ids), 0) # Attach PI1/PR1, PI1/PR2, PI2/PR1, PI2/PR2 to VPG-1 ae_ids = {} @@ -891,7 +902,7 @@ def get_zk_ae_ids(prs=None): vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) pi_refs = vpg_obj.get_physical_interface_refs() ae_ids[vpg_name] = {ref['href'].split('/')[-1]: ref['attr'].ae_num - for ref in pi_refs} + for ref in pi_refs} # verify PI-refs are correct self.assertEqual(len(pi_refs), 4) # verify all AE-IDs allocated per prouter are unique @@ -934,7 +945,7 @@ def get_zk_ae_ids(prs=None): vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) pi_refs = vpg_obj.get_physical_interface_refs() ae_ids[vpg_name] = {ref['href'].split('/')[-1]: ref['attr'].ae_num - for ref in pi_refs} + for ref in pi_refs} # verify PI-refs are correct self.assertEqual(len(pi_refs), 4) # verify all AE-IDs allocated per prouter are unique @@ -954,7 +965,10 @@ def test_adding_pi_refs_while_vpg_creation(self): proj_obj, fabric_obj, pr_objs = self._create_prerequisites( create_second_pr=True) test_id = self.id() - process_ae_ids = lambda x: [int(i) for i in sorted(x)] + + def process_ae_ids(x): + return [int(i) for i in sorted(x)] + def get_zk_ae_ids(prs=None): prefix = os.path.join( self.__class__.__name__, @@ -996,14 +1010,14 @@ def get_zk_ae_ids(prs=None): self.api.virtual_port_group_create(vpg) def test_exhaust_ae_ids(self): - ''' - This test ensures that an exhaust error is thrown when - more than 128 VPGs are created. - ''' + """ + Raise Exhaustion Exception when more than MAX-AE-ID VPGs are attached. + + MAX-AE-ID == 128 + """ proj_obj, fabric_obj, pr_objs = self._create_prerequisites( create_second_pr=True) test_id = self.id().split('.')[-1] - fabric_name = fabric_obj.get_fq_name() def process_ae_ids(x): return [int(i) for i in sorted(x)] @@ -1044,8 +1058,8 @@ def get_zk_ae_ids(prs=None): vpg_objs = self._create_vpgs(fabric_obj, vpg_names) # record AE-IDs in ZK before creating any VPG - ae_ids = get_zk_ae_ids().values() - self.assertEqual(len(filter(None, ae_ids)), 0) + ae_ids = [x for x in get_zk_ae_ids().values() if x] + self.assertEqual(len(ae_ids), 0) def update_vpg(vpg_obj, pis, vpg_count): vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) @@ -1056,13 +1070,15 @@ def update_vpg(vpg_obj, pis, vpg_count): pi_refs = vpg_obj.get_physical_interface_refs() self.assertEqual(len(pi_refs), 2) vpg_ae_ids = {ref['href'].split('/')[-1]: ref['attr'].ae_num - for ref in pi_refs} + for ref in pi_refs} self.assertEqual(len(set(vpg_ae_ids.values())), 1) pr_ae_ids = get_zk_ae_ids() self.assertEqual(len(pr_ae_ids[pr_objs[0].name]), vpg_count) self.assertEqual(len(pr_ae_ids[pr_objs[1].name]), vpg_count) - self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[0].name]), [x for x in range(vpg_count)]) - self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[1].name]), [x for x in range(vpg_count)]) + self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[0].name]), + [x for x in range(vpg_count)]) + self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[1].name]), + [x for x in range(vpg_count)]) # Case 1: Update 128 VPGs with One PI from both PRs # This is expected to PASS @@ -1077,23 +1093,25 @@ def update_vpg(vpg_obj, pis, vpg_count): vpg_name = vpg_names[index] vpg_obj = vpg_objs[vpg_name] vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) - vpg_pis = [pr1_pi_objs[pr1_pi_names[index]], pr2_pi_objs[pr2_pi_names[index]]] + vpg_pis = [pr1_pi_objs[pr1_pi_names[index]], + pr2_pi_objs[pr2_pi_names[index]]] update_vpg(vpg_obj, vpg_pis, index) index = 130 vpg_name = vpg_names[index] vpg_obj = vpg_objs[vpg_name] vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) - vpg_pis = [pr1_pi_objs[pr1_pi_names[index]], pr2_pi_objs[pr2_pi_names[index]]] + vpg_pis = [pr1_pi_objs[pr1_pi_names[index]], + pr2_pi_objs[pr2_pi_names[index]]] with ExpectedException(BadRequest): update_vpg(vpg_obj, vpg_pis, index) def _multiple_vpg_with_multiple_pi( self, proj_obj, fabric_obj, pr_objs, validation): - '''Test Steps. + """Test Steps. Add all test steps - ''' + """ test_id = self.id().split('.')[-1] fabric_name = fabric_obj.get_fq_name() vlan_vn_count = 10 @@ -1117,7 +1135,7 @@ def get_zk_ae_ids(prs=None): vlan_ids = range(1, vlan_vn_count + 1) vn_names = ['vn_%s_%s' % (test_id, i) - for i in range(1, vlan_vn_count + 1)] + for i in range(1, vlan_vn_count + 1)] vn_objs = self._create_vns(proj_obj, vn_names) # create four PIs, two on each PR @@ -1134,11 +1152,12 @@ def get_zk_ae_ids(prs=None): # create three VPGs vpg_count = 10 - vpg_names = ['vpg_%s_%s' % (test_id, i) for i in range(1, vpg_count+1)] + vpg_names = ['vpg_%s_%s' % (test_id, i) for + i in range(1, vpg_count + 1)] vpg_objs = self._create_vpgs(fabric_obj, vpg_names) # record AE-IDs in ZK before creating any VPG - ae_ids = reduce(sum, get_zk_ae_ids().values()) + ae_ids = [x for x in get_zk_ae_ids().values() if x] self.assertEqual(len(ae_ids), 0) # create 10 VMIs, 4 PIs (2 from each PR) in a VPG @@ -1159,30 +1178,31 @@ def get_zk_ae_ids(prs=None): range(1, vlan_vn_count + 1)] for vmi_id in range(1, vlan_vn_count + 1): info = { - 'name': vpg1_vmi_names[vmi_id-1], + 'name': vpg1_vmi_names[vmi_id - 1], 'vmi_id': vmi_id, 'parent_obj': proj_obj, - 'vn': vn_objs[vn_names[vmi_id-1]], + 'vn': vn_objs[vn_names[vmi_id - 1]], 'vpg': vpg_objs[vpg_names[0]].uuid, 'fabric': fabric_name, 'pis': vpg1_pis, - 'vlan': vlan_ids[vmi_id-1], + 'vlan': vlan_ids[vmi_id - 1], 'is_untagged': False} vmi_infos.append(info) info = { - 'name': vpg2_vmi_names[vmi_id-1], + 'name': vpg2_vmi_names[vmi_id - 1], 'vmi_id': vmi_id, 'parent_obj': proj_obj, - 'vn': vn_objs[vn_names[vmi_id-1]], + 'vn': vn_objs[vn_names[vmi_id - 1]], 'vpg': vpg_objs[vpg_names[1]].uuid, 'fabric': fabric_name, 'pis': vpg2_pis, - 'vlan': vlan_ids[vmi_id-1], + 'vlan': vlan_ids[vmi_id - 1], 'is_untagged': False} vmi_infos.append(info) vmi_objs = self._create_vmis(vmi_infos) for vpg_name, vpg_obj in vpg_objs.items(): - vpg_objs[vpg_name] = self.api.virtual_port_group_read(id=vpg_obj.uuid) + vpg_objs[vpg_name] = self.api.virtual_port_group_read( + id=vpg_obj.uuid) # record AE-IDs allocated for each prouter ae_ids = {} @@ -1190,7 +1210,7 @@ def get_zk_ae_ids(prs=None): vpg_name = vpg_names[vpg] pi_refs = vpg_objs[vpg_name].get_physical_interface_refs() ae_ids[vpg_name] = {ref['href'].split('/')[-1]: ref['attr'].ae_num - for ref in pi_refs} + for ref in pi_refs} # verify all AE-IDs allocated per prouter are unique self.assertEqual(len(set(ae_ids[vpg_name].keys())), len(pi_refs)) self.assertEqual(len(set(ae_ids[vpg_name].values())), 1) @@ -1211,17 +1231,18 @@ def get_zk_ae_ids(prs=None): 'vpg': vpg_objs[vpg_name].uuid, 'fabric': fabric_name, 'pis': vpg1_pis[1:], - 'vlan': vlan_ids[vmi_id-1], + 'vlan': vlan_ids[vmi_id - 1], 'is_untagged': False}] - vmi_vpg1_1 = self._update_vmis(vmi_infos) + self._update_vmis(vmi_infos) # re-read VPGs - for vpg_name, vpg_obj in vpg_objs.items(): - vpg_objs[vpg_name] = self.api.virtual_port_group_read(id=vpg_obj.uuid) + for vpg, vpg_o in vpg_objs.items(): + vpg_objs[vpg] = self.api.virtual_port_group_read( + id=vpg_o.uuid) # Verifications at VPG-1 # check PI-1 is removed from VPG-1 - pi_refs = vpg_objs[vpg_names[0]].get_physical_interface_refs() + pi_refs = vpg_objs[vpg_name].get_physical_interface_refs() vpg1_ae_ids = [pi_ref['attr'].ae_num for pi_ref in pi_refs] self.assertEqual(len(pi_refs), 3) # verify AE-ID associated with VPG-1 @@ -1253,13 +1274,14 @@ def get_zk_ae_ids(prs=None): 'vpg': vpg_objs[vpg_name].uuid, 'fabric': fabric_name, 'pis': vpg1_pis[0], - 'vlan': vlan_ids[vmi_id-1], + 'vlan': vlan_ids[vmi_id - 1], 'is_untagged': False}] - vmi_vpg1_1 = self._update_vmis(vmi_infos) + self._update_vmis(vmi_infos) # re-read VPGs - for vpg_name, vpg_obj in vpg_objs.items(): - vpg_objs[vpg_name] = self.api.virtual_port_group_read(id=vpg_obj.uuid) + for vpg, vpg_o in vpg_objs.items(): + vpg_objs[vpg] = self.api.virtual_port_group_read( + id=vpg_o.uuid) # Verifications at VPG-1 # check PI-1 is removed from VPG-1 @@ -1345,13 +1367,14 @@ def get_zk_ae_ids(prs=None): 'vpg': vpg_objs[vpg_name].uuid, 'fabric': fabric_name, 'pis': vpg1_pis[0:2], - 'vlan': vlan_ids[vmi_id-1], + 'vlan': vlan_ids[vmi_id - 1], 'is_untagged': False}] - vmi_vpg1_1 = self._update_vmis(vmi_infos) + self._update_vmis(vmi_infos) # re-read VPGs for vpg_name, vpg_obj in vpg_objs.items(): - vpg_objs[vpg_name] = self.api.virtual_port_group_read(id=vpg_obj.uuid) + vpg_objs[vpg_name] = self.api.virtual_port_group_read( + id=vpg_obj.uuid) # Verifications at VPG-1 # check PI1/PR1 and PI2/PR1 are added to VPG-1 @@ -1386,15 +1409,12 @@ def get_zk_ae_ids(prs=None): vn_objs.update(caseX1_vn_objs) pi_per_pr = 2 caseX1_pr1_pi_names = ['%s_caseX1_pr1_pi%d' % (test_id, caseX1_id), - '%s_caseX1_pr1_pi%d' % (test_id, caseX1_id+1)] + '%s_caseX1_pr1_pi%d' % (test_id, caseX1_id + 1)] caseX1_pr1_pi_objs = self._create_pi_objects( pr_objs[0], caseX1_pr1_pi_names) - # not required, we need to attach all PIs to only PR1s - #case3_pr2_pi_objs = self._create_pi_objects( - # pr_objs[1], [case3_pr2_pi_name]) vpgX1_pis = [pi.get_fq_name() for pi in - [caseX1_pr1_pi_objs[caseX1_pr1_pi_names[0]], - caseX1_pr1_pi_objs[caseX1_pr1_pi_names[1]]]] + [caseX1_pr1_pi_objs[caseX1_pr1_pi_names[0]], + caseX1_pr1_pi_objs[caseX1_pr1_pi_names[1]]]] pi_objs.update(caseX1_pr1_pi_objs) vmi_info = { 'name': 'vmi_vpg4_%s_%s' % (test_id, caseX1_id), @@ -1409,7 +1429,8 @@ def get_zk_ae_ids(prs=None): caseX1_vmi_obj = self._create_vmis([vmi_info]) vmi_objs.update(caseX1_vmi_obj) # re-read VPG-3 - vpg_objs[vpg_names[3]] = self.api.virtual_port_group_read(id=vpgX1_uuid) + vpg_objs[vpg_names[3]] = self.api.virtual_port_group_read( + id=vpgX1_uuid) # Verifications at VPG-3 pi_refs = vpg_objs[vpg_names[3]].get_physical_interface_refs() vpgX1_ae_ids = [pi_ref['attr'].ae_num for pi_ref in pi_refs] @@ -1435,15 +1456,12 @@ def get_zk_ae_ids(prs=None): vn_objs.update(caseX2_vn_objs) pi_per_pr = 2 caseX2_pr1_pi_names = ['%s_caseX2_pr1_pi%d' % (test_id, caseX2_id), - '%s_caseX2_pr1_pi%d' % (test_id, caseX2_id+1)] + '%s_caseX2_pr1_pi%d' % (test_id, caseX2_id + 1)] caseX2_pr1_pi_objs = self._create_pi_objects( pr_objs[0], caseX2_pr1_pi_names) - # not required, we need to attach all PIs to only PR1s - #case3_pr2_pi_objs = self._create_pi_objects( - # pr_objs[1], [case3_pr2_pi_name]) vpgX2_pis = [pi.get_fq_name() for pi in - [caseX2_pr1_pi_objs[caseX2_pr1_pi_names[0]], - caseX2_pr1_pi_objs[caseX2_pr1_pi_names[1]]]] + [caseX2_pr1_pi_objs[caseX2_pr1_pi_names[0]], + caseX2_pr1_pi_objs[caseX2_pr1_pi_names[1]]]] pi_objs.update(caseX2_pr1_pi_objs) vmi_info = { 'name': 'vmi_vpg5_%s_%s' % (test_id, caseX2_id), @@ -1458,10 +1476,10 @@ def get_zk_ae_ids(prs=None): caseX2_vmi_obj = self._create_vmis([vmi_info]) vmi_objs.update(caseX2_vmi_obj) # re-read VPG-3 - vpg_objs[vpg_names[4]] = self.api.virtual_port_group_read(id=vpgX2_uuid) + vpg_objs[vpg_names[4]] = self.api.virtual_port_group_read( + id=vpgX2_uuid) # Verifications at VPG-3 pi_refs = vpg_objs[vpg_names[4]].get_physical_interface_refs() - vpgX2_ae_ids = [pi_ref['attr'].ae_num for pi_ref in pi_refs] self.assertEqual(len(pi_refs), 2) # verify an AE-ID is allocated self.assertEqual(len(set(vpgX1_ae_ids)), 1) @@ -1487,9 +1505,9 @@ def get_zk_ae_ids(prs=None): 'vpg': vpg_objs[vpg_name].uuid, 'fabric': fabric_name, 'pis': vpg1_pis[1], - 'vlan': vlan_ids[vmi_id-1], + 'vlan': vlan_ids[vmi_id - 1], 'is_untagged': False}] - vmi_vpg1_1 = self._update_vmis(vmi_infos) + self._update_vmis(vmi_infos) # re-read VPG1 vpg_objs[vpg_names[0]] = self.api.virtual_port_group_read(id=vpg1_uuid) @@ -1527,15 +1545,12 @@ def get_zk_ae_ids(prs=None): vn_objs.update(caseX4_vn_objs) pi_per_pr = 2 caseX4_pr1_pi_names = ['%s_caseX4_pr1_pi%d' % (test_id, caseX4_id), - '%s_caseX4_pr1_pi%d' % (test_id, caseX4_id+1)] + '%s_caseX4_pr1_pi%d' % (test_id, caseX4_id + 1)] caseX4_pr1_pi_objs = self._create_pi_objects( pr_objs[0], caseX4_pr1_pi_names) - # not required, we need to attach all PIs to only PR1s - #case3_pr2_pi_objs = self._create_pi_objects( - # pr_objs[1], [case3_pr2_pi_name]) vpgX4_pis = [pi.get_fq_name() for pi in - [caseX4_pr1_pi_objs[caseX4_pr1_pi_names[0]], - caseX4_pr1_pi_objs[caseX4_pr1_pi_names[1]]]] + [caseX4_pr1_pi_objs[caseX4_pr1_pi_names[0]], + caseX4_pr1_pi_objs[caseX4_pr1_pi_names[1]]]] pi_objs.update(caseX4_pr1_pi_objs) vmi_info = { 'name': 'vmi_vpg6_%s_%s' % (test_id, caseX4_id), @@ -1550,7 +1565,8 @@ def get_zk_ae_ids(prs=None): caseX4_vmi_obj = self._create_vmis([vmi_info]) vmi_objs.update(caseX4_vmi_obj) # re-read VPG-5 - vpg_objs[vpg_names[5]] = self.api.virtual_port_group_read(id=vpgX4_uuid) + vpg_objs[vpg_names[5]] = self.api.virtual_port_group_read( + id=vpgX4_uuid) # Verifications at VPG-5 pi_refs = vpg_objs[vpg_names[5]].get_physical_interface_refs() vpgX4_ae_ids = [pi_ref['attr'].ae_num for pi_ref in pi_refs] @@ -1567,8 +1583,6 @@ def get_zk_ae_ids(prs=None): # TO-DO # Verify AE-ID is re-allocated instead of new one - - # Case 5 vpg_objs[vpg_names[0]] = self.api.virtual_port_group_read( id=vpg_objs[vpg_names[0]].uuid) @@ -1584,7 +1598,7 @@ def get_zk_ae_ids(prs=None): case5_pr2_pi_objs = self._create_pi_objects( pr_objs[1], [case5_pr2_pi_name]) vpg1_case5_pis = [pi.get_fq_name() for pi in - [case5_pr2_pi_objs[case5_pr2_pi_name]]] + [case5_pr2_pi_objs[case5_pr2_pi_name]]] vpg1_case5_pis += curr_pis pi_objs.update(case5_pr2_pi_objs) vmi_info = { @@ -1601,7 +1615,8 @@ def get_zk_ae_ids(prs=None): vmi_objs.update(case5_vmi_obj) # re-read VPGs for vpg_name, vpg_obj in vpg_objs.items(): - vpg_objs[vpg_name] = self.api.virtual_port_group_read(id=vpg_obj.uuid) + vpg_objs[vpg_name] = self.api.virtual_port_group_read( + id=vpg_obj.uuid) # Verifications at VPG-1 # check PI-1 is removed from VPG-1 @@ -1636,7 +1651,6 @@ def get_zk_ae_ids(prs=None): self.api.fabric_delete(id=fabric_obj.uuid) self.api.project_delete(id=proj_obj.uuid) - def _multiple_vpg_with_multiple_pi_old( self, proj_obj, fabric_obj, pr_obj, validation): pi_count = 300 @@ -1650,26 +1664,26 @@ def _multiple_vpg_with_multiple_pi_old( for i in range(1, vlan_vn_count)] vn_objs = self._create_vns(proj_obj, vn_names) - pi_names = ['phy_intf_%s_%s' % (test_id, i) for i in range(1, pi_count + 1)] + pi_names = ['phy_intf_%s_%s' % (test_id, i) for i in range( + 1, pi_count + 1)] pi_objs = self._create_pi_objects(pr_obj, pi_names) - pi_fq_names = [pi_objs[pi].get_fq_name() for pi, obj in pi_objs.items()] - - vpg_names = ['vpg_%s_%s' % (test_id, i) for i in range(1, vlan_vn_count)] + vpg_names = ['vpg_%s_%s' % (test_id, i) for i in range( + 1, vlan_vn_count)] vpg_objs = self._create_vpgs(fabric_obj, vpg_names) vmi_infos = [] for vmi_id in range(1, vlan_vn_count): - pinames = pi_names[(vmi_id-1)* pi_per_vmi : vmi_id * pi_per_vmi] + pinames = pi_names[(vmi_id - 1) * pi_per_vmi: vmi_id * pi_per_vmi] pis = [pi_objs[pi].get_fq_name() for pi in pinames] info = { 'name': 'vmi_%s_%s' % (test_id, vmi_id), 'vmi_id': vmi_id, 'parent_obj': proj_obj, - 'vn': vn_objs[vn_names[vmi_id-1]], - 'vpg': vpg_objs[vpg_names[vmi_id-1]].uuid, + 'vn': vn_objs[vn_names[vmi_id - 1]], + 'vpg': vpg_objs[vpg_names[vmi_id - 1]].uuid, 'fabric': fabric_name, 'pis': pis, - 'vlan': vlan_ids[vmi_id-1], + 'vlan': vlan_ids[vmi_id - 1], 'is_untagged': False} vmi_infos.append(info) @@ -1725,17 +1739,17 @@ def _multiple_vpg_with_multiple_pi_old( set(ae_nums_org), set(extra_ae_nums), 'AE numbers before (%s) and after (%s) ' - 'replacing PI are not same' %( - ae_nums_org, extra_ae_nums)) + 'replacing PI are not same' % ( + ae_nums_org, extra_ae_nums)) # add a three more pis to first VMI extra_2_pi_start = extra_pi_end + 1 extra_2_pi_end = extra_2_pi_start + 4 extra_2_pi_names = ['phy_intf_%s_%s' % (test_id, i) - for i in range(extra_2_pi_start, extra_2_pi_end)] + for i in range(extra_2_pi_start, extra_2_pi_end)] extra_2_pi_objs = self._create_pi_objects(pr_obj, extra_2_pi_names) extra_2_pi_fq_names = [extra_2_pi_objs[pi].get_fq_name() - for pi, obj in extra_2_pi_objs.items()] + for pi, obj in extra_2_pi_objs.items()] vmi_obj_1 = vmi_objs[vmi_objs.keys()[0]] kv_pairs = self._create_kv_pairs( extra_pi_fq_names + extra_2_pi_fq_names, fabric_name, @@ -1760,8 +1774,8 @@ def _multiple_vpg_with_multiple_pi_old( set(ae_nums_org), set(ae_nums_new), 'AE numbers before (%s) and after (%s) ' - 'replacing PI are not same' %( - ae_nums_org, ae_nums_new)) + 'replacing PI are not same' % ( + ae_nums_org, ae_nums_new)) # cleanup for vmi_name, vmi_obj in vmi_objs.items(): @@ -1780,7 +1794,6 @@ def _multiple_vpg_with_multiple_pi_old( self.api.fabric_delete(id=fabric_obj.uuid) self.api.project_delete(id=proj_obj.uuid) - def test_multiple_vpg_with_multiple_pi(self): """Verify adding a PI to VMI in enterprise style.""" proj_obj, fabric_obj, pr_objs = self._create_prerequisites( @@ -3786,6 +3799,323 @@ def test_ae_id_deallocated_for_vpg_multihoming_interfaces(self): self.api.virtual_network_read(id=vn1_obj.uuid) self.api.fabric_delete(id=fabric_obj.uuid) + # Using VPG update logic + def test_same_pi_can_not_attach_to_different_vpg(self): + proj_obj, fabric_obj, pr_obj = self._create_prerequisites() + test_id = self.id() + + pi_per_pr = 4 + pi_names = ['%s_pr1_pi%d' % (test_id, i) for + i in range(1, pi_per_pr + 1)] + pi_objs = self._create_pi_objects(pr_obj, pi_names) + + vpg_count = 2 + vpg_names = ['vpg_%s_%s' % (test_id, i) for i in range( + 1, vpg_count + 1)] + vpg_objs = self._create_vpgs(fabric_obj, vpg_names) + + # Add all PIs to VPG-1 + vpg_obj = vpg_objs[vpg_names[0]] + for pi_name in pi_names: + vpg_obj.add_physical_interface(pi_objs[pi_name]) + self.api.virtual_port_group_update(vpg_obj) + vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) + pi_refs = vpg_obj.get_physical_interface_refs() + self.assertEqual(len(pi_refs), 4) + + # Try Add PI1, PI2 to VPG-2 + vpg_obj = vpg_objs[vpg_names[1]] + vpg_obj.add_physical_interface(pi_objs[pi_names[0]]) + vpg_obj.add_physical_interface(pi_objs[pi_names[1]]) + with ExpectedException(BadRequest): + self.api.virtual_port_group_update(vpg_obj) + + # Delete PI1, PI2 from VPG-1 + vpg_obj = vpg_objs[vpg_names[0]] + for pi_name in pi_names[:2]: + vpg_obj.del_physical_interface(pi_objs[pi_name]) + self.api.virtual_port_group_update(vpg_obj) + vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) + pi_refs = vpg_obj.get_physical_interface_refs() + self.assertEqual(len(pi_refs), 2) + + # Now try attach PI1, PI2 to VPG-2, + # should work as PI1, PI2 are no longer attached to VPG1 + vpg_obj = vpg_objs[vpg_names[1]] + vpg_obj.add_physical_interface(pi_objs[pi_names[0]]) + vpg_obj.add_physical_interface(pi_objs[pi_names[1]]) + self.api.virtual_port_group_update(vpg_obj) + vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) + pi_refs = vpg_obj.get_physical_interface_refs() + self.assertEqual(len(pi_refs), 2) + + # cleanup + for _, vpg_obj in vpg_objs.items(): + self.api.virtual_port_group_delete(id=vpg_obj.uuid) + for _, pi_obj in pi_objs.items(): + self.api.physical_interface_delete(id=pi_obj.uuid) + self.api.physical_router_delete(id=pr_obj.uuid) + self.api.fabric_delete(id=fabric_obj.uuid) + self.api.project_delete(id=proj_obj.uuid) + + # To verify allocation and dellocation - through VMI + def test_ae_id_alloc_dealloc(self): + proj_obj, fabric_obj, pr_objs = self._create_prerequisites( + create_second_pr=True) + test_id = self.id().split('.')[-1] + fabric_name = fabric_obj.get_fq_name() + vlan_vn_count = 3 + + def process_ae_ids(x): + return [int(i) for i in sorted(x)] + + def get_zk_ae_ids(prs=None): + prefix = os.path.join( + self.__class__.__name__, + 'id', 'aggregated-ethernet') + zk_client = self._api_server._db_conn._zk_db._zk_client._zk_client + if not prs: + prs = [os.path.join(prefix, pr.name) for pr in pr_objs] + else: + if not isinstance(prs, list): + prs = [prs] + prs = [os.path.join(prefix, pr) for pr in prs] + ae_ids = {} + for pr in prs: + pr_org = os.path.split(pr)[-1] + ae_ids[pr_org] = zk_client.get_children(pr) + return ae_ids + + vlan_ids = range(1, vlan_vn_count + 1) + vn_names = ['vn_%s_%s' % (test_id, i) + for i in range(1, vlan_vn_count + 1)] + vn_objs = self._create_vns(proj_obj, vn_names) + + vmi_objs = {} + # create four PIs, two on each PR + pi_objs = {} + pi_per_pr = 1 + pr1_pi_names = ['%s_pr1_pi%d' % (test_id, i) for + i in range(1, pi_per_pr + 1)] + pr2_pi_names = ['%s_pr2_pi%d' % (test_id, i) for + i in range(1, pi_per_pr + 1)] + pr1_pi_objs = self._create_pi_objects(pr_objs[0], pr1_pi_names) + pr2_pi_objs = self._create_pi_objects(pr_objs[1], pr2_pi_names) + pi_objs.update(pr1_pi_objs) + pi_objs.update(pr2_pi_objs) + + # create VPGs + vpg_count = 2 + vpg_names = ['vpg_%s_%s' % (test_id, i) + for i in range(1, vpg_count + 1)] + vpg_objs = self._create_vpgs(fabric_obj, vpg_names) + + # record AE-IDs in ZK before creating any VPG + ae_ids = [x for x in get_zk_ae_ids().values() if x] + self.assertEqual(len(ae_ids), 0) + + # Case 1: Attach PI-1/PR-1 and PI-1/PR-2 to VPG-1 + # one AE-ID i.e 0 to be allocated to VPG-1 + vpg_index = 0 + vpg_name = vpg_names[0] + vpg_obj = vpg_objs[vpg_name] + vpg_pi_fqs = [pi.get_fq_name() for _, pi in pi_objs.items()] + vmi_infos = [] + vmi_vn_vlan_map = defaultdict(list) + for vmi_id in range(3): + vmi_name = 'vmi_%s_%s' % (test_id, vmi_id) + info = { + 'name': vmi_name, + 'vmi_id': '%s' % vmi_id, + 'parent_obj': proj_obj, + 'vn': vn_objs[vn_names[vmi_id - 1]], + 'vpg': vpg_obj.uuid, + 'fabric': fabric_name, + 'pis': vpg_pi_fqs, + 'vlan': vlan_ids[vmi_id - 1], + 'is_untagged': False} + vmi_infos.append(info) + vmi_vn_vlan_map[vmi_name] = ( + vn_objs[vn_names[vmi_id - 1]], vlan_ids[vmi_id - 1]) + vmi_objs = self._create_vmis(vmi_infos) + for vpg, vpg_o in vpg_objs.items(): + vpg_objs[vpg] = self.api.virtual_port_group_read( + id=vpg_o.uuid) + + # record AE-IDs allocated for each prouter + ae_ids = {} + pi_refs = vpg_objs[vpg_name].get_physical_interface_refs() + self.assertEqual(len(pi_refs), len(vpg_pi_fqs)) + ae_ids[vpg_name] = {ref['href'].split('/')[-1]: ref['attr'].ae_num + for ref in pi_refs} + # verify all AE-IDs allocated per prouter are unique + self.assertEqual(len(set(ae_ids[vpg_name].keys())), + len(vpg_pi_fqs)) + self.assertEqual(len(set(ae_ids[vpg_name].values())), 1) + self.assertEqual(list(ae_ids[vpg_name].values()), [0, 0]) + + # verification at Physical Routers + pr_ae_ids = get_zk_ae_ids() + self.assertEqual(len(pr_ae_ids[pr_objs[0].name]), 1) + self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[0].name]), [0]) + self.assertEqual(len(pr_ae_ids[pr_objs[1].name]), 1) + self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[1].name]), [0]) + + # Case 2: Attach only one PI to VPG-1 + vpg_index = 0 + vpg_name = vpg_names[0] + vpg_obj = vpg_objs[vpg_name] + vpg_pi_fqs = [pr1_pi_objs[pr1_pi_names[0]].get_fq_name()] + vmi_infos = [] + vmi_names = list(vmi_objs.keys()) + for vmi_id in range(3): + info = { + 'name': vmi_names[vmi_id], + 'vmi_uuid': '%s' % vmi_objs[vmi_names[vmi_id]].uuid, + 'vn': vmi_vn_vlan_map[vmi_names[vmi_id]][0], + 'vpg': vpg_obj.uuid, + 'fabric': fabric_name, + 'pis': vpg_pi_fqs, + 'vlan': vmi_vn_vlan_map[vmi_names[vmi_id]][1], + 'is_untagged': False} + vmi_infos.append(info) + vmi_objs = self._update_vmis(vmi_infos) + for vpg, vpg_o in vpg_objs.items(): + vpg_objs[vpg] = self.api.virtual_port_group_read( + id=vpg_o.uuid) + + # record AE-IDs allocated for each prouter + ae_ids = {} + pi_refs = vpg_objs[vpg_name].get_physical_interface_refs() + self.assertEqual(len(pi_refs), len(vpg_pi_fqs)) + ae_ids[vpg_name] = {ref['href'].split('/')[-1]: ref['attr'].ae_num + for ref in pi_refs} + # verify all AE-IDs allocated per prouter are unique + self.assertEqual(len(set(ae_ids[vpg_name].keys())), + len(vpg_pi_fqs)) + self.assertIsNone(list(ae_ids[vpg_name].values())[0]) + self.assertEqual(list(ae_ids[vpg_name].values()), [None]) + + # verification at Physical Routers + pr_ae_ids = get_zk_ae_ids() + self.assertEqual(len(pr_ae_ids[pr_objs[0].name]), 0) + self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[0].name]), []) + self.assertEqual(len(pr_ae_ids[pr_objs[1].name]), 0) + self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[1].name]), []) + + # Case-3: Add All PIs back to VPG and update VMIs + # ensure AE-IDs are allocated back + vpg_index = 0 + vpg_name = vpg_names[0] + vpg_obj = vpg_objs[vpg_name] + vpg_pi_fqs = [pi.get_fq_name() for _, pi in pi_objs.items()] + vmi_infos = [] + vmi_names = list(vmi_objs.keys()) + for vmi_id in range(3): + info = { + 'name': vmi_names[vmi_id], + 'vmi_uuid': '%s' % vmi_objs[vmi_names[vmi_id]].uuid, + 'vn': vmi_vn_vlan_map[vmi_names[vmi_id]][0], + 'vpg': vpg_obj.uuid, + 'fabric': fabric_name, + 'pis': vpg_pi_fqs, + 'vlan': vmi_vn_vlan_map[vmi_names[vmi_id]][1], + 'is_untagged': False} + vmi_infos.append(info) + vmi_objs = self._update_vmis(vmi_infos) + for vpg, vpg_o in vpg_objs.items(): + vpg_objs[vpg] = self.api.virtual_port_group_read( + id=vpg_o.uuid) + + # record AE-IDs allocated for each prouter + ae_ids = {} + pi_refs = vpg_objs[vpg_name].get_physical_interface_refs() + self.assertEqual(len(pi_refs), len(vpg_pi_fqs)) + ae_ids[vpg_name] = {ref['href'].split('/')[-1]: ref['attr'].ae_num + for ref in pi_refs} + # verify all AE-IDs allocated per prouter are unique + self.assertEqual(len(set(ae_ids[vpg_name].keys())), + len(vpg_pi_fqs)) + self.assertEqual(len(set(ae_ids[vpg_name].values())), 1) + self.assertEqual(list(ae_ids[vpg_name].values()), [0, 0]) + + # verification at Physical Routers + pr_ae_ids = get_zk_ae_ids() + self.assertEqual(len(pr_ae_ids[pr_objs[0].name]), 1) + self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[0].name]), [0]) + self.assertEqual(len(pr_ae_ids[pr_objs[1].name]), 1) + self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[1].name]), [0]) + + # Case-4: Delete two VMIs + # Ensure all AE-IDs are deallocated + for _, vmi_obj in list(vmi_objs.items())[0:2]: + self.api.virtual_machine_interface_delete(id=vmi_obj.uuid) + + # record AE-IDs allocated for each prouter + ae_ids = {} + pi_refs = vpg_objs[vpg_name].get_physical_interface_refs() + self.assertEqual(len(pi_refs), len(vpg_pi_fqs)) + ae_ids[vpg_name] = {ref['href'].split('/')[-1]: ref['attr'].ae_num + for ref in pi_refs} + # verify all AE-IDs allocated per prouter are unique + self.assertEqual(len(set(ae_ids[vpg_name].keys())), + len(vpg_pi_fqs)) + self.assertEqual(len(set(ae_ids[vpg_name].values())), 1) + self.assertEqual(list(ae_ids[vpg_name].values()), [0, 0]) + + # verification at Physical Routers + pr_ae_ids = get_zk_ae_ids() + self.assertEqual(len(pr_ae_ids[pr_objs[0].name]), 1) + self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[0].name]), [0]) + self.assertEqual(len(pr_ae_ids[pr_objs[1].name]), 1) + self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[1].name]), [0]) + + # Case 5 : Delete VPG-1 + vpg_index = 0 + vpg_obj = vpg_objs[vpg_names[vpg_index]] + vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) + for vmi_ref in vpg_obj.get_virtual_machine_interface_refs(): + self.api.virtual_machine_interface_delete(id=vmi_ref['uuid']) + del vpg_objs[vpg_names[0]] + # Now delete VPG-1 + self.api.virtual_port_group_delete(id=vpg_obj.uuid) + # Verification at Physical Routers + with ExpectedException(NoIdError): + self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) + pr_ae_ids = get_zk_ae_ids() + self.assertEqual(len(pr_ae_ids[pr_objs[0].name]), 0) + self.assertEqual(len(pr_ae_ids[pr_objs[0].name]), 0) + self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[0].name]), []) + self.assertEqual(process_ae_ids(pr_ae_ids[pr_objs[1].name]), []) + + # cleanup + # remove VMIs + # already cleared during Case 5 + for _, vmi_obj in vmi_objs.items(): + try: + self.api.virtual_machine_interface_delete(id=vmi_obj.uuid) + except NoIdError: + pass + # remove VNs + for _, vn_obj in vn_objs.items(): + self.api.virtual_network_delete(id=vn_obj.uuid) + # remove VPGs + for _, vpg_obj in vpg_objs.items(): + try: + self.api.virtual_port_group_delete(id=vpg_obj.uuid) + except NoIdError: + pass + # remove PIs + for _, pi_obj in pi_objs.items(): + self.api.physical_interface_delete(id=pi_obj.uuid) + # remove PR + for pr_obj in pr_objs: + self.api.physical_router_delete(id=pr_obj.uuid) + # remove fabric + self.api.fabric_delete(id=fabric_obj.uuid) + # remove project + self.api.project_delete(id=proj_obj.uuid) + def test_two_virtual_port_groups_for_single_pi(self): # Similar to e.g. test_same_vn_with_same_vlan_across_vpg_in_enterprise, # but one of VPG's has no name and we try to bind one PI to both VPGs @@ -3842,9 +4172,8 @@ def test_two_virtual_port_groups_for_single_pi(self): # Create single VN for second VMI vn2 = VirtualNetwork('vn2-%s' % (self.id()), parent_obj=proj_obj) self.api.virtual_network_create(vn2) - # Create a VMI that's attached to vpg-2 and having reference - # to vn1 + # to vn2 vmi_obj_2 = VirtualMachineInterface(self.id() + "2", parent_obj=proj_obj) vmi_obj_2.set_virtual_network(vn2) @@ -3867,61 +4196,3 @@ def test_two_virtual_port_groups_for_single_pi(self): self.api.physical_interface_delete(id=pi_uuid) self.api.physical_router_delete(id=pr_obj.uuid) self.api.fabric_delete(id=fabric_obj.uuid) - - def test_same_pi_can_not_attach_to_different_vpg(self): - proj_obj, fabric_obj, pr_obj = self._create_prerequisites() - test_id = self.id() - - pi_per_pr = 4 - pi_names = ['%s_pr1_pi%d' % (test_id, i) for - i in range(1, pi_per_pr + 1)] - pi_objs = self._create_pi_objects(pr_obj, pi_names) - - vpg_count = 2 - vpg_names = ['vpg_%s_%s' % (test_id, i) for i in range(1, vpg_count+1)] - vpg_objs = self._create_vpgs(fabric_obj, vpg_names) - - # Add all PIs to VPG-1 - vpg_obj = vpg_objs[vpg_names[0]] - for pi_name in pi_names: - vpg_obj.add_physical_interface(pi_objs[pi_name]) - self.api.virtual_port_group_update(vpg_obj) - vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) - pi_refs = vpg_obj.get_physical_interface_refs() - self.assertEqual(len(pi_refs), 4) - - # Try Add PI1, PI2 to VPG-2 - vpg_obj = vpg_objs[vpg_names[1]] - vpg_obj.add_physical_interface(pi_objs[pi_names[0]]) - vpg_obj.add_physical_interface(pi_objs[pi_names[1]]) - with ExpectedException(BadRequest) as exc: - self.api.virtual_port_group_update(vpg_obj) - - # Delete PI1, PI2 from VPG-1 - vpg_obj = vpg_objs[vpg_names[0]] - for pi_name in pi_names[:2]: - vpg_obj.del_physical_interface(pi_objs[pi_name]) - self.api.virtual_port_group_update(vpg_obj) - vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) - pi_refs = vpg_obj.get_physical_interface_refs() - self.assertEqual(len(pi_refs), 2) - - # Now try attach PI1, PI2 to VPG-2, - # should work as PI1, PI2 are no longer attached to VPG1 - vpg_obj = vpg_objs[vpg_names[1]] - vpg_obj.add_physical_interface(pi_objs[pi_names[0]]) - vpg_obj.add_physical_interface(pi_objs[pi_names[1]]) - self.api.virtual_port_group_update(vpg_obj) - vpg_obj = self._vnc_lib.virtual_port_group_read(id=vpg_obj.uuid) - pi_refs = vpg_obj.get_physical_interface_refs() - self.assertEqual(len(pi_refs), 2) - - # cleanup - for _, vpg_obj in vpg_objs.items(): - self.api.virtual_port_group_delete(id=vpg_obj.uuid) - for _, pi_obj in pi_objs.items(): - self.api.physical_interface_delete(id=pi_obj.uuid) - self.api.physical_router_delete(id=pr_obj.uuid) - self.api.fabric_delete(id=fabric_obj.uuid) - self.api.project_delete(id=proj_obj.uuid) -