diff --git a/src/config/schema-transformer/config_db.py b/src/config/schema-transformer/config_db.py index 79387a8bef5..8c8656a03e5 100644 --- a/src/config/schema-transformer/config_db.py +++ b/src/config/schema-transformer/config_db.py @@ -217,6 +217,20 @@ def __init__(self, name, obj=None, acl_dict=None): RouteTargetST.locate(rt) else: self.rt_list = set() + import_rt_list = self.obj.get_import_route_target_list() + if import_rt_list: + self.import_rt_list = set(rt_list.get_route_target()) + for rt in self.import_rt_list: + RouteTargetST.locate(rt) + else: + self.import_rt_list = set() + export_rt_list = self.obj.get_export_route_target_list() + if export_rt_list: + self.export_rt_list = set(rt_list.get_route_target()) + for rt in self.export_rt_list: + RouteTargetST.locate(rt) + else: + self.export_rt_list = set() self._route_target = None self.route_tables = set() self.routes = {} @@ -272,7 +286,7 @@ def update(self, obj=None): prop = self.obj.get_virtual_network_properties( ) or VirtualNetworkType() self.set_properties(prop) - self.set_route_target_list(self.obj.get_route_target_list()) + self.set_route_target_list(self.obj) mpsce = self.obj.get_multi_policy_service_chains_enabled() if mpsce != self.multi_policy_service_chains_enabled: self.multi_policy_service_chains_enabled = mpsce @@ -361,8 +375,8 @@ def update_autonomous_system(self, new_asn): left_ri = self._get_routing_instance_from_route(nexthop) if left_ri is None: continue - left_ri.update_route_target_list([new_rtgt_name], [old_rtgt_name], - "import") + left_ri.update_route_target_list(rt_add_import=[new_rtgt_name], + rt_del=[old_rtgt_name]) static_route_entries = left_ri.obj.get_static_route_entries() if static_route_entries is None: continue @@ -591,39 +605,59 @@ def set_properties(self, properties): if self.allow_transit: # if the network is now a transit network, add the VN's # route target to all service RIs - ri.update_route_target_list([self.get_route_target()], [], - import_export='export') + ri.update_route_target_list( + rt_add_export=[self.get_route_target()]) else: # if the network is not a transit network any more, then we # need to delete the route target from service RIs - ri.update_route_target_list([], [self.get_route_target()]) + ri.update_route_target_list(rt_del=[self.get_route_target()]) # end set_properties - def set_route_target_list(self, rt_list): + def set_route_target_list(self, obj): ri = self.get_primary_routing_instance() old_rt_list = self.rt_list + rt_list = obj.get_route_target_list() if rt_list: self.rt_list = set(rt_list.get_route_target()) else: self.rt_list = set() + old_import_rt_list = self.import_rt_list + rt_list = obj.get_import_route_target_list() + if rt_list: + self.import_rt_list = set(rt_list.get_route_target()) + else: + self.import_rt_list = set() + old_export_rt_list = self.export_rt_list + rt_list = obj.get_export_route_target_list() + if rt_list: + self.export_rt_list = set(rt_list.get_route_target()) + else: + self.export_rt_list = set() + rt_add = self.rt_list - old_rt_list - rt_del = old_rt_list - self.rt_list - if len(rt_add) == 0 and len(rt_del) == 0: + rt_add_export = self.export_rt_list - old_export_rt_list + rt_add_import = self.import_rt_list - old_import_rt_list + rt_del = ((old_rt_list - self.rt_list) | + (old_export_rt_list - self.export_rt_list) | + (old_import_rt_list - self.import_rt_list)) + if not (rt_add or rt_add_export or rt_add_import or rt_del): return - for rt in rt_add: + for rt in itertools.chain(rt_add, rt_add_export, rt_add_import): RouteTargetST.locate(rt) - ri.update_route_target_list(rt_add, rt_del) + if ri: + ri.update_route_target_list(rt_add=rt_add, rt_add_import=rt_add_import, + rt_add_export=rt_add_export, rt_del=rt_del) for ri_name in self.routing_instances: if self._ri_needs_external_rt(self.name, ri_name): service_ri = RoutingInstanceST.get(ri_name) - service_ri.update_route_target_list(rt_add, rt_del, - import_export='export') + service_ri.update_route_target_list( + rt_add_export=rt_add|rt_add_export, rt_del=rt_del) for (prefix, nexthop) in self.routes.items(): left_ri = self._get_routing_instance_from_route(nexthop) if left_ri is None: continue - left_ri.update_route_target_list(rt_add, rt_del, - import_export='import') + left_ri.update_route_target_list(rt_add_import=rt_add|rt_add_import, + rt_del=rt_del) static_route_entries = left_ri.obj.get_static_route_entries() update = False for static_route in static_route_entries.get_route() or []: @@ -633,7 +667,7 @@ def set_route_target_list(self, rt_list): if rt in static_route.route_target: static_route.route_target.remove(rt) update = True - for rt in rt_add: + for rt in rt_add | rt_add_import: if rt not in static_route.route_target: static_route.route_target.append(rt) update = True @@ -643,7 +677,7 @@ def set_route_target_list(self, rt_list): if update: left_ri.obj.set_static_route_entries(static_route_entries) self._vnc_lib.routing_instance_update(left_ri.obj) - for rt in rt_del: + for rt in rt_del - (rt_add | rt_add_export | rt_add_import): try: RouteTargetST.delete(rt) except RefsExistError: @@ -698,27 +732,26 @@ def add_route(self, prefix, next_hop): return sc_address = service_info.get_service_chain_address() static_route_entries = left_ri.obj.get_static_route_entries( - ) or StaticRouteEntriesType() + ) or StaticRouteEntriesType() update = False + rt_list = self.rt_list | self.import_rt_list + rt_list.add(self.get_route_target()) for static_route in static_route_entries.get_route() or []: if prefix == static_route.prefix: - for rt in self.rt_list | set([self.get_route_target()]): - if rt not in static_route.route_target: - static_route.route_target.append(rt) - update = True + rt_diff = rt_list - set(static_route.route_target) + if rt_diff: + static_route.route_target.extend(rt_diff) + update = True break else: - rt_list = list(self.rt_list | set([self.get_route_target()])) static_route = StaticRouteType(prefix=prefix, next_hop=sc_address, - route_target=rt_list) + route_target=list(rt_list)) static_route_entries.add_route(static_route) update = True if update: left_ri.obj.set_static_route_entries(static_route_entries) self._vnc_lib.routing_instance_update(left_ri.obj) - left_ri.update_route_target_list( - rt_add=self.rt_list | set([self.get_route_target()]), - import_export="import") + left_ri.update_route_target_list(rt_add_import=rt_list) # end add_route def delete_route(self, prefix): @@ -729,10 +762,9 @@ def delete_route(self, prefix): left_ri = self._get_routing_instance_from_route(next_hop) if left_ri is None: return - left_ri.update_route_target_list(rt_add=set(), - rt_del=self.rt_list | set( - [self.get_route_target()]), - import_export="import") + rt_list = self.rt_list | self.import_rt_list + rt_list.add(self.get_route_target()) + left_ri.update_route_target_list(rt_del=rt_list) update = False static_route_entries = left_ri.obj.get_static_route_entries() if static_route_entries is None: @@ -740,10 +772,10 @@ def delete_route(self, prefix): for static_route in static_route_entries.get_route() or []: if static_route.prefix != prefix: continue - for rt in self.rt_list | set([self.get_route_target()]): - if rt in static_route.route_target: - static_route.route_target.remove(rt) - update = True + rt_diff = set(static_route.route_target) - rt_list + if rt_list & set(static_route.route_target): + static_route.route_target = list(rt_diff) + update = True if static_route.route_target == []: static_route_entries.delete_route(static_route) update = True @@ -1808,9 +1840,18 @@ def locate_route_target(self): self.obj.set_route_target(rtgt_obj, InstanceTargetType()) if inst_tgt_data: for rt in vn.rt_list: - rtgt_obj = RouteTarget(rt) - self.obj.add_route_target(rtgt_obj, inst_tgt_data) - if not self.is_default and vn.allow_transit: + rtgt_obj = RouteTargetST.locate(rt) + self.obj.add_route_target(rtgt_obj.obj, inst_tgt_data) + for rt in vn.export_rt_list: + rtgt_obj = RouteTargetST.locate(rt) + self.obj.add_route_target(rtgt_obj.obj, + InstanceTargetType('export')) + if self.is_default: + for rt in vn.import_rt_list: + rtgt_obj = RouteTargetST.locate(rt) + self.obj.add_route_target( + rtgt_obj.obj, InstanceTargetType('import')) + elif vn.allow_transit: rtgt_obj = RouteTarget(vn._route_target) rinst_obj.add_route_target(rtgt_obj, inst_tgt_data) if not compare_refs(self.obj.get_route_target_refs(), @@ -1897,16 +1938,24 @@ def add_service_info(self, remote_vn, service_instance=None, self.obj.set_ipv6_service_chain_information(v6_info) # end add_service_info - def update_route_target_list(self, rt_add, rt_del=None, - import_export=None): - for rt in rt_add: - rtgt_obj = RouteTargetST.locate(rt).obj - inst_tgt_data = InstanceTargetType(import_export=import_export) - self.obj.add_route_target(rtgt_obj, inst_tgt_data) + def update_route_target_list(self, rt_add=None, rt_add_import=None, + rt_add_export=None, rt_del=None): for rt in rt_del or []: rtgt_obj = RouteTarget(rt) self.obj.del_route_target(rtgt_obj) - if rt_add or rt_del: + for rt in rt_add or []: + rtgt_obj = RouteTargetST.locate(rt).obj + inst_tgt_data = InstanceTargetType(import_export=None) + self.obj.add_route_target(rtgt_obj, inst_tgt_data) + for rt in rt_add_import or []: + rtgt_obj = RouteTargetST.locate(rt).obj + inst_tgt_data = InstanceTargetType(import_export='import') + self.obj.add_route_target(rtgt_obj, inst_tgt_data) + for rt in rt_add_export or []: + rtgt_obj = RouteTargetST.locate(rt).obj + inst_tgt_data = InstanceTargetType(import_export='export') + self.obj.add_route_target(rtgt_obj, inst_tgt_data) + if rt_add or rt_add_export or rt_add_import or rt_del: try: self._vnc_lib.routing_instance_update(self.obj) except NoIdError: @@ -1932,7 +1981,7 @@ def update_static_routes(self, si_name): vn = VirtualNetworkST.get(vn_name) if vn is None: continue - route_targets = route_targets.union(vn.rt_list) + route_targets = route_targets | vn.rt_list | vn.import_rt_list route_targets.add(vn.get_route_target()) for route in route_table.routes: if route.next_hop != si_name: @@ -1944,7 +1993,7 @@ def update_static_routes(self, si_name): all_route_targets != route_targets self.obj.set_static_route_entries(static_routes) - self.update_route_target_list(rt_add=all_route_targets, import_export="import") + self.update_route_target_list(rt_add_import=all_route_targets) # end update_static_routes def delete_obj(self): @@ -2256,11 +2305,10 @@ def _create(self, si_info): if first_node: first_node = False - rt_list = set(vn1_obj.rt_list) + rt_list = vn1_obj.rt_list | vn1_obj.export_rt_list if vn1_obj.allow_transit: rt_list.add(vn1_obj.get_route_target()) - service_ri1.update_route_target_list(rt_list, - import_export='export') + service_ri1.update_route_target_list(rt_add_export=rt_list) mode = si_info[service]['mode'] nat_service = (mode == "in-network-nat") @@ -2295,10 +2343,10 @@ def _create(self, si_info): self._vnc_lib.routing_instance_update(service_ri1.obj) self._vnc_lib.routing_instance_update(service_ri2.obj) - rt_list = set(vn2_obj.rt_list) + rt_list = vn2_obj.rt_list | vn2_obj.export_rt_list if vn2_obj.allow_transit: rt_list.add(vn2_obj.get_route_target()) - service_ri2.update_route_target_list(rt_list, import_export='export') + service_ri2.update_route_target_list(rt_add_export=rt_list) if not vn2_obj.multi_policy_service_chains_enabled: service_ri2.add_connection(vn2_obj.get_primary_routing_instance()) diff --git a/src/config/schema-transformer/test/test_service.py b/src/config/schema-transformer/test/test_service.py index 21b6b7aed5a..9b2b5991abf 100644 --- a/src/config/schema-transformer/test/test_service.py +++ b/src/config/schema-transformer/test/test_service.py @@ -927,6 +927,10 @@ def test_add_delete_route(self): vn = self.create_virtual_network(vn_name, "1.0.0.0/24") rtgt_list = RouteTargetList(route_target=['target:1:1']) vn.set_route_target_list(rtgt_list) + exp_rtgt_list = RouteTargetList(route_target=['target:2:1']) + vn.set_export_route_target_list(exp_rtgt_list) + imp_rtgt_list = RouteTargetList(route_target=['target:3:1']) + vn.set_import_route_target_list(imp_rtgt_list) self._vnc_lib.virtual_network_update(vn) rt = RouteTable("rt1") self._vnc_lib.route_table_create(rt) @@ -959,23 +963,34 @@ def _match_route_table(rtgt_list): self.assertIn(rtgt, route.route_target) ri100 = self._vnc_lib.routing_instance_read( fq_name=self.get_ri_name(vn)) - rt100 = ri100.get_route_target_refs()[0]['to'] - for rt_ref in lri.get_route_target_refs() or []: - if rt100 == rt_ref['to']: - return sc_ri_name, rt100 + rt100 = set(ref['to'][0] for ref in ri100.get_route_target_refs()) + lrt = set(ref['to'][0] for ref in lri.get_route_target_refs() or []) + if rt100 & lrt: + return sc_ri_name, (rt100 & lrt) raise Exception("rt100 route-target ref not found") - sc_ri_name, rt100 = _match_route_table(rtgt_list.get_route_target()) + sc_ri_name, rt100 = _match_route_table(rtgt_list.get_route_target() + + imp_rtgt_list.get_route_target()) rtgt_list.add_route_target('target:1:2') vn.set_route_target_list(rtgt_list) + exp_rtgt_list.add_route_target('target:2:2') + vn.set_export_route_target_list(exp_rtgt_list) + imp_rtgt_list.add_route_target('target:3:2') + vn.set_import_route_target_list(imp_rtgt_list) self._vnc_lib.virtual_network_update(vn) - _match_route_table(rtgt_list.get_route_target()) + _match_route_table(rtgt_list.get_route_target() + + imp_rtgt_list.get_route_target()) rtgt_list.delete_route_target('target:1:1') vn.set_route_target_list(rtgt_list) + exp_rtgt_list.delete_route_target('target:2:1') + vn.set_export_route_target_list(exp_rtgt_list) + imp_rtgt_list.delete_route_target('target:3:1') + vn.set_import_route_target_list(imp_rtgt_list) self._vnc_lib.virtual_network_update(vn) - _match_route_table(rtgt_list.get_route_target()) + _match_route_table(rtgt_list.get_route_target() + + imp_rtgt_list.get_route_target()) routes.set_route([]) rt.set_routes(routes) @@ -991,9 +1006,9 @@ def _match_route_table_cleanup(sc_ri_name, rt100): ri = self._vnc_lib.routing_instance_read( fq_name=self.get_ri_name(lvn)) rt_refs = ri.get_route_target_refs() - for rt_ref in ri.get_route_target_refs() or []: - if rt100 == rt_ref['to']: - raise Exception("rt100 route-target ref found") + rt_set = set(ref['to'][0] for ref in ri.get_route_target_refs() or []) + if rt100 & rt_set: + raise Exception("route-target ref still found: %s" % (rt100 & rt_set)) _match_route_table_cleanup(sc_ri_name, rt100) @@ -2012,34 +2027,47 @@ def test_transit_vn(self): #test external rt rtgt_list = RouteTargetList(route_target=['target:1:1']) vn1_obj.set_route_target_list(rtgt_list) + rtgt_list = RouteTargetList(route_target=['target:2:1']) + vn1_obj.set_export_route_target_list(rtgt_list) vn_props.allow_transit = True vn1_obj.set_virtual_network_properties(vn_props) self._vnc_lib.virtual_network_update(vn1_obj) self.check_rt_in_ri(self.get_ri_name(vn1_obj,sc_ri_name), 'target:64512:8000001', True) self.check_rt_in_ri(self.get_ri_name(vn1_obj,sc_ri_name), 'target:1:1', True) + self.check_rt_in_ri(self.get_ri_name(vn1_obj,sc_ri_name), 'target:2:1', True) #modify external rt rtgt_list = RouteTargetList(route_target=['target:1:2']) vn1_obj.set_route_target_list(rtgt_list) + rtgt_list = RouteTargetList(route_target=['target:2:2']) + vn1_obj.set_export_route_target_list(rtgt_list) self._vnc_lib.virtual_network_update(vn1_obj) self.check_rt_in_ri(self.get_ri_name(vn1_obj,sc_ri_name), 'target:64512:8000001', True) self.check_rt_in_ri(self.get_ri_name(vn1_obj,sc_ri_name), 'target:1:2', True) + self.check_rt_in_ri(self.get_ri_name(vn1_obj,sc_ri_name), 'target:2:2', True) #have more than one external rt rtgt_list = RouteTargetList(route_target=['target:1:1', 'target:1:2']) vn1_obj.set_route_target_list(rtgt_list) + rtgt_list = RouteTargetList(route_target=['target:2:1', 'target:2:2']) + vn1_obj.set_export_route_target_list(rtgt_list) self._vnc_lib.virtual_network_update(vn1_obj) self.check_rt_in_ri(self.get_ri_name(vn1_obj,sc_ri_name), 'target:64512:8000001', True) self.check_rt_in_ri(self.get_ri_name(vn1_obj,sc_ri_name), 'target:1:1', True) self.check_rt_in_ri(self.get_ri_name(vn1_obj,sc_ri_name), 'target:1:2', True) + self.check_rt_in_ri(self.get_ri_name(vn1_obj,sc_ri_name), 'target:2:1', True) + self.check_rt_in_ri(self.get_ri_name(vn1_obj,sc_ri_name), 'target:2:2', True) #unset external rt vn1_obj.set_route_target_list(RouteTargetList()) + vn1_obj.set_export_route_target_list(RouteTargetList()) self._vnc_lib.virtual_network_update(vn1_obj) self.check_rt_in_ri(self.get_ri_name(vn1_obj,sc_ri_name), 'target:64512:8000001', True) self.check_rt_in_ri(self.get_ri_name(vn1_obj,sc_ri_name), 'target:1:1', False) self.check_rt_in_ri(self.get_ri_name(vn1_obj,sc_ri_name), 'target:1:2', False) + self.check_rt_in_ri(self.get_ri_name(vn1_obj,sc_ri_name), 'target:2:1', False) + self.check_rt_in_ri(self.get_ri_name(vn1_obj,sc_ri_name), 'target:2:2', False) vn1_obj.del_network_policy(np) vn2_obj.del_network_policy(np) diff --git a/src/config/schema-transformer/to_bgp.py b/src/config/schema-transformer/to_bgp.py index 9cd683f7dc0..035b699f7e3 100644 --- a/src/config/schema-transformer/to_bgp.py +++ b/src/config/schema-transformer/to_bgp.py @@ -115,10 +115,11 @@ class SchemaTransformer(object): }, 'bgp_as_a_service': { 'self': ['bgp_router'], - 'virtual_machine)interface': ['bgp_router'] + 'virtual_machine_interface': ['bgp_router'] }, 'bgp_router': { 'self': [], + 'bgp_as_a_service': [], }, 'global_system_config': { 'self': [], @@ -610,8 +611,8 @@ def parse_args(args_str): 'logging_conf': '', 'logger_class': None, 'sandesh_send_rate_limit': SandeshSystem.get_sandesh_send_rate_limit(), - 'bgpaas_port_start': '50000', - 'bgpaas_port_end': '50256', + 'bgpaas_port_start': 50000, + 'bgpaas_port_end': 50256, } secopts = { 'use_certs': False, @@ -724,9 +725,9 @@ def parse_args(args_str): parser.add_argument("--rabbit_password", help="password for rabbit") parser.add_argument("--rabbit_ha_mode", action='store_true', help="True if the rabbitmq cluster is mirroring all queue") - parser.add_argument("--bgpaas_port_start", + parser.add_argument("--bgpaas_port_start", type=int, help="Start port for bgp-as-a-service proxy") - parser.add_argument("--bgpaas_port_end", + parser.add_argument("--bgpaas_port_end", type=int, help="End port for bgp-as-a-service proxy") args = parser.parse_args(remaining_argv) diff --git a/src/schema/vnc_cfg.xsd b/src/schema/vnc_cfg.xsd index 0873f2cd761..1c819b4cbed 100644 --- a/src/schema/vnc_cfg.xsd +++ b/src/schema/vnc_cfg.xsd @@ -795,6 +795,14 @@ targetNamespace="http://www.contrailsystems.com/2012/VNC-CONFIG/0"> + + + + + +