Exemple #1
0
def _delete_flip(context, id, address_type):
    filters = {'address_type': address_type, '_deallocated': False}

    flip = db_api.floating_ip_find(context, id=id, scope=db_api.ONE, **filters)
    if not flip:
        raise q_exc.FloatingIpNotFound(id=id)

    current_ports = flip.ports
    if address_type == ip_types.FLOATING:
        if current_ports:
            current_ports = [flip.ports[0]]
    elif address_type == ip_types.SCALING:
        current_ports = flip.ports

    context.session.begin()
    try:
        strategy_name = flip.network.get('ipam_strategy')
        ipam_driver = ipam.IPAM_REGISTRY.get_strategy(strategy_name)
        ipam_driver.deallocate_ip_address(context, flip)

        if current_ports:
            db_api.port_disassociate_ip(context, current_ports, flip)
        if flip.fixed_ips:
            db_api.floating_ip_disassociate_all_fixed_ips(context, flip)

        context.session.commit()
    except Exception:
        context.session.rollback()
        raise

    try:
        driver = registry.DRIVER_REGISTRY.get_driver()
        driver.remove_floating_ip(flip)
    except Exception as e:
        LOG.error('There was an error when trying to delete the floating ip '
                  'on the unicorn API.  The ip has been cleaned up, but '
                  'may need to be handled manually in the unicorn API.  '
                  'Error: %s' % e.message)

    # alexm: Notify from this method because we don't have the flip object
    # in the callers
    billing.notify(context, billing.IP_DISASSOC, flip)
def _delete_flip(context, id, address_type):
    filters = {'address_type': address_type, '_deallocated': False}

    flip = db_api.floating_ip_find(context, id=id, scope=db_api.ONE, **filters)
    if not flip:
        raise q_exc.FloatingIpNotFound(id=id)

    current_ports = flip.ports
    if address_type == ip_types.FLOATING:
        if current_ports:
            current_ports = [flip.ports[0]]
    elif address_type == ip_types.SCALING:
        current_ports = flip.ports

    context.session.begin()
    try:
        strategy_name = flip.network.get('ipam_strategy')
        ipam_driver = ipam.IPAM_REGISTRY.get_strategy(strategy_name)
        ipam_driver.deallocate_ip_address(context, flip)

        if current_ports:
            db_api.port_disassociate_ip(context, current_ports, flip)
        if flip.fixed_ips:
            db_api.floating_ip_disassociate_all_fixed_ips(context, flip)

        context.session.commit()
    except Exception:
        context.session.rollback()
        raise

    try:
        driver = registry.DRIVER_REGISTRY.get_driver()
        driver.remove_floating_ip(flip)
    except Exception as e:
        LOG.error('There was an error when trying to delete the floating ip '
                  'on the unicorn API.  The ip has been cleaned up, but '
                  'may need to be handled manually in the unicorn API.  '
                  'Error: %s' % e.message)

    # alexm: Notify from this method because we don't have the flip object
    # in the callers
    billing.notify(context, billing.IP_DISASSOC, flip)
Exemple #3
0
    def deallocate_ips_by_port(self, context, port=None, **kwargs):
        ips_to_remove = []
        for addr in port["ip_addresses"]:
            if "ip_address" in kwargs:
                ip = kwargs["ip_address"]
                if ip != netaddr.IPAddress(int(addr["address"])):
                    continue

            # Note: only deallocate ip if this is the
            # only port mapped
            ips_to_remove.append(addr)

        port["ip_addresses"] = list(
            set(port["ip_addresses"]) - set(ips_to_remove))

        # NCP-1541: We don't need to track v6 IPs the same way. Also, we can't
        # delete them until we've removed the FK on the assoc record first, so
        # we have to flush the current state of the transaction.
        # NOTE(mdietz): this does increase traffic to the db because we need
        #               to flush, fetch the records again and potentially make
        #               another trip to deallocate each IP, but keeping our
        #               indices smaller probably provides more value than the
        #               cost
        # NOTE(aquillin): For floating IPs associated with the port, we do not
        #                 want to deallocate the IP or disassociate the IP from
        #                 the tenant, instead we will disassociate floating's
        #                 fixed IP address.
        context.session.flush()
        deallocated_ips = []
        flip = None
        for ip in ips_to_remove:
            if ip["address_type"] in (ip_types.FLOATING, ip_types.SCALING):
                flip = ip
            else:
                if len(ip["ports"]) == 0:
                    self.deallocate_ip_address(context, ip)
                    deallocated_ips.append(ip.id)
        if flip:
            if flip.fixed_ips and len(flip.fixed_ips) == 1:
                # This is a FLIP or SCIP that is only associated with one
                # port and fixed_ip, so we can safely just disassociate all
                # and remove the flip from unicorn.
                db_api.floating_ip_disassociate_all_fixed_ips(context, flip)
                # NOTE(blogan): I'm not too happy about having do another
                # flush but some test runs showed inconsistent state based on
                # SQLAlchemy caching.
                context.session.add(flip)
                context.session.flush()
                billing.notify(context, billing.IP_DISASSOC, flip, **kwargs)
                driver = registry.DRIVER_REGISTRY.get_driver()
                driver.remove_floating_ip(flip)
            elif len(flip.fixed_ips) > 1:
                # This is a SCIP and we need to diassociate the one fixed_ip
                # from the SCIP and update unicorn with the remaining
                # ports and fixed_ips
                remaining_fixed_ips = []
                for fix_ip in flip.fixed_ips:
                    if fix_ip.id in deallocated_ips:
                        db_api.floating_ip_disassociate_fixed_ip(
                            context, flip, fix_ip)
                        context.session.add(flip)
                        context.session.flush()
                        billing.notify(context, billing.IP_DISASSOC, flip,
                                       **kwargs)
                    else:
                        remaining_fixed_ips.append(fix_ip)
                port_fixed_ips = {}
                for fix_ip in remaining_fixed_ips:
                    # NOTE(blogan): Since this is the flip's fixed_ips it
                    # should be safe to assume there is only one port
                    # associated with it.
                    remaining_port = fix_ip.ports[0]
                    port_fixed_ips[remaining_port.id] = {
                        'port': remaining_port,
                        'fixed_ip': fix_ip
                    }
                driver = registry.DRIVER_REGISTRY.get_driver()
                driver.update_floating_ip(flip, port_fixed_ips)
Exemple #4
0
    def deallocate_ips_by_port(self, context, port=None, **kwargs):
        ips_to_remove = []
        for addr in port["ip_addresses"]:
            if "ip_address" in kwargs:
                ip = kwargs["ip_address"]
                if ip != netaddr.IPAddress(int(addr["address"])):
                    continue

            # Note: only deallocate ip if this is the
            # only port mapped
            ips_to_remove.append(addr)

        port["ip_addresses"] = list(
            set(port["ip_addresses"]) - set(ips_to_remove))

        # NCP-1541: We don't need to track v6 IPs the same way. Also, we can't
        # delete them until we've removed the FK on the assoc record first, so
        # we have to flush the current state of the transaction.
        # NOTE(mdietz): this does increase traffic to the db because we need
        #               to flush, fetch the records again and potentially make
        #               another trip to deallocate each IP, but keeping our
        #               indices smaller probably provides more value than the
        #               cost
        # NOTE(aquillin): For floating IPs associated with the port, we do not
        #                 want to deallocate the IP or disassociate the IP from
        #                 the tenant, instead we will disassociate floating's
        #                 fixed IP address.
        context.session.flush()
        deallocated_ips = []
        flip = None
        for ip in ips_to_remove:
            if ip["address_type"] in (ip_types.FLOATING, ip_types.SCALING):
                flip = ip
            else:
                if len(ip["ports"]) == 0:
                    self.deallocate_ip_address(context, ip)
                    deallocated_ips.append(ip.id)
        if flip:
            if flip.fixed_ips and len(flip.fixed_ips) == 1:
                # This is a FLIP or SCIP that is only associated with one
                # port and fixed_ip, so we can safely just disassociate all
                # and remove the flip from unicorn.
                db_api.floating_ip_disassociate_all_fixed_ips(context, flip)
                # NOTE(blogan): I'm not too happy about having do another
                # flush but some test runs showed inconsistent state based on
                # SQLAlchemy caching.
                context.session.add(flip)
                context.session.flush()
                notify(context, 'ip.disassociate', flip)
                driver = registry.DRIVER_REGISTRY.get_driver()
                driver.remove_floating_ip(flip)
            elif len(flip.fixed_ips) > 1:
                # This is a SCIP and we need to diassociate the one fixed_ip
                # from the SCIP and update unicorn with the remaining
                # ports and fixed_ips
                remaining_fixed_ips = []
                for fix_ip in flip.fixed_ips:
                    if fix_ip.id in deallocated_ips:
                        db_api.floating_ip_disassociate_fixed_ip(
                            context, flip, fix_ip)
                        context.session.add(flip)
                        context.session.flush()
                        notify(context, 'ip.disassociate', flip)
                    else:
                        remaining_fixed_ips.append(fix_ip)
                port_fixed_ips = {}
                for fix_ip in remaining_fixed_ips:
                    # NOTE(blogan): Since this is the flip's fixed_ips it
                    # should be safe to assume there is only one port
                    # associated with it.
                    remaining_port = fix_ip.ports[0]
                    port_fixed_ips[remaining_port.id] = {
                        'port': remaining_port,
                        'fixed_ip': fix_ip
                    }
                driver = registry.DRIVER_REGISTRY.get_driver()
                driver.update_floating_ip(flip, port_fixed_ips)