diff --git a/akanda/neutron/plugins/floatingip.py b/akanda/neutron/plugins/floatingip.py new file mode 100644 index 0000000..31d5e39 --- /dev/null +++ b/akanda/neutron/plugins/floatingip.py @@ -0,0 +1,63 @@ +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) diff --git a/akanda/neutron/plugins/nvp_neutron_plugin.py b/akanda/neutron/plugins/nvp_neutron_plugin.py index d370480..3a62d4c 100644 --- a/akanda/neutron/plugins/nvp_neutron_plugin.py +++ b/akanda/neutron/plugins/nvp_neutron_plugin.py @@ -28,6 +28,7 @@ from neutron.plugins.nicira.NeutronPlugin import nicira_db from neutron.plugins.nicira import NeutronPlugin as nvp from akanda.neutron.plugins import decorators as akanda +from akanda.neutron.plugins import floatingip LOG = logging.getLogger("NeutronPlugin") akanda.monkey_patch_ipv6_generator() @@ -75,7 +76,8 @@ class AkandaNvpRpcCallbacks(l3_rpc.L3RpcCallbackMixin, pass -class NvpPluginV2(nvp.NvpPluginV2): +class NvpPluginV2(floatingip.ExplicitFloatingIPAllocationMixin, + nvp.NvpPluginV2): """ NvpPluginV2 is a Neutron plugin that provides L2 Virtual Network functionality using NVP. @@ -136,7 +138,6 @@ class NvpPluginV2(nvp.NvpPluginV2): get_routers = l3_db.L3_NAT_db_mixin.get_routers add_router_interface = l3_db.L3_NAT_db_mixin.add_router_interface remove_router_interface = l3_db.L3_NAT_db_mixin.remove_router_interface - create_floatingip = l3_db.L3_NAT_db_mixin.create_floatingip update_floatingip = l3_db.L3_NAT_db_mixin.update_floatingip delete_floatingip = l3_db.L3_NAT_db_mixin.delete_floatingip get_floatingip = l3_db.L3_NAT_db_mixin.get_floatingip diff --git a/akanda/neutron/plugins/ovs_neutron_plugin.py b/akanda/neutron/plugins/ovs_neutron_plugin.py index b2e1371..30b1dc4 100644 --- a/akanda/neutron/plugins/ovs_neutron_plugin.py +++ b/akanda/neutron/plugins/ovs_neutron_plugin.py @@ -19,10 +19,13 @@ from neutron.plugins.openvswitch import ovs_neutron_plugin from akanda.neutron.plugins import decorators as akanda +from akanda.neutron.plugins import floatingip + akanda.monkey_patch_ipv6_generator() -class OVSNeutronPluginV2(ovs_neutron_plugin.OVSNeutronPluginV2): +class OVSNeutronPluginV2(floatingip.ExplicitFloatingIPAllocationMixin, + ovs_neutron_plugin.OVSNeutronPluginV2): _supported_extension_aliases = ( ovs_neutron_plugin.OVSNeutronPluginV2._supported_extension_aliases + ["dhportforward", "dhaddressgroup", "dhaddressentry",