diff --git a/src/config/schema-transformer/config_db.py b/src/config/schema-transformer/config_db.py index 163da28f04d..f0029d82207 100644 --- a/src/config/schema-transformer/config_db.py +++ b/src/config/schema-transformer/config_db.py @@ -2474,6 +2474,8 @@ def init(cls): chain.created_stale = chain.created if not hasattr(chain, 'partially_created'): chain.partially_created = False + if not hasattr(chain, 'si_info'): + chain.si_info = None cls._dict[name] = chain # end init @@ -2486,6 +2488,7 @@ def __init__(self, name, left_vn, right_vn, direction, sp_list, dp_list, self.sp_list = sp_list self.dp_list = dp_list self.service_list = list(services) + self.si_info = None self.protocol = protocol self.created = False @@ -2669,6 +2672,15 @@ def create(self): if si_info is None: # if previously created but no longer valid, then destroy self.destroy() + + # If the VMIs associated with the SC has changed + # after the SC is created, recreate the SC object. + if self.si_info != None and si_info != self.si_info: + self._create(si_info) + self.si_info = si_info + if self.partially_created: + self.destroy() + return return if si_info is None: @@ -2677,6 +2689,7 @@ def create(self): if self.partially_created: self.destroy() return + self.si_info = si_info self.uve_send() # end create diff --git a/src/config/schema-transformer/test/test_service_policy.py b/src/config/schema-transformer/test/test_service_policy.py index 60929c262e7..25c22f190f5 100644 --- a/src/config/schema-transformer/test/test_service_policy.py +++ b/src/config/schema-transformer/test/test_service_policy.py @@ -29,6 +29,8 @@ from test_utils import CassandraCFs import test_common from unittest import skip +from netaddr import IPNetwork, IPAddress +import uuid class VerifyServicePolicy(VerifyPolicy): @@ -49,8 +51,12 @@ def wait_to_get_sc(self, left_vn=None, right_vn=None, si_name=None, @retries(5) def check_service_chain_prefix_match(self, fq_name, prefix): + ip_version = IPNetwork(prefix).version ri = self._vnc_lib.routing_instance_read(fq_name) - sci = ri.get_service_chain_information() + if ip_version == 6: + sci = ri.get_ipv6_service_chain_information() + else: + sci = ri.get_service_chain_information() if sci is None: print "retrying ... ", test_common.lineno() raise Exception('Service chain info not found for %s' % fq_name) @@ -1887,7 +1893,7 @@ def test_service_policy_vmi_with_multi_port_tuples(self): vn1_obj.del_network_policy(np) vn2_obj.del_network_policy(np) - vn2_obj.del_network_policy(np) + vn3_obj.del_network_policy(np) self._vnc_lib.virtual_network_update(vn1_obj) self._vnc_lib.virtual_network_update(vn2_obj) @@ -1931,4 +1937,96 @@ def test_mps_with_nat(self, version=2): 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()) # end test_mps_with_nat + + def assign_vn_subnet(self, vn_obj, subnet_list): + subnet_info = [] + for subnet in subnet_list: + cidr = IPNetwork(subnet) + subnet_info.append(IpamSubnetType( + subnet = SubnetType( + str(cidr.network), + int(cidr.prefixlen), + ), + default_gateway = str(IPAddress(cidr.last - 1)), + subnet_uuid = str(uuid.uuid4()), + ) + ) + ipam_fq_name = [ + 'default-domain', 'default-project', 'default-network-ipam'] + ipam_obj = self._vnc_lib.network_ipam_read(fq_name=ipam_fq_name) + subnet_data = VnSubnetsType(subnet_info) + vn_obj.add_network_ipam(ipam_obj, subnet_data) + self._vnc_lib.virtual_network_update(vn_obj) + vn_obj.clear_pending_updates() + + def test_service_policy_with_v4_v6_subnets(self): + + # If the SC chain info changes after the SI is created + # (for example, IP address assignment) then the + # RI needs to be updated with the new info. + + # Create VN without subnets + vn1_name = self.id() + 'vn1' + vn2_name = self.id() + 'vn2' + vn1_obj = VirtualNetwork(name=vn1_name) + self._vnc_lib.virtual_network_create(vn1_obj) + vn2_obj = VirtualNetwork(name=vn2_name) + self._vnc_lib.virtual_network_create(vn2_obj) + + # Create SC + service_name = self.id() + 's1' + np = self.create_network_policy(vn1_obj, vn2_obj, [service_name], version=2) + 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) + sc = self.wait_to_get_sc() + + # Assign prefix after the SC is created + self.assign_vn_subnet(vn1_obj, ['10.0.0.0/24', '1000::/16']) + self.assign_vn_subnet(vn2_obj, ['20.0.0.0/24', '2000::/16']) + + sc_ri_name = 'service-'+sc+'-default-domain_default-project_' + service_name + self.check_ri_ref_present(self.get_ri_name(vn1_obj), + self.get_ri_name(vn1_obj, sc_ri_name)) + self.check_ri_ref_present(self.get_ri_name(vn2_obj, sc_ri_name), + self.get_ri_name(vn2_obj)) + + # Checking the Service chain address in the service RI + v4_service_chain_address = '10.0.0.251' + v6_service_chain_address = '1000:ffff:ffff:ffff:ffff:ffff:ffff:fffb' + + sci = ServiceChainInfo(prefix = ['10.0.0.0/24'], + routing_instance = ':'.join(self.get_ri_name(vn1_obj)), + service_chain_address = v4_service_chain_address, + service_instance = 'default-domain:default-project:' + service_name) + self.check_service_chain_info(self.get_ri_name(vn2_obj, sc_ri_name), sci) + sci.prefix = ['1000::/16'] + sci.service_chain_address = v6_service_chain_address + self.check_v6_service_chain_info(self.get_ri_name(vn2_obj, sc_ri_name), sci) + sci = ServiceChainInfo(prefix = ['20.0.0.0/24'], + routing_instance = ':'.join(self.get_ri_name(vn2_obj)), + service_chain_address = v4_service_chain_address, + service_instance = 'default-domain:default-project:' + service_name) + self.check_service_chain_info(self.get_ri_name(vn1_obj, sc_ri_name), sci) + sci.prefix = ['2000::/16'] + sci.service_chain_address = v6_service_chain_address + self.check_v6_service_chain_info(self.get_ri_name(vn1_obj, sc_ri_name), sci) + + left_ri_fq_name = ['default-domain', 'default-project', vn1_name, sc_ri_name] + right_ri_fq_name = ['default-domain', 'default-project', vn2_name, sc_ri_name] + self.check_service_chain_prefix_match(left_ri_fq_name, prefix='2000::/16') + self.check_service_chain_prefix_match(left_ri_fq_name, prefix='20.0.0.0/24') + self.check_service_chain_prefix_match(right_ri_fq_name, prefix='1000::/16') + self.check_service_chain_prefix_match(right_ri_fq_name, prefix='10.0.0.0/24') + + vn2_obj.del_network_policy(np) + self._vnc_lib.virtual_network_update(vn2_obj) + vn1_obj.del_network_policy(np) + self._vnc_lib.virtual_network_update(vn1_obj) + self._vnc_lib.network_policy_delete(id=np.uuid) + #end test_service_policy_with_v4_v6_subnets # end class TestServicePolicy