From 0c46e09076321e06a4cbb4269f63e468b5feb4d5 Mon Sep 17 00:00:00 2001 From: Ranjeet R Date: Thu, 10 Mar 2016 14:03:32 -0800 Subject: [PATCH] Fixes: Stale Service chain entries seen in Schema Introspect Deleting a VN should check for service chain references and delete the service chain as well if the service chain does not have VN references. Change-Id: I8040032459821fa8dc3a555ff59d4278698b50a8 ClosesBug: 1545475 --- src/config/schema-transformer/config_db.py | 56 ++++++++++++------- .../schema-transformer/test/test_service.py | 42 ++++++++++++++ 2 files changed, 79 insertions(+), 19 deletions(-) diff --git a/src/config/schema-transformer/config_db.py b/src/config/schema-transformer/config_db.py index 1e654c56009..91e16707444 100644 --- a/src/config/schema-transformer/config_db.py +++ b/src/config/schema-transformer/config_db.py @@ -358,6 +358,41 @@ def check_multi_policy_service_chain_status(self): sc, other_si_name, multi_policy_enabled) # end check_multi_policy_service_chain_status + def delete_inactive_service_chains(self, old_scs, new_scs=None): + + # Delete the service chains that are no longer active + for remote_vn_name in old_scs: + # Get the Remote VNs in this VN's service chain and + # get a list of the remote service chains in the remote + # VNs which has this VNs name. + remote_vn = VirtualNetworkST.get(remote_vn_name) + if remote_vn is None: + remote_service_chain_list = [] + else: + remote_service_chain_list = remote_vn.service_chains.get(self.name) + + # Get a list of this VN's service chains which has a + # remote VN name as one of its service endpoints. + # Case 1: If the Service Chain is present in the updated + # SC list (if any), then dont do anythnig. + # Case 2: If the SC is not present in the updated SC + # list (if any), but present in the remote VN + # SC list, then invalidate it and mark it for + # deletion. + # Case 3: If the SC is not present in the updated SC + # list (if any) and not in the remote VN SC list, + # then delete it permanentely since there is no + # VNs that are referring to this SC. + service_chain_list = old_scs[remote_vn_name] + for service_chain in service_chain_list or []: + if new_scs and\ + service_chain in (new_scs.get(remote_vn_name) or []): + continue + if service_chain in (remote_service_chain_list or []): + service_chain.destroy() + else: + service_chain.delete() + def delete_obj(self): for policy_name in self.network_policys: policy = NetworkPolicyST.get(policy_name) @@ -366,9 +401,7 @@ def delete_obj(self): policy.virtual_networks.discard(self.name) self.update_multiple_refs('virtual_machine_interface', {}) - for service_chain_list in self.service_chains.values(): - for service_chain in service_chain_list: - service_chain.destroy() + self.delete_inactive_service_chains(self.service_chains) for ri_name in self.routing_instances: RoutingInstanceST.delete(ri_name) if self.acl: @@ -1324,22 +1357,7 @@ def evaluate(self): # end for service_chain # end for remote_vn_name - # Delete the service chains that are no longer active - for remote_vn_name in old_service_chains: - remote_vn = VirtualNetworkST.get(remote_vn_name) - if remote_vn is None: - continue - remote_service_chain_list = remote_vn.service_chains.get(self.name) - service_chain_list = old_service_chains[remote_vn_name] - for service_chain in service_chain_list or []: - if service_chain in (self.service_chains.get(remote_vn_name) - or []): - continue - if service_chain in (remote_service_chain_list or []): - service_chain.destroy() - else: - service_chain.delete() - # for remote_vn_name + self.delete_inactive_service_chains(old_service_chains, self.service_chains) self.update_route_table() self.update_pnf_presence() diff --git a/src/config/schema-transformer/test/test_service.py b/src/config/schema-transformer/test/test_service.py index cafe801269d..8f8f489ef17 100644 --- a/src/config/schema-transformer/test/test_service.py +++ b/src/config/schema-transformer/test/test_service.py @@ -107,6 +107,12 @@ def check_v6_service_chain_info(self, fq_name, expected): raise Exception('Ipv6 service chain info not found for %s' % fq_name) self.assertEqual(sci, expected) + @retries(5) + def check_service_chain_is_deleted(self, sc_uuid): + for sc in to_bgp.ServiceChain.values(): + if sc_uuid == sc.name: + raise Exception('Service chain %s not deleted' % sc_uuid) + @retries(5) def check_analyzer_ip(self, vmi_fq_name): vmi = self._vnc_lib.virtual_machine_interface_read(vmi_fq_name) @@ -928,6 +934,42 @@ def test_service_policy_no_vm(self): self.check_ri_is_deleted(fq_name=self.get_ri_name(vn2_obj)) # end test_service_policy_no_vm + def test_service_policy_delete_vns_deletes_scs(self): + # Test to check deleting VNs without deleting the + # policy associated, deletes the service chain. + + # create vn1 + vn1_name = self.id() + 'vn1' + vn1_obj = self.create_virtual_network(vn1_name, '10.0.0.0/24') + + # create vn2 + vn2_name = self.id() + 'vn2' + vn2_obj = self.create_virtual_network(vn2_name, '20.0.0.0/24') + + service_name = self.id() + 's1' + np = self.create_network_policy(vn1_obj, vn2_obj) + seq = SequenceType(1, 1) + vnp = VirtualNetworkPolicyType(seq) + + vn1_obj.set_network_policy(np, vnp) + vn2_obj.set_network_policy(np, vnp) + self._vnc_lib.virtual_network_update(vn1_obj) + self._vnc_lib.virtual_network_update(vn2_obj) + + np.network_policy_entries.policy_rule[0].action_list.apply_service = ["default-domain:default-project:"+service_name] + np.set_network_policy_entries(np.network_policy_entries) + self._vnc_lib.network_policy_update(np) + sc = self.wait_to_get_sc() + sc_ri_name = 'service-'+sc+'-default-domain_default-project_' + service_name + + self._vnc_lib.virtual_network_delete(fq_name=vn1_obj.get_fq_name()) + self._vnc_lib.virtual_network_delete(fq_name=vn2_obj.get_fq_name()) + + self.check_service_chain_is_deleted(sc_uuid=sc) + self.check_vn_is_deleted(uuid=vn1_obj.uuid) + self.check_vn_is_deleted(uuid=vn2_obj.uuid) + # end test_service_policy_delete_vns_deletes_scs + def test_multi_service_in_policy(self): # create vn1 vn1_name = self.id() + 'vn1'