from neutron.common import exceptions as q_exc
from neutron.openstack.common import uuidutils
from neutron.api.v2 import attributes
from neutron.db.l3_db import DEVICE_OWNER_FLOATINGIP, FloatingIP


class ExplicitFloatingIPAllocationMixin(object):
    """Overrides methods for managing floating ips

    Should be mixed in before inheriting from
    neutron.db.l3_db.L3_NAT_db_mixin.

    """

    def create_floatingip(self, context, floatingip):
        fip = floatingip['floatingip']
        tenant_id = self._get_tenant_id_for_create(context, fip)
        fip_id = uuidutils.generate_uuid()

        f_net_id = fip['floating_network_id']
        if not self._core_plugin._network_is_external(context, f_net_id):
            msg = _("Network %s is not a valid external network") % f_net_id
            raise q_exc.BadRequest(resource='floatingip', msg=msg)

        with context.session.begin(subtransactions=True):
            # This external port is never exposed to the tenant.
            # it is used purely for internal system and admin use when
            # managing floating IPs.
            external_port = self._core_plugin.create_port(context.elevated(), {
                'port':
                {'tenant_id': '',  # tenant intentionally not set
                 'network_id': f_net_id,
                 'mac_address': attributes.ATTR_NOT_SPECIFIED,
                 'fixed_ips': attributes.ATTR_NOT_SPECIFIED,
                 'admin_state_up': True,
                 'device_id': fip_id,
                 'device_owner': DEVICE_OWNER_FLOATINGIP,
                 'name': ''}})
            # Ensure IP addresses are allocated on external port
            if not external_port['fixed_ips']:
                raise q_exc.ExternalIpAddressExhausted(net_id=f_net_id)

            floating_fixed_ip = external_port['fixed_ips'][0]
            floating_ip_address = floating_fixed_ip['ip_address']
            floatingip_db = FloatingIP(
                id=fip_id,
                tenant_id=tenant_id,
                floating_network_id=fip['floating_network_id'],
                floating_ip_address=floating_ip_address,
                floating_port_id=external_port['id'])
            fip['tenant_id'] = tenant_id
            # Update association with internal port
            # and define external IP address
            self._update_fip_assoc(context, fip,
                                   floatingip_db, external_port)
            context.session.add(floatingip_db)

        router_id = floatingip_db['router_id']
        if router_id:
            self.l3_rpc_notifier.routers_updated(
                context, [router_id],
                'create_floatingip')
        return self._make_floatingip_dict(floatingip_db)

@@ -1,20 +1,58 @@
+from neutron.api.v2 import attributes%0A
 from neutron.common 
@@ -95,144 +95,422 @@
 ron.
-openstack.common import uuidutils%0Afrom neutron.api.v2 import attributes%0Afrom neutron.db.l3_db import DEVICE_OWNER_FLOATINGIP, F
+db.l3_db import DEVICE_OWNER_FLOATINGIP, FloatingIP%0Afrom neutron.openstack.common import uuidutils%0Afrom neutron.openstack.common import log%0A%0Afrom oslo.config import cfg%0A%0A%0ALOG = log.getLogger(__name__)%0A%0Aexplicit_floating_ip_opts = %5B%0A    cfg.MultiStrOpt(%0A        'floatingip_subnet',%0A        default=%5B%5D,%0A        help='UUID(s) of subnet(s) from which floating IPs should be al
 lo
+c
 at
-ingIP
+ed',%0A        required=True,%0A    ),%0A%5D
 %0A%0A%0Ac
@@ -715,53 +715,1062 @@
 def 
-create_floatingip(self, context, floatingip):
+_allocate_floatingip_from_configured_subnets(self, context):%0A        cfg.CONF.register_opts(explicit_floating_ip_opts, group='akanda')%0A        LOG.debug('looking for floating ip on %25s', str(cfg.CONF.akanda.floatingip_subnet))%0A        # NOTE(dhellmann): There may be a better way to do this, but%0A        # the %22filter%22 argument to get_subnets() is not documented so%0A        # who knows.%0A        e_context = context.elevated()%0A        subnets = %5B%0A            self._get_subnet(e_context, unicode(s))%0A            for s in cfg.CONF.akanda.floatingip_subnet%0A        %5D%0A        if not subnets:%0A            LOG.error('config setting akanda.floatingip_subnet missing')%0A            raise q_exc.IpAddressGenerationFailure(net_id='UNKNOWN')%0A        # The base class method _generate_ip() handles the allocation%0A        # ranges and going from one subnet to the next when a network%0A        # is exhausted.%0A        return self._generate_ip(context, subnets)%0A%0A    def create_floatingip(self, context, floatingip):%0A        LOG.debug('create_floatingip %25s', (floatingip,))
 %0A   
@@ -2179,16 +2179,271 @@
 g=msg)%0A%0A
+        # NOTE(dhellmann): Custom%0A        #%0A        # FIXME(dhellmann): This should probably verify that the subnet%0A        # being used is on the network the user requested.%0A        ip_to_use = self._allocate_floatingip_from_configured_subnets(context)%0A%0A
         
@@ -2960,50 +2960,75 @@
     
-'fixed_ips': attributes.ATTR_NOT_SPECIFIED
+# NOTE(dhellmann): Custom%0A                 'fixed_ips': %5Bip_to_use%5D
 ,%0A  

Look for floatingips on configured subnets