Example #1
0
    def create_router(self, context, router):
        """Create a new router entry in DB, and create it in vFabric."""
        # create_router can't go in parallel with l3_sync (synchronize)
        # parallelism of router operations
        # shared (S) lock during transaction.
        db_session = db_api.get_writer_session()
        with db_session.begin(subtransactions=True):
            caller_msg = 'create_router %s' % router['router']['name']
            kaloom_db.get_Lock(db_session, kconst.L3_LOCK_NAME, read=True, caller_msg = caller_msg)

            # Add router to the DB
            new_router = super(KaloomL3ServicePlugin, self).create_router(
                context,
                router)
            # create router on the vFabric
            try:
                self.driver.create_router(context, new_router)
                #Add router-id to the KaloomConcurrency table (later use for x/s lock)
                kaloom_db.create_entry_for_Lock(new_router['id'])
                return new_router
            except Exception:
                with excutils.save_and_reraise_exception():
                    super(KaloomL3ServicePlugin, self).delete_router(
                        context,
                        new_router['id']
                    )
Example #2
0
 def sync_router_interfaces(self, routers):
     for r in routers:
         # Sync (vfabric.add_router_interface) can't go in parallel with router operations (on same router)
         # to avoid race condition of creating router--network link.
         # parallelism of router operations (on different router)
         # write (x) lock on "the router" during transaction (supports multiple sync_router_interfaces operations)
         db_session = db_api.get_writer_session()
         with db_session.begin(subtransactions=True):
             try:
                 caller_msg = 'l3_sync_interface on router id=%s name=%s' % (r['id'] , r['name'])
                 kaloom_db.get_Lock(db_session, r['id'], read=False, caller_msg = caller_msg)
             except Exception as e:
                 #no record (router deleted): nothing to sync for the router
                 #lock timeout 
                 LOG.warning("sync_router_interfaces failed to lock router, err:%s", e)
                 continue
             grouped_router_interfaces = self.get_router_interfaces(r)
             for nw_name in grouped_router_interfaces.keys():
                 try:
                     if not self.driver.router_l2node_link_exists(r['id'], r['name'], nw_name):
                         router_interfaces = grouped_router_interfaces[nw_name]
                         for ri in router_interfaces:
                             try:
                                 self.driver.add_router_interface(self, ri)
                             except Exception as e:
                                 LOG.error("sync_router_interfaces failed to add_router_interface msg:%s", e)
                 except Exception as e:
                     LOG.error("sync_router_interfaces failed to check link existence:%s--%s, msg:%s", r['name'], nw_name, e)
Example #3
0
    def synchronize(self):
        """Synchronizes Router DB from Neturon DB with Kaloom Fabric.

        Walks through the Neturon Db and ensures that all the routers
        created in Netuton DB match with Kaloom Fabric. After creating appropriate
        routers, it ensures to add interfaces as well.
        Stranded routers in vFabric get deleted.
        Uses idempotent properties of Kaloom vFabric configuration, which means
        same commands can be repeated.
        """
        # Sync (read from neutron_db and vfabric) can't go in parallel with router operations
        # parallelism of router operations
        # write (x) lock during transaction.
        db_session = db_api.get_writer_session()
        with db_session.begin(subtransactions=True):
            try:
                kaloom_db.get_Lock(db_session, kconst.L3_LOCK_NAME, read=False, caller_msg = 'l3_sync_read')
                routers = directory.get_plugin(plugin_constants.L3).get_routers(nctx.get_admin_context())
                vfabric_routers = self.driver.get_routers()
            except Exception as e:
                LOG.warning(e)
                return
        LOG.info('Syncing Neutron Router DB <-> vFabric')
        self.sync_routers(routers, vfabric_routers)
        self.sync_router_interfaces(routers)
Example #4
0
 def fake_synchronize_read(self, read_time, routers, vfabric_routers):
     db_session = db_api.get_writer_session()
     with db_session.begin(subtransactions=True):
         kaloom_db.get_Lock(db_session,
                            kconst.L3_LOCK_NAME,
                            read=False,
                            caller_msg='l3_sync_read')
         time.sleep(read_time)
         LOG.info(LOG_MESSAGE_READ)
Example #5
0
    def add_router_interface(self, context, router_id, interface_info):
        """Add a subnet of a network to an existing router."""
        router = self.get_router(context, router_id)
        # add_router_interface can't go in parallel with l3_sync_interface on same router
        # parallelism of router operations (on different router)
        # write (x) lock on "the router" during transaction.
        db_session = db_api.get_writer_session()
        with db_session.begin(subtransactions=True):
            caller_msg = 'add_router_interface on router id=%s name=%s' % (router_id, router['name'])
            kaloom_db.get_Lock(db_session, router_id, read=False, caller_msg = caller_msg)
            new_router_ifc = super(KaloomL3ServicePlugin, self).add_router_interface(
                context, router_id, interface_info)

            core = directory.get_plugin()

            # Get network info for the subnet that is being added to the router.
            # Check if the interface information is by port-id or subnet-id
            add_by_port, add_by_sub = self._validate_interface_info(interface_info)
            if add_by_sub:
                subnet = core.get_subnet(context, interface_info['subnet_id'])
                port = core.get_port(context, new_router_ifc['port_id'])
                #port has multiple (ip_address, subnet_id)
                ip_address = self._get_subnet_ip(port['fixed_ips'], interface_info['subnet_id'])
            elif add_by_port:
                port = core.get_port(context, interface_info['port_id'])
                ip_address = port['fixed_ips'][0]['ip_address']
                subnet_id = port['fixed_ips'][0]['subnet_id']
                subnet = core.get_subnet(context, subnet_id)

            # Package all the info needed for vFabric programming
            network_id = subnet['network_id']
            try:
                nw_name = utils._kaloom_nw_name(self.prefix, network_id)
            except n_exc.NetworkNotFound as e:
                LOG.warning('Nothing to do in add_router_interface as no such network=%s, msg:%s', network_id, e)
                return new_router_ifc

            router_info = copy.deepcopy(new_router_ifc)
            router_info['nw_name'] = nw_name
            router_info['ip_address'] = ip_address
            router_info['name'] = router['name']
            router_info['cidr'] = subnet['cidr']
            router_info['gip'] = subnet['gateway_ip']
            router_info['ip_version'] = subnet['ip_version']

            try:
                self.driver.add_router_interface(context, router_info)
                self._update_port_up(context, port['id'])
                return new_router_ifc
            except Exception:
                with excutils.save_and_reraise_exception():
                    super(KaloomL3ServicePlugin, self).remove_router_interface(
                        context,
                        router_id,
                        interface_info)
Example #6
0
    def remove_router_interface(self, context, router_id, interface_info):
        """Remove a subnet of a network from an existing router."""
        router = self.get_router(context, router_id)
        # remove_router_interface can't go in parallel with l3_sync_interface on same router
        # parallelism of router operations (on different router)
        # write (x) lock on "the router" during transaction.
        db_session = db_api.get_writer_session()
        with db_session.begin(subtransactions=True):
            caller_msg = 'remove_router_interface on router id=%s name=%s' % (router_id, router['name'])
            kaloom_db.get_Lock(db_session, router_id, read=False, caller_msg = caller_msg)
            # Get ip_address info for the subnet that is being deleted from the router.
            # Check if the interface information is by port-id or subnet-id
            core = directory.get_plugin()
            add_by_port, add_by_sub = self._validate_interface_info(interface_info)
            if add_by_sub:
                subnet = core.get_subnet(context, interface_info['subnet_id'])
                ip_address = self._get_subnet_ip_from_router_info(router, interface_info['subnet_id'], subnet['network_id'], subnet['gateway_ip'])
            elif add_by_port:
                port = core.get_port(context, interface_info['port_id'])
                ip_address = port['fixed_ips'][0]['ip_address']
                subnet_id = port['fixed_ips'][0]['subnet_id']
                subnet = core.get_subnet(context, subnet_id)

            router_ifc_to_del = (
                super(KaloomL3ServicePlugin, self).remove_router_interface(
                    context,
                    router_id,
                    interface_info)
                )

            # Get network information of the subnet that is being removed
            network_id = subnet['network_id']
            try:
                nw_name = utils._kaloom_nw_name(self.prefix, network_id)
            except n_exc.NetworkNotFound as e:
                LOG.warning('Nothing to do in remove_router_interface as no such network=%s, msg:%s', network_id, e)
                return

            router_info = copy.deepcopy(router_ifc_to_del)
            router_info['nw_name'] = nw_name
            router_info['name'] = router['name']
            router_info['ip_address'] = ip_address
            router_info['ip_version'] = subnet['ip_version']

            try:
                self.driver.remove_router_interface(context, router_info)
                return router_ifc_to_del
            except Exception as e:
                msg = "remove_router_interface (router %s -- IP %s subnet_id %s) failed in vfabric: %s" % (router['name'], ip_address, subnet['id'], e)
                LOG.error(msg)
Example #7
0
    def delete_router(self, context, router_id):
        """Delete an existing router from Kaloom vFabric as well as from the DB."""
        router = self.get_router(context, router_id)
        router_name = utils._kaloom_router_name(self.prefix, router_id, router['name'])
        # delete_router can't go in parallel with l3_sync (synchronize)
        # parallelism of router operations
        # shared (S) lock during transaction.
        db_session = db_api.get_writer_session()
        with db_session.begin(subtransactions=True):
            caller_msg = 'delete_router %s' % router_name
            kaloom_db.get_Lock(db_session, kconst.L3_LOCK_NAME, read=True, caller_msg = caller_msg)

            # Delete on neutron database
            super(KaloomL3ServicePlugin, self).delete_router(context, router_id)

            #delete router-id from the KaloomConcurrency table (no more future x/s lock)
            kaloom_db.delete_entry_for_Lock(router_id)

            # Delete router on the Kaloom vFabric, in case former does not raise exception
            try:
                self.driver.delete_router(context, router_id, router)
            except Exception as e:
                msg = "Failed to delete router %s on Kaloom vFabric, err:%s" % (router_name, e)
                LOG.warning(msg)
Example #8
0
    def update_router(self, context, router_id, router):
        """Update an existing router in DB, and update it in Kaloom vFabric."""

        # Read existing router record from DB
        original_router = self.get_router(context, router_id)

        try:
            r = router['router']
            #support for extra-routes
            new_routes_info = r['routes'] if r.has_key('routes') else None

            #support for external_gateway_info
            external_gateway_info = r['external_gateway_info'] if r.has_key('external_gateway_info') else None

            #support for router re/name
            new_name = r['name'] if r.has_key('name') else None
            #
            if new_routes_info is not None:
                # Update router DB
                new_router = super(KaloomL3ServicePlugin, self).update_router(context, router_id, router)
                # Modify router on the vFabric
                self.driver.update_router_routes_info(context, router_id, 
                                                     original_router, new_routes_info)

            elif external_gateway_info is not None:
                if external_gateway_info == {}: # "unset --external-gateway" get called
                    # "unset --external-gateway" can't go in parallel with l3_sync_interface on same router
                    # parallelism of router operations (on different router)
                    # write (x) lock on "the router" during transaction.
                    db_session = db_api.get_writer_session()
                    with db_session.begin(subtransactions=True):
                        caller_msg = 'unset_external_gateway on router id=%s name=%s' % (router_id, original_router['name'])
                        kaloom_db.get_Lock(db_session, router_id, read=False, caller_msg = caller_msg)
                        new_router = self._unset_external_gateway(context, router_id, router)
                else: # "set --external-gateway" get called
                    network_id = external_gateway_info['network_id']
                    ##Kaloom does not support SNAT
                    if 'enable_snat' not in external_gateway_info.keys() or external_gateway_info['enable_snat'] == True:
                       raise n_exc.BadRequest(resource='router', msg='SNAT not supported in vFabric')
                    # "set --external-gateway" can't go in parallel with l3_sync_interface on same router
                    # parallelism of router operations (on different router)
                    # write (x) lock on "the router" during transaction.
                    db_session = db_api.get_writer_session()
                    with db_session.begin(subtransactions=True):
                        caller_msg = 'set_external_gateway on router id=%s name=%s' % (router_id, original_router['name'])
                        kaloom_db.get_Lock(db_session, router_id, read=False, caller_msg = caller_msg)
                        # Update router DB
                        new_router = super(KaloomL3ServicePlugin, self).update_router(context, router_id, router)
                        # Modify router on the vFabric
                        if len(new_router['external_gateway_info']['external_fixed_ips']) > 0:
                            self._set_external_gateway(context, router_id, network_id,
                                                       original_router, new_router)
            else:
                # Update router DB
                new_router = super(KaloomL3ServicePlugin, self).update_router(context, router_id, router)
                # Modify router on the vFabric
                if new_name is not None and new_name != original_router['name']:
                   ##rename router in vFabric
                   self.driver.update_router(context, router_id,
                                         original_router, new_router)
            return new_router
        except Exception as e:
            #re-raise exception 
            with excutils.save_and_reraise_exception():
               msg = "update_router failed: %s" % (e)
               LOG.error(msg)