From 9d7963d517e030831665d185d5827bebec10c4d0 Mon Sep 17 00:00:00 2001 From: Sachin Bansal Date: Fri, 8 Jan 2016 17:02:38 -0800 Subject: [PATCH] Route aggregate support in schema transformer Added support for route aggregate objects in schema transformer. Schema transformer will watch for route aggregate objects, and when they are linked to a service instance, it will also link it to the corresponding left or right routing instance. Also made route aggregate a child of project similar to routing policy. Change-Id: I22a4def2ed0508b392b8df0156068ed55f0f2d1c Partial-Bug: 1500698 --- src/config/schema-transformer/config_db.py | 75 ++++++++++++++++++- .../schema-transformer/test/test_service.py | 15 ++++ src/config/schema-transformer/to_bgp.py | 4 + src/schema/vnc_cfg.xsd | 4 + 4 files changed, 94 insertions(+), 4 deletions(-) diff --git a/src/config/schema-transformer/config_db.py b/src/config/schema-transformer/config_db.py index ccc94c1ec0e..2d0d05349d7 100644 --- a/src/config/schema-transformer/config_db.py +++ b/src/config/schema-transformer/config_db.py @@ -1244,7 +1244,7 @@ def evaluate(self): for ri_name in self.routing_instances: ri = RoutingInstanceST.get(ri_name) if ri: - ri.update_routing_policy() + ri.update_routing_policy_and_aggregates() # end evaluate def get_prefixes(self, ip_version): @@ -1767,6 +1767,7 @@ def __init__(self, name, obj=None): self.add_to_parent(self.obj) self.route_target = None self.routing_policys = {} + self.route_aggregates = set() if self.obj.get_parent_fq_name() in [common.IP_FABRIC_VN_FQ_NAME, common.LINK_LOCAL_VN_FQ_NAME]: return @@ -1816,7 +1817,7 @@ def _get_service_id_from_ri(name): return ri_name[8:44] # end _get_service_id_from_ri - def update_routing_policy(self): + def update_routing_policy_and_aggregates(self): if not self.service_chain: return sc = ServiceChain.get(self.service_chain) @@ -1830,10 +1831,14 @@ def update_routing_policy(self): rp_dict = dict((rp, attr.get_left_sequence()) for rp, attr in si.routing_policys.items() if attr.get_left_sequence()) + ra_set = set(ra for ra, if_type in si.route_aggregates.items() + if if_type == 'left') elif sc.right_vn == self.virtual_network: rp_dict = dict((rp, attr.get_right_sequence()) for rp, attr in si.routing_policys.items() if attr.get_right_sequence()) + ra_set = set(ra for ra, if_type in si.route_aggregates.items() + if if_type == 'right') else: break for rp_name in self.routing_policys: @@ -1848,7 +1853,16 @@ def update_routing_policy(self): if rp: rp.add_routing_instance(self, seq) self.routing_policys = rp_dict - # end update_routing_policy + for ra_name in self.route_aggregates - ra_set: + ra = RouteAggregateST.get(ra_name) + if ra: + ra.delete_routing_instance(self) + for ra_name in ra_set - self.route_aggregates: + ra = RouteAggregateST.get(ra_name) + if ra: + ra.add_routing_instance(self) + self.route_aggregates = ra_set + # end update_routing_policy_and_aggregates def locate_route_target(self): old_rtgt = self._cassandra.get_route_target(self.name) @@ -2067,7 +2081,12 @@ def delete_obj(self): rp = RoutingPolicyST.get(rp_name) if rp: rp.delete_routing_instance(self.name) + for ra_name in self.route_aggregates: + ra = RouteAggregateST.get(ra_name) + if ra: + ra.delete_routing_instance(self.name) self.routing_policys = {} + self.route_aggregates = set() bgpaas_server_name = self.obj.get_fq_name_str() + ':bgpaas-server' bgpaas_server = BgpRouterST.get(bgpaas_server_name) if bgpaas_server: @@ -3379,11 +3398,14 @@ def __init__(self, name, obj=None): self.left_vn_str = None self.right_vn_str = None self.routing_policys = {} + self.route_aggregates = {} self.update(obj) self.network_policys = NetworkPolicyST.get_by_service_instance(self.name) self.route_tables = RouteTableST.get_by_service_instance(self.name) for ref in self.obj.get_routing_policy_back_refs() or []: self.routing_policys[':'.join(ref['to'])] = ref['attr'] + for ref in self.obj.get_route_aggregate_back_refs() or []: + self.route_aggregate[':'.join(ref['to'])] = ref['attr'].interface_type # end __init__ def update(self, obj=None): @@ -3571,6 +3593,51 @@ def delete_routing_instance(self, ri): 'routing_instance', ri.obj.uuid, None, 'DELETE') self.routing_instances.discard(ri.name) - # end delete_routing_instance # end RoutingPolicyST + +class RouteAggregateST(DBBaseST): + _dict = {} + obj_type = 'route_aggregate' + + def __init__(self, name, obj=None): + self.name = name + self.service_instances = {} + self.routing_instances = set() + self.update(obj) + # end __init__ + + def update(self, obj=None): + self.obj = obj or self.read_vnc_obj(fq_name=self.name) + new_refs = dict((':'.join(ref['to']), ref['attr'].interface_type) + for ref in self.obj.get_service_instance_refs() or []) + for ref in set(self.service_instances.keys()) - set(new_refs.keys()): + si = ServiceInstanceST.get(ref) + if si and self.name in si.route_aggregates: + del si.route_aggregates[self.name] + for ref in set(new_refs.keys()): + si = ServiceInstanceST.get(ref) + if si: + si.route_aggregates[self.name] = new_refs[ref] + self.service_instances = new_refs + self.update_multiple_refs('routing_instance', self.obj) + # end update + + def add_routing_instance(self, ri): + if ri.name in self.routing_instances: + return + self._vnc_lib.ref_update('route_aggregate', self.obj.uuid, + 'routing_instance', ri.obj.uuid, + None, 'ADD') + self.routing_instances.add(ri.name) + # end add_routing_instance + + def delete_routing_instance(self, ri): + if ri.name not in self.routing_instances: + return + self._vnc_lib.ref_update('route_aggregate', self.obj.uuid, + 'routing_instance', ri.obj.uuid, + None, 'DELETE') + self.routing_instances.discard(ri.name) + # end delete_routing_instance +# end RouteAggregateST diff --git a/src/config/schema-transformer/test/test_service.py b/src/config/schema-transformer/test/test_service.py index 2f0918c3ac2..15c1522dda8 100644 --- a/src/config/schema-transformer/test/test_service.py +++ b/src/config/schema-transformer/test/test_service.py @@ -637,6 +637,21 @@ def test_service_policy(self): rp.del_service_instance(si_obj) self._vnc_lib.routing_policy_update(rp) self.wait_to_remove_link(ident_name, ':'.join(self.get_ri_name(vn1_obj, sc_ri_name))) + self._vnc_lib.routing_policy_delete(id=rp.uuid) + + ra = RouteAggregate('ra1') + sit = ServiceInterfaceTag(interface_type='left') + ra.add_service_instance(si_obj, sit) + self._vnc_lib.route_aggregate_create(ra) + self.wait_to_get_object(config_db.RouteAggregateST, + ra.get_fq_name_str()) + ident_name = self.get_obj_imid(ra) + self.wait_to_get_link(ident_name, ':'.join(self.get_ri_name(vn1_obj, sc_ri_name))) + ra.del_service_instance(si_obj) + self._vnc_lib.route_aggregate_update(ra) + self.wait_to_remove_link(ident_name, ':'.join(self.get_ri_name(vn1_obj, sc_ri_name))) + self._vnc_lib.route_aggregate_delete(id=ra.uuid) + vn1_obj.del_network_policy(np) vn2_obj.del_network_policy(np) self._vnc_lib.virtual_network_update(vn1_obj) diff --git a/src/config/schema-transformer/to_bgp.py b/src/config/schema-transformer/to_bgp.py index 09d152a3cf8..91e7eba629a 100644 --- a/src/config/schema-transformer/to_bgp.py +++ b/src/config/schema-transformer/to_bgp.py @@ -88,6 +88,7 @@ class SchemaTransformer(object): 'service_instance': { 'self': ['network_policy'], 'routing_policy': ['network_policy'], + 'route_aggregate': ['network_policy'], 'virtual_machine': ['network_policy'], 'network_policy': ['virtual_machine'] }, @@ -127,6 +128,9 @@ class SchemaTransformer(object): }, 'routing_policy': { 'self': ['service_instance'], + }, + 'route_aggregate': { + 'self': ['service_instance'], } } diff --git a/src/schema/vnc_cfg.xsd b/src/schema/vnc_cfg.xsd index 1ee1ddb75a4..7ad8d648335 100644 --- a/src/schema/vnc_cfg.xsd +++ b/src/schema/vnc_cfg.xsd @@ -1432,6 +1432,10 @@ targetNamespace="http://www.contrailsystems.com/2012/VNC-CONFIG/0"> + + +