Пример #1
0
    def _sync_base(self):
        ctx = context.get_admin_context()
        # Sync Networks
        for network in self.core_plugin.get_networks(ctx):
            mech_context = driver_context.NetworkContext(self.core_plugin, ctx,
                                                         network)
            try:
                self.driver.create_network_postcommit(mech_context)
            except Exception:
                LOG.warn(_LW("Create network postcommit failed for "
                             "network %s"), network['id'])

        # Sync Subnets
        for subnet in self.core_plugin.get_subnets(ctx):
            mech_context = driver_context.SubnetContext(self.core_plugin, ctx,
                                                        subnet)
            try:
                self.driver.create_subnet_postcommit(mech_context)
            except Exception:
                LOG.warn(_LW("Create subnet postcommit failed for"
                             " subnet %s"), subnet['id'])

        # Sync Ports (compute/gateway/dhcp)
        for port in self.core_plugin.get_ports(ctx):
            _, binding = l2_db.get_locked_port_and_binding(ctx.session,
                                                           port['id'])
            network = self.core_plugin.get_network(ctx, port['network_id'])
            mech_context = driver_context.PortContext(self.core_plugin, ctx,
                                                      port, network, binding,
                                                      [])
            try:
                self.driver.create_port_postcommit(mech_context)
            except Exception:
                LOG.warn(_LW("Create port postcommit failed for"
                             " port %s"), port['id'])
Пример #2
0
    def delete_subnet(self, context, id):
        # REVISIT(rkukura) The super(Ml2Plugin, self).delete_subnet()
        # function is not used because it auto-deletes ports from the
        # DB without invoking the derived class's delete_port(),
        # preventing mechanism drivers from being called. This
        # approach should be revisited when the API layer is reworked
        # during icehouse.

        LOG.debug(_("Deleting subnet %s"), id)
        session = context.session
        while True:
            with session.begin(subtransactions=True):
                subnet = self.get_subnet(context, id)
                # Get ports to auto-delete.
                allocated = (session.query(models_v2.IPAllocation).
                             filter_by(subnet_id=id).
                             join(models_v2.Port).
                             filter_by(network_id=subnet['network_id']).
                             with_lockmode('update').all())
                LOG.debug(_("Ports to auto-delete: %s"), allocated)
                only_auto_del = all(not a.port_id or
                                    a.ports.device_owner in db_base_plugin_v2.
                                    AUTO_DELETE_PORT_OWNERS
                                    for a in allocated)
                if not only_auto_del:
                    LOG.debug(_("Tenant-owned ports exist"))
                    raise exc.SubnetInUse(subnet_id=id)

                if not allocated:
                    mech_context = driver_context.SubnetContext(self, context,
                                                                subnet)
                    self.mechanism_manager.delete_subnet_precommit(
                        mech_context)

                    LOG.debug(_("Deleting subnet record"))
                    record = self._get_subnet(context, id)
                    session.delete(record)

                    LOG.debug(_("Committing transaction"))
                    break

            for a in allocated:
                try:
                    self.delete_port(context, a.port_id)
                except Exception:
                    LOG.exception(_("Exception auto-deleting port %s"),
                                  a.port_id)
                    raise

        try:
            self.mechanism_manager.delete_subnet_postcommit(mech_context)
        except ml2_exc.MechanismDriverError:
            # TODO(apech) - One or more mechanism driver failed to
            # delete the subnet.  Ideally we'd notify the caller of
            # the fact that an error occurred.
            LOG.error(_("mechanism_manager.delete_subnet_postcommit failed"))
Пример #3
0
    def _sync_base(self):
        ctx = context.get_admin_context()
        # Sync Networks
        # Unroll to avoid unwanted additions during sync
        networks = [x for x in self.core_plugin.get_networks(ctx)]
        for network in networks:
            if (network['name'].startswith(
                    constants.HOST_SNAT_NETWORK_PREFIX) or
                    constants.APIC_SYNC_NETWORK == network['name']):
                continue

            mech_context = driver_context.NetworkContext(
                self.core_plugin, ctx, network)
            try:
                self.driver.create_network_postcommit(mech_context)
            except aexc.ReservedSynchronizationName as e:
                LOG.debug(e.message)
            except Exception as e:
                LOG.exception(e)

        # Sync Subnets
        subnets = [x for x in self.core_plugin.get_subnets(ctx)]
        for subnet in subnets:
            if constants.HOST_SNAT_POOL in subnet['name']:
                continue
            network = self.core_plugin.get_network(
                ctx, subnet['network_id'])
            mech_context = driver_context.SubnetContext(self.core_plugin, ctx,
                                                        subnet, network)
            try:
                self.driver.create_subnet_postcommit(mech_context)
            except Exception as e:
                LOG.exception(e)

        # Sync Ports (compute/gateway/dhcp)
        ports = [x for x in self.core_plugin.get_ports(ctx)]
        for port in ports:
            if constants.HOST_SNAT_POOL_PORT in port['name']:
                continue
            _, binding = l2_db.get_locked_port_and_binding(ctx.session,
                                                           port['id'])
            levels = l2_db.get_binding_levels(ctx.session, port['id'],
                                              binding.host)
            network = self.core_plugin.get_network(ctx, port['network_id'])
            mech_context = driver_context.PortContext(self.core_plugin, ctx,
                                                      port, network, binding,
                                                      levels)
            try:
                self.driver.create_port_postcommit(mech_context)
            except Exception as e:
                LOG.exception(e)
Пример #4
0
 def delete_subnet(self, context, id):
     session = context.session
     with session.begin(subtransactions=True):
         subnet = self.get_subnet(context, id)
         mech_context = driver_context.SubnetContext(self, context, subnet)
         self.mechanism_manager.delete_subnet_precommit(mech_context)
         super(Ml2Plugin, self).delete_subnet(context, id)
     try:
         self.mechanism_manager.delete_subnet_postcommit(mech_context)
     except ml2_exc.MechanismDriverError:
         # TODO(apech) - One or more mechanism driver failed to
         # delete the subnet.  Ideally we'd notify the caller of
         # the fact that an error occurred.
         pass
Пример #5
0
    def create_subnet(self, context, subnet):
        session = context.session
        with session.begin(subtransactions=True):
            result = super(Ml2Plugin, self).create_subnet(context, subnet)
            mech_context = driver_context.SubnetContext(self, context, result)
            self.mechanism_manager.create_subnet_precommit(mech_context)

        try:
            self.mechanism_manager.create_subnet_postcommit(mech_context)
        except ml2_exc.MechanismDriverError:
            with excutils.save_and_reraise_exception():
                LOG.error(_("mechanism_manager.create_subnet_postcommit "
                            "failed, deleting subnet '%s'"), result['id'])
                self.delete_subnet(context, result['id'])
        return result
Пример #6
0
    def update_subnet(self, context, id, subnet):
        session = context.session
        with session.begin(subtransactions=True):
            original_subnet = super(Ml2Plugin, self).get_subnet(context, id)
            updated_subnet = super(Ml2Plugin, self).update_subnet(
                context, id, subnet)
            mech_context = driver_context.SubnetContext(
                self, context, updated_subnet, original_subnet=original_subnet)
            self.mechanism_manager.update_subnet_precommit(mech_context)

        # TODO(apech) - handle errors raised by update_subnet, potentially
        # by re-calling update_subnet with the previous attributes. For
        # now the error is propogated to the caller, which is expected to
        # either undo/retry the operation or delete the resource.
        self.mechanism_manager.update_subnet_postcommit(mech_context)
        return updated_subnet
Пример #7
0
    def _sync_base(self):
        ctx = context.get_admin_context()
        # Sync Networks
        # Unroll to avoid unwanted additions during sync
        networks = [x for x in self.core_plugin.get_networks(ctx)]
        for network in networks:
            if constants.APIC_SYNC_NETWORK == network['name']:
                continue

            mech_context = driver_context.NetworkContext(
                self.core_plugin, ctx, network)
            try:
                self.driver.create_network_postcommit(mech_context)
            except aexc.ReservedSynchronizationName as e:
                LOG.debug(e.message)
            except Exception as e:
                LOG.warning(_LW("Create network postcommit failed for "
                                "network %(net_id)s: %(message)s"),
                            net_id=network['id'], message=e.message)
        # Sync Subnets
        subnets = [x for x in self.core_plugin.get_subnets(ctx)]
        for subnet in subnets:
            mech_context = driver_context.SubnetContext(self.core_plugin, ctx,
                                                        subnet)
            try:
                self.driver.create_subnet_postcommit(mech_context)
            except Exception as e:
                LOG.warning(_LW("Create subnet postcommit failed for "
                                "subnet %(sub_id)s: %(message)s"),
                            sub_id=subnet['id'], message=e.message)
        # Sync Ports (compute/gateway/dhcp)
        ports = [x for x in self.core_plugin.get_ports(ctx)]
        for port in ports:
            binding = l2_db.get_locked_port_and_binding(ctx.session,
                                                        port['id'])[1]
            levels = l2_db.get_binding_levels(ctx.session, port['id'],
                                              binding.host)
            network = self.core_plugin.get_network(ctx, port['network_id'])
            mech_context = driver_context.PortContext(self.core_plugin, ctx,
                                                      port, network, binding,
                                                      levels)
            try:
                self.driver.create_port_postcommit(mech_context)
            except Exception as e:
                LOG.warning(_LW("Create port postcommit failed for "
                                "port %(port_id)s: %(message)s"),
                            port_id=port['id'], message=e.message)
Пример #8
0
 def filter_create_attributes_with_plugin(cls, subnet, plugin, dbcontext):
     network = plugin.get_network(dbcontext, subnet['network_id'])
     context = driver_context.SubnetContext(plugin, dbcontext, subnet,
                                            network)
     cls.filter_create_attributes(subnet, context)
     cls._filter_unmapped_null(subnet, cls._UNMAPPED_KEYS)
Пример #9
0
 def filter_create_attributes_with_plugin(cls, subnet, plugin, dbcontext):
     network = plugin.get_network(dbcontext, subnet['network_id'])
     context = driver_context.SubnetContext(plugin, dbcontext, subnet,
                                            network)
     cls.filter_create_attributes(subnet, context)
Пример #10
0
    def delete_subnet(self, context, id):
        # REVISIT(rkukura) The super(Ml2Plugin, self).delete_subnet()
        # function is not used because it deallocates the subnet's addresses
        # from ports in the DB without invoking the derived class's
        # update_port(), preventing mechanism drivers from being called.
        # This approach should be revisited when the API layer is reworked
        # during icehouse.

        LOG.debug(_("Deleting subnet %s"), id)
        session = context.session
        while True:
            with session.begin(subtransactions=True):
                subnet = self.get_subnet(context, id)
                # Get ports to auto-deallocate
                allocated = (session.query(models_v2.IPAllocation).filter_by(
                    subnet_id=id).join(models_v2.Port).filter_by(
                        network_id=subnet['network_id']).with_lockmode(
                            'update').all())
                LOG.debug(_("Ports to auto-deallocate: %s"), allocated)
                only_auto_del = all(not a.port_id or a.ports.device_owner in
                                    db_base_plugin_v2.AUTO_DELETE_PORT_OWNERS
                                    for a in allocated)
                if not only_auto_del:
                    LOG.debug(_("Tenant-owned ports exist"))
                    raise exc.SubnetInUse(subnet_id=id)

                if not allocated:
                    mech_context = driver_context.SubnetContext(
                        self, context, subnet)
                    self.mechanism_manager.delete_subnet_precommit(
                        mech_context)

                    LOG.debug(_("Deleting subnet record"))
                    record = self._get_subnet(context, id)
                    session.delete(record)

                    LOG.debug(_("Committing transaction"))
                    break

            for a in allocated:
                if a.port_id:
                    # calling update_port() for each allocation to remove the
                    # IP from the port and call the MechanismDrivers
                    data = {
                        'port': {
                            'fixed_ips': [{
                                'subnet_id': ip.subnet_id,
                                'ip_address': ip.ip_address
                            } for ip in a.ports.fixed_ips
                                          if ip.subnet_id != id]
                        }
                    }
                    try:
                        self.update_port(context, a.port_id, data)
                    except Exception:
                        with excutils.save_and_reraise_exception():
                            LOG.exception(
                                _("Exception deleting fixed_ip from "
                                  "port %s"), a.port_id)
                session.delete(a)

        try:
            self.mechanism_manager.delete_subnet_postcommit(mech_context)
        except ml2_exc.MechanismDriverError:
            # TODO(apech) - One or more mechanism driver failed to
            # delete the subnet.  Ideally we'd notify the caller of
            # the fact that an error occurred.
            LOG.error(_("mechanism_manager.delete_subnet_postcommit failed"))
Пример #11
0
def delete_subnet(self, context, id):
    # REVISIT(rkukura) The super(Ml2Plugin, self).delete_subnet()
    # function is not used because it deallocates the subnet's addresses
    # from ports in the DB without invoking the derived class's
    # update_port(), preventing mechanism drivers from being called.
    # This approach should be revisited when the API layer is reworked
    # during icehouse.

    LOG.debug("Deleting subnet %s", id)
    session = context.session
    attempt = 0
    while True:
        attempt += 1
        LOG.info(i18n._LI("Attempt %(attempt)s to delete subnet %(subnet)s"), {
            'attempt': attempt,
            'subnet': id
        })
        if attempt > 100:
            raise InfiniteLoopError()
        with session.begin(subtransactions=True):
            record = self._get_subnet(context, id)
            subnet = self._make_subnet_dict(record, None, context=context)
            qry_allocated = (session.query(models_v2.IPAllocation).filter_by(
                subnet_id=id).join(models_v2.Port))
            is_auto_addr_subnet = ipv6_utils.is_auto_address_subnet(subnet)
            # Remove network owned ports, and delete IP allocations
            # for IPv6 addresses which were automatically generated
            # via SLAAC
            if is_auto_addr_subnet:
                self._subnet_check_ip_allocations_internal_router_ports(
                    context, id)
            else:
                qry_allocated = (qry_allocated.filter(
                    models_v2.Port.device_owner.in_(
                        db_base_plugin_v2.AUTO_DELETE_PORT_OWNERS)))
            allocated = qry_allocated.all()
            # Delete all the IPAllocation that can be auto-deleted
            if allocated:
                for x in allocated:
                    session.delete(x)
            LOG.debug("Ports to auto-deallocate: %s", allocated)
            # Check if there are more IP allocations, unless
            # is_auto_address_subnet is True. In that case the check is
            # unnecessary. This additional check not only would be wasteful
            # for this class of subnet, but is also error-prone since when
            # the isolation level is set to READ COMMITTED allocations made
            # concurrently will be returned by this query
            if not is_auto_addr_subnet:
                alloc = self._subnet_check_ip_allocations(context, id)
                if alloc:
                    user_alloc = self._subnet_get_user_allocation(context, id)
                    if user_alloc:
                        LOG.info(
                            i18n._LI("Found port (%(port_id)s, %(ip)s) "
                                     "having IP allocation on subnet "
                                     "%(subnet)s, cannot delete"), {
                                         'ip': user_alloc.ip_address,
                                         'port_id': user_alloc.port_id,
                                         'subnet': id
                                     })
                        raise exc.SubnetInUse(subnet_id=id)
                    else:
                        # allocation found and it was DHCP port
                        # that appeared after autodelete ports were
                        # removed - need to restart whole operation
                        raise os_db_exception.RetryRequest(
                            exc.SubnetInUse(subnet_id=id))

            db_base_plugin_v2._check_subnet_not_used(context, id)

            # If allocated is None, then all the IPAllocation were
            # correctly deleted during the previous pass.
            if not allocated:
                network = self.get_network(context, subnet['network_id'])
                mech_context = driver_context.SubnetContext(
                    self, context, subnet, network)
                self.mechanism_manager.delete_subnet_precommit(mech_context)

                LOG.debug("Deleting subnet record")
                session.delete(record)

                # The super(Ml2Plugin, self).delete_subnet() is not called,
                # so need to manually call delete_subnet for pluggable ipam
                self.ipam.delete_subnet(context, id)

                LOG.debug("Committing transaction")
                break

        for a in allocated:
            if a.port:
                # calling update_port() for each allocation to remove the
                # IP from the port and call the MechanismDrivers
                data = {
                    attributes.PORT: {
                        'fixed_ips': [{
                            'subnet_id': ip.subnet_id,
                            'ip_address': ip.ip_address
                        } for ip in a.port.fixed_ips if ip.subnet_id != id]
                    }
                }
                try:
                    self.update_port(context, a.port_id, data)
                except exc.PortNotFound:
                    LOG.debug("Port %s deleted concurrently", a.port_id)
                except Exception:
                    with excutils.save_and_reraise_exception():
                        LOG.exception(
                            i18n._LE("Exception deleting fixed_ip "
                                     "from port %s"), a.port_id)

    try:
        self.mechanism_manager.delete_subnet_postcommit(mech_context)
    except ml2_exc.MechanismDriverError:
        # TODO(apech) - One or more mechanism driver failed to
        # delete the subnet.  Ideally we'd notify the caller of
        # the fact that an error occurred.
        LOG.error(
            i18n._LE("mechanism_manager.delete_subnet_postcommit failed"))
Пример #12
0
 def _get_subnet_context(self, context, network_id, subnet_id):
     plugin = directory.get_plugin()
     network = plugin.get_network(context, network_id)
     subnet = plugin.get_subnet(context, subnet_id)
     return driver_context.SubnetContext(plugin, context, subnet, network)
Пример #13
0
 def filter_create_attributes_with_plugin(cls, subnet, plugin, dbcontext):
     context = driver_context.SubnetContext(subnet, plugin, dbcontext)
     cls.filter_create_attributes(subnet, context)