Skip to content

Commit

Permalink
Fixes: Stale Service chain entries seen in Schema Introspect
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Ranjeet R committed Mar 11, 2016
1 parent fa4dc42 commit 0c46e09
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 19 deletions.
56 changes: 37 additions & 19 deletions src/config/schema-transformer/config_db.py
Expand Up @@ -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)
Expand All @@ -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:
Expand Down Expand Up @@ -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()
Expand Down
42 changes: 42 additions & 0 deletions src/config/schema-transformer/test/test_service.py
Expand Up @@ -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)
Expand Down Expand Up @@ -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'
Expand Down

0 comments on commit 0c46e09

Please sign in to comment.