Exemplo n.º 1
0
 def update_route_target_list(self,
                              rt_add=None,
                              rt_add_import=None,
                              rt_add_export=None,
                              rt_del=None):
     update = False
     for rt in rt_del or []:
         if rt in self.stale_route_targets:
             self.stale_route_targets.remove(rt)
         rtgt_obj = RouteTarget(rt)
         self.obj.del_route_target(rtgt_obj)
         update = True
     for rt in rt_add or []:
         if rt not in self.stale_route_targets:
             rtgt_obj = ResourceBaseST.get_obj_type_map().get(
                 'route_target').locate(rt).obj
             inst_tgt_data = InstanceTargetType(import_export=None)
             self.obj.add_route_target(rtgt_obj, inst_tgt_data)
             update = True
         else:
             self.stale_route_targets.remove(rt)
     for rt in rt_add_import or []:
         if rt not in self.stale_route_targets:
             rtgt_obj = ResourceBaseST.get_obj_type_map().get(
                 'route_target').locate(rt).obj
             inst_tgt_data = InstanceTargetType(import_export='import')
             self.obj.add_route_target(rtgt_obj, inst_tgt_data)
             update = True
         else:
             self.stale_route_targets.remove(rt)
     for rt in rt_add_export or []:
         if rt not in self.stale_route_targets:
             rtgt_obj = ResourceBaseST.get_obj_type_map().get(
                 'route_target').locate(rt).obj
             inst_tgt_data = InstanceTargetType(import_export='export')
             self.obj.add_route_target(rtgt_obj, inst_tgt_data)
             update = True
         else:
             self.stale_route_targets.remove(rt)
     if update:
         try:
             self._vnc_lib.routing_instance_update(self.obj)
             # update local cache of ri-->rt refs
             self.update_route_targets()
         except NoIdError:
             return
    def import_default_ri_route_target_to_service_ri(self):
        update_ri = False
        if not self.service_chain:
            return update_ri
        sc = ResourceBaseST.get_obj_type_map().get('service_chain').get(
            self.service_chain)
        if sc is None or not sc.created:
            return update_ri
        left_vn = ResourceBaseST.get_obj_type_map().get('virtual_network').get(
            sc.left_vn)
        right_vn = ResourceBaseST.get_obj_type_map().get(
            'virtual_network').get(sc.right_vn)
        if left_vn is None or right_vn is None:
            self._logger.debug("left or right vn not found for RI " +
                               self.name)
            return update_ri

        right_si_name = sc.service_list[-1]
        right_si = ResourceBaseST.get_obj_type_map().get(
            'service_instance').get(right_si_name)
        multi_policy_enabled = (
            left_vn.multi_policy_service_chains_enabled
            and right_vn.multi_policy_service_chains_enabled
            and right_si.get_service_mode() != 'in-network-nat')

        if not multi_policy_enabled:
            return update_ri
        vn = ResourceBaseST.get_obj_type_map().get('virtual_network').get(
            self.virtual_network)
        if sc.left_vn == vn.name:
            si_name = sc.service_list[0]
        elif sc.right_vn == vn.name:
            si_name = sc.service_list[-1]
        else:
            return update_ri
        service_ri_name = vn.get_service_name(sc.name, si_name)
        if service_ri_name == self.name:
            rt = vn.get_route_target()
            if rt not in self.stale_route_targets:
                rt_obj = ResourceBaseST.get_obj_type_map().get(
                    'route_target').get(rt)
                self.obj.add_route_target(rt_obj.obj,
                                          InstanceTargetType('import'))
                update_ri = True
            else:
                self.stale_route_targets.remove(rt)
        return update_ri
Exemplo n.º 3
0
    def update_autonomous_system(cls, new_asn):
        if int(new_asn) == cls._autonomous_system:
            return False
        # From the global route target list, pick ones with the
        # changed ASN, and update the routing instances' referred
        # by the route target

        for route_tgt in list(ResourceBaseST.get_obj_type_map().get(
                'route_target').values()):
            _, asn, target = route_tgt.obj.get_fq_name()[0].split(':')
            if int(asn) != cls.get_autonomous_system():
                continue
            if int(target) < common.get_bgp_rtgt_min_id(asn):
                continue

            asn = cls._autonomous_system
            new_target = target
            if ((new_asn > 0xFFFF) and (asn <= 0xFFFF)
                    or (new_asn <= 0xFFFF and asn > 0xFFFF)):
                ri_fq_name_in_str = cls._object_db.get_ri_from_route_target(
                    int(target), asn)
                if ri_fq_name_in_str is None or ri_fq_name_in_str == '':
                    continue
                # free_route_target has to be called before alloc_route_target.
                # as get_route_target(ri_fq_name) inside free_route_target
                # will return wrong values if this order is changed.
                cls._object_db.free_route_target(ri_fq_name_in_str, asn)
                new_target = cls._object_db.alloc_route_target(
                    ri_fq_name_in_str, new_asn)

            new_rtgt_name = "target:%s:%s" % (new_asn, new_target)
            new_rtgt_obj = ResourceBaseST.get_obj_type_map().get(
                'route_target').locate(new_rtgt_name)
            old_rtgt_name = "target:%d:%s" % (cls._autonomous_system, target)
            old_rtgt_obj = RouteTarget(old_rtgt_name)

            route_tgt.obj = ResourceBaseST.get_obj_type_map().get(
                'route_target').read_vnc_obj(fq_name=[old_rtgt_name],
                                             fields=[
                                                 'logical_router_back_refs',
                                                 'routing_instance_back_refs'
                                             ])

            for ri_ref in route_tgt.obj.get_routing_instance_back_refs() or []:
                rt_inst = ResourceBaseST.get_obj_type_map().get(
                    'routing_instance').get(':'.join(ri_ref['to']))
                if rt_inst:
                    ri = rt_inst.obj
                else:
                    continue
                inst_tgt_data = InstanceTargetType()
                ri.del_route_target(old_rtgt_obj)
                ri.add_route_target(new_rtgt_obj.obj, inst_tgt_data)
                cls._vnc_lib.routing_instance_update(ri)
                # Also, update the static_routes, if any, in the routing
                # instance with the new route target
                static_route_entries = ri.get_static_route_entries()
                if static_route_entries is None:
                    continue
                for static_route in static_route_entries.get_route() or []:
                    if old_rtgt_name in static_route.route_target:
                        static_route.route_target.remove(old_rtgt_name)
                        static_route.route_target.append(new_rtgt_name)
                    ri.set_static_route_entries(static_route_entries)
                    cls._vnc_lib.routing_instance_update(ri)

            # Updating the logical router referred by the route target with
            # new route target.
            for router_ref in route_tgt.obj.get_logical_router_back_refs() \
                    or []:
                lr = ResourceBaseST.get_obj_type_map().get(
                    'logical_router').get(':'.join(router_ref['to']))
                if lr:
                    logical_router = lr.obj
                else:
                    continue
                logical_router.del_route_target(old_rtgt_obj)
                logical_router.add_route_target(new_rtgt_obj.obj)
                cls._vnc_lib.logical_router_update(logical_router)

                # We need to execute this code only in case of SNAT routing.
                # If vxlan_routing is enabled, LR RTs will not have a back_ref
                # to the Routing Instance of all the connected VNs
                proj_obj = ResourceBaseST.get_obj_type_map().get(
                    'logical_router').read_vnc_obj(logical_router.parent_uuid,
                                                   obj_type='project',
                                                   fields=['vxlan_routing'])
                vxlan_routing = proj_obj.get_vxlan_routing()
                if not vxlan_routing:
                    for vn in lr.virtual_networks:
                        vn_obj = ResourceBaseST.get_obj_type_map().get(
                            'virtual_network').get(vn)
                        if vn_obj is not None:
                            ri_obj = vn_obj.get_primary_routing_instance()
                            ri_obj.update_route_target_list(
                                rt_del=[old_rtgt_name], rt_add=[new_rtgt_name])
                lr.route_target = new_rtgt_name

            ResourceBaseST.get_obj_type_map().get(
                'route_target').delete_vnc_obj(old_rtgt_obj.get_fq_name()[0])

        cls._autonomous_system = int(new_asn)
        return True
    def locate_route_target(self):
        old_rtgt = self._object_db.get_route_target(self.name)
        asn = ResourceBaseST.get_obj_type_map().get(
            'global_system_config').get_autonomous_system()
        rtgt_num = self._object_db.alloc_route_target(self.name, asn)

        rt_key = "target:%s:%d" % (asn, rtgt_num)
        rtgt_obj = ResourceBaseST.get_obj_type_map().get(
            'route_target').locate(rt_key).obj
        if self.is_default:
            inst_tgt_data = InstanceTargetType()
        elif ResourceBaseST.get_obj_type_map().get(
                'virtual_network')._ri_needs_external_rt(
                    self.virtual_network, self.name):
            inst_tgt_data = InstanceTargetType(import_export="export")
        else:
            inst_tgt_data = None

        vn = ResourceBaseST.get_obj_type_map().get('virtual_network').get(
            self.virtual_network)
        if vn is None:
            self._logger.error("Parent VN not found for RI: " + self.name)
            return

        try:
            if self.obj.parent_uuid != vn.obj.uuid:
                # Stale object. Delete it.
                self._vnc_lib.routing_instance_delete(id=self.obj.uuid)
                self.obj = None
            else:
                update_ri = False
                self.stale_route_targets = \
                    [':'.join(rt_ref['to']) for rt_ref in
                     self.obj.get_route_target_refs() or []]
                if rt_key not in self.stale_route_targets:
                    self.obj.add_route_target(rtgt_obj, InstanceTargetType())
                    update_ri = True
                else:
                    self.stale_route_targets.remove(rt_key)
                if inst_tgt_data:
                    for rt in vn.rt_list | vn.bgpvpn_rt_list:
                        if rt not in self.stale_route_targets:
                            rtgt_obj = ResourceBaseST.get_obj_type_map().get(
                                'route_target').locate(rt)
                            self.obj.add_route_target(rtgt_obj.obj,
                                                      inst_tgt_data)
                            update_ri = True
                        else:
                            self.stale_route_targets.remove(rt)
                    if self.is_default:
                        for rt in (vn.export_rt_list
                                   | vn.bgpvpn_export_rt_list):
                            if rt not in self.stale_route_targets:
                                rtgt_obj = \
                                    ResourceBaseST.get_obj_type_map().get(
                                        'route_target').locate(rt)
                                self.obj.add_route_target(
                                    rtgt_obj.obj, InstanceTargetType('export'))
                                update_ri = True
                            else:
                                self.stale_route_targets.remove(rt)
                        for rt in (vn.import_rt_list
                                   | vn.bgpvpn_import_rt_list):
                            if rt not in self.stale_route_targets:
                                rtgt_obj = \
                                    ResourceBaseST.get_obj_type_map().get(
                                        'route_target').locate(rt)
                                self.obj.add_route_target(
                                    rtgt_obj.obj, InstanceTargetType('import'))
                                update_ri = True
                            else:
                                self.stale_route_targets.remove(rt)
                    elif vn.allow_transit:
                        if vn.get_route_target() not in \
                                self.stale_route_targets:
                            rtgt_obj = RouteTarget(vn.get_route_target())
                            self.obj.add_route_target(rtgt_obj, inst_tgt_data)
                            update_ri = True
                        else:
                            self.stale_route_targets.remove(
                                vn.get_route_target())
                update_ri |= \
                    self.import_default_ri_route_target_to_service_ri()

                if update_ri:
                    try:
                        self._vnc_lib.routing_instance_update(self.obj)
                    except Exception as e:
                        # error due to inconsistency in db
                        self._logger.error(
                            "Error while updating routing instance: " + str(e))
                    return
        except NoIdError as e:
            self._logger.error("Error while updating routing instance: " +
                               str(e))
            raise

        self.route_target = rt_key
        if self.is_default:
            vn.set_route_target(rt_key)

        asn = ResourceBaseST.get_obj_type_map().get(
            'global_system_config').get_autonomous_system()
        if 0 < old_rtgt < common.get_bgp_rtgt_min_id(asn):
            rt_key = "target:%s:%d" % (asn, old_rtgt)
            ResourceBaseST.get_obj_type_map().get(
                'route_target').delete_vnc_obj(rt_key)
Exemplo n.º 5
0
    def _create(self, si_info):
        self.partially_created = True
        vn1_obj = ResourceBaseST.get_obj_type_map().get(
            'virtual_network').locate(self.left_vn)
        vn2_obj = ResourceBaseST.get_obj_type_map().get(
            'virtual_network').locate(self.right_vn)
        if not vn1_obj or not vn2_obj:
            self.log_error("vn1_obj or vn2_obj is None")
            return

        right_si_name = self.service_list[-1]
        right_si = ResourceBaseST.get_obj_type_map().get(
            'service_instance').get(right_si_name)
        multi_policy_enabled = (
            vn1_obj.multi_policy_service_chains_enabled
            and vn2_obj.multi_policy_service_chains_enabled
            and right_si.get_service_mode() != 'in-network-nat')
        service_ri2 = None
        if not multi_policy_enabled:
            service_ri2 = vn1_obj.get_primary_routing_instance()
            if service_ri2 is None:
                self.log_error("primary ri is None for " + self.left_vn)
                return
        first_node = True

        # first_service_instance variable is used to determine if the
        # service info is for the first service instance in a chain
        first_service_instance = True

        # last_service_instance variable is used to determine if the
        # service info is for the last service instance in a chain,
        # this is useful for reverse direction traffic
        last_service_instance = False
        service_list_length = len(self.service_list)

        for index, service in enumerate(self.service_list):
            if index + 1 == service_list_length:
                last_service_instance = True

            service_name1 = vn1_obj.get_service_name(self.name, service)
            service_name2 = vn2_obj.get_service_name(self.name, service)
            has_pnf = (
                si_info[service]['virtualization_type'] == 'physical-device')
            ri_obj = ResourceBaseST.get_obj_type_map().get(
                'routing_instance').create(service_name1, vn1_obj, has_pnf)
            service_ri1 = ResourceBaseST.get_obj_type_map().get(
                'routing_instance').locate(service_name1, ri_obj)
            if service_ri1 is None:
                self.log_error("service_ri1 is None")
                return
            if service_ri2 is not None:
                service_ri2.add_connection(service_ri1)
            else:
                # add primary ri's target to service ri
                rt_obj = ResourceBaseST.get_obj_type_map().get(
                    'route_target').get(vn1_obj.get_route_target())
                service_ri1.obj.add_route_target(rt_obj.obj,
                                                 InstanceTargetType('import'))
                self._vnc_lib.routing_instance_update(service_ri1.obj)

            mode = si_info[service]['mode']
            nat_service = (mode == "in-network-nat")
            transparent = (mode not in ["in-network", "in-network-nat"])
            self._logger.info("service chain %s: creating %s chain" %
                              (self.name, mode))

            if not nat_service:
                ri_obj = ResourceBaseST.get_obj_type_map().get(
                    'routing_instance').create(service_name2, vn2_obj, has_pnf)
                service_ri2 = ResourceBaseST.get_obj_type_map().get(
                    'routing_instance').locate(service_name2, ri_obj)
                if service_ri2 is None:
                    self.log_error("service_ri2 is None")
                    return
            else:
                service_ri2 = None

            if first_node:
                first_node = False
                rt_list = set(vn1_obj.rt_list)
                if vn1_obj.allow_transit:
                    rt_list.add(vn1_obj.get_route_target())
                service_ri1.update_route_target_list(rt_add_export=rt_list)

            if transparent:
                v4_address, v6_address = vn1_obj.allocate_service_chain_ip(
                    service_name1)
                if v4_address is None and v6_address is None:
                    self.log_error('Cannot allocate service chain ip address')
                    return
                service_ri1.add_service_info(vn2_obj,
                                             service,
                                             v4_address,
                                             v6_address,
                                             service_chain_id=self.name,
                                             head=first_service_instance)
                if service_ri2 and self.direction == "<>":
                    service_ri2.add_service_info(vn1_obj,
                                                 service,
                                                 v4_address,
                                                 v6_address,
                                                 service_chain_id=self.name,
                                                 head=last_service_instance)

            for vm_info in si_info[service]['vm_list']:
                if transparent:
                    result = self.process_transparent_service(
                        vm_info, v4_address, v6_address, service_ri1,
                        service_ri2)
                else:
                    result = self.process_in_network_service(
                        vm_info, service, vn1_obj, vn2_obj, service_ri1,
                        service_ri2, nat_service, first_service_instance,
                        last_service_instance)
                if not result:
                    return
            self._vnc_lib.routing_instance_update(service_ri1.obj)
            if service_ri2:
                self._vnc_lib.routing_instance_update(service_ri2.obj)
            first_service_instance = False

        if service_ri2:
            rt_list = set(vn2_obj.rt_list)
            if vn2_obj.allow_transit:
                rt_list.add(vn2_obj.get_route_target())
            service_ri2.update_route_target_list(rt_add_export=rt_list)

            if not multi_policy_enabled:
                service_ri2.add_connection(
                    vn2_obj.get_primary_routing_instance())
            else:
                # add primary ri's target to service ri
                rt_obj = ResourceBaseST.get_obj_type_map().get(
                    'route_target').get(vn2_obj.get_route_target())
                service_ri2.obj.add_route_target(rt_obj.obj,
                                                 InstanceTargetType('import'))
                self._vnc_lib.routing_instance_update(service_ri2.obj)

        self.created = True
        self.partially_created = False
        self.error_msg = None
        self._object_db.add_service_chain_uuid(self.name,
                                               jsonpickle.encode(self))