Floatingip extension support for nuage plugin
Nuage's VSP supports adding floating-ip which fits nicely with this floatingip extension supported by openstack's neutron. This set of change enables that. Implements: blueprint floatingip-ext-for-nuage-plugin Change-Id: I7178ef0dd170567d0e50035eeed0db2ca33f6c1a
This commit is contained in:
parent
0997238c38
commit
baf36a01e1
@ -0,0 +1,83 @@
|
||||
# Copyright 2014 OpenStack Foundation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
"""nuage_floatingip
|
||||
|
||||
Revision ID: 2db5203cb7a9
|
||||
Revises: 10cd28e692e9
|
||||
Create Date: 2014-05-19 16:39:42.048125
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '2db5203cb7a9'
|
||||
down_revision = '10cd28e692e9'
|
||||
|
||||
migration_for_plugins = [
|
||||
'neutron.plugins.nuage.plugin.NuagePlugin'
|
||||
]
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
from neutron.db import migration
|
||||
|
||||
|
||||
def upgrade(active_plugins=None, options=None):
|
||||
if not migration.should_run(active_plugins, migration_for_plugins):
|
||||
return
|
||||
|
||||
op.create_table(
|
||||
'nuage_floatingip_pool_mapping',
|
||||
sa.Column('fip_pool_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('net_id', sa.String(length=36), nullable=True),
|
||||
sa.Column('router_id', sa.String(length=36), nullable=True),
|
||||
sa.ForeignKeyConstraint(['net_id'], ['networks.id'],
|
||||
ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['router_id'], ['routers.id'],
|
||||
ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('fip_pool_id'),
|
||||
)
|
||||
op.create_table(
|
||||
'nuage_floatingip_mapping',
|
||||
sa.Column('fip_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('router_id', sa.String(length=36), nullable=True),
|
||||
sa.Column('nuage_fip_id', sa.String(length=36), nullable=True),
|
||||
sa.ForeignKeyConstraint(['fip_id'], ['floatingips.id'],
|
||||
ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('fip_id'),
|
||||
)
|
||||
op.rename_table('net_partitions', 'nuage_net_partitions')
|
||||
op.rename_table('net_partition_router_mapping',
|
||||
'nuage_net_partition_router_mapping')
|
||||
op.rename_table('router_zone_mapping', 'nuage_router_zone_mapping')
|
||||
op.rename_table('subnet_l2dom_mapping', 'nuage_subnet_l2dom_mapping')
|
||||
op.rename_table('port_mapping', 'nuage_port_mapping')
|
||||
op.rename_table('routerroutes_mapping', 'nuage_routerroutes_mapping')
|
||||
|
||||
|
||||
def downgrade(active_plugins=None, options=None):
|
||||
if not migration.should_run(active_plugins, migration_for_plugins):
|
||||
return
|
||||
|
||||
op.drop_table('nuage_floatingip_mapping')
|
||||
op.drop_table('nuage_floatingip_pool_mapping')
|
||||
op.rename_table('nuage_net_partitions', 'net_partitions')
|
||||
op.rename_table('nuage_net_partition_router_mapping',
|
||||
'net_partition_router_mapping')
|
||||
op.rename_table('nuage_router_zone_mapping', 'router_zone_mapping')
|
||||
op.rename_table('nuage_subnet_l2dom_mapping', 'subnet_l2dom_mapping')
|
||||
op.rename_table('nuage_port_mapping', 'port_mapping')
|
||||
op.rename_table('nuage_routerroutes_mapping', 'routerroutes_mapping')
|
@ -1 +1 @@
|
||||
10cd28e692e9
|
||||
2db5203cb7a9
|
@ -24,3 +24,5 @@ AUTO_CREATE_PORT_OWNERS = [
|
||||
]
|
||||
|
||||
NOVA_PORT_OWNER_PREF = 'compute:'
|
||||
|
||||
SR_TYPE_FLOATING = "FLOATING"
|
||||
|
@ -22,16 +22,16 @@ from neutron.db import models_v2
|
||||
|
||||
|
||||
class NetPartition(model_base.BASEV2, models_v2.HasId):
|
||||
__tablename__ = 'net_partitions'
|
||||
__tablename__ = 'nuage_net_partitions'
|
||||
name = Column(String(64))
|
||||
l3dom_tmplt_id = Column(String(36))
|
||||
l2dom_tmplt_id = Column(String(36))
|
||||
|
||||
|
||||
class NetPartitionRouter(model_base.BASEV2):
|
||||
__tablename__ = "net_partition_router_mapping"
|
||||
__tablename__ = "nuage_net_partition_router_mapping"
|
||||
net_partition_id = Column(String(36),
|
||||
ForeignKey('net_partitions.id',
|
||||
ForeignKey('nuage_net_partitions.id',
|
||||
ondelete="CASCADE"),
|
||||
primary_key=True)
|
||||
router_id = Column(String(36),
|
||||
@ -41,7 +41,7 @@ class NetPartitionRouter(model_base.BASEV2):
|
||||
|
||||
|
||||
class RouterZone(model_base.BASEV2):
|
||||
__tablename__ = "router_zone_mapping"
|
||||
__tablename__ = "nuage_router_zone_mapping"
|
||||
router_id = Column(String(36),
|
||||
ForeignKey('routers.id', ondelete="CASCADE"),
|
||||
primary_key=True)
|
||||
@ -51,12 +51,12 @@ class RouterZone(model_base.BASEV2):
|
||||
|
||||
|
||||
class SubnetL2Domain(model_base.BASEV2):
|
||||
__tablename__ = 'subnet_l2dom_mapping'
|
||||
__tablename__ = 'nuage_subnet_l2dom_mapping'
|
||||
subnet_id = Column(String(36),
|
||||
ForeignKey('subnets.id', ondelete="CASCADE"),
|
||||
primary_key=True)
|
||||
net_partition_id = Column(String(36),
|
||||
ForeignKey('net_partitions.id',
|
||||
ForeignKey('nuage_net_partitions.id',
|
||||
ondelete="CASCADE"))
|
||||
nuage_subnet_id = Column(String(36))
|
||||
nuage_l2dom_tmplt_id = Column(String(36))
|
||||
@ -65,7 +65,7 @@ class SubnetL2Domain(model_base.BASEV2):
|
||||
|
||||
|
||||
class PortVPortMapping(model_base.BASEV2):
|
||||
__tablename__ = 'port_mapping'
|
||||
__tablename__ = 'nuage_port_mapping'
|
||||
port_id = Column(String(36),
|
||||
ForeignKey('ports.id', ondelete="CASCADE"),
|
||||
primary_key=True)
|
||||
@ -75,10 +75,28 @@ class PortVPortMapping(model_base.BASEV2):
|
||||
|
||||
|
||||
class RouterRoutesMapping(model_base.BASEV2, models_v2.Route):
|
||||
__tablename__ = 'routerroutes_mapping'
|
||||
__tablename__ = 'nuage_routerroutes_mapping'
|
||||
router_id = Column(String(36),
|
||||
ForeignKey('routers.id',
|
||||
ondelete="CASCADE"),
|
||||
primary_key=True,
|
||||
nullable=False)
|
||||
nuage_route_id = Column(String(36))
|
||||
|
||||
|
||||
class FloatingIPPoolMapping(model_base.BASEV2):
|
||||
__tablename__ = "nuage_floatingip_pool_mapping"
|
||||
fip_pool_id = Column(String(36), primary_key=True)
|
||||
net_id = Column(String(36),
|
||||
ForeignKey('networks.id', ondelete="CASCADE"))
|
||||
router_id = Column(String(36))
|
||||
|
||||
|
||||
class FloatingIPMapping(model_base.BASEV2):
|
||||
__tablename__ = 'nuage_floatingip_mapping'
|
||||
fip_id = Column(String(36),
|
||||
ForeignKey('floatingips.id',
|
||||
ondelete="CASCADE"),
|
||||
primary_key=True)
|
||||
router_id = Column(String(36))
|
||||
nuage_fip_id = Column(String(36))
|
||||
|
@ -58,6 +58,10 @@ def update_subnetl2dom_mapping(subnet_l2dom,
|
||||
subnet_l2dom.update(new_dict)
|
||||
|
||||
|
||||
def delete_subnetl2dom_mapping(session, subnet_l2dom):
|
||||
session.delete(subnet_l2dom)
|
||||
|
||||
|
||||
def add_port_vport_mapping(session, port_id, nuage_vport_id,
|
||||
nuage_vif_id, static_ip):
|
||||
port_mapping = nuage_models.PortVPortMapping(port_id=port_id,
|
||||
@ -152,3 +156,47 @@ def add_static_route(session, router_id, nuage_rtr_id,
|
||||
nexthop=nexthop)
|
||||
session.add(staticrt)
|
||||
return staticrt
|
||||
|
||||
|
||||
def add_fip_mapping(session, neutron_fip_id, router_id, nuage_fip_id):
|
||||
fip = nuage_models.FloatingIPMapping(fip_id=neutron_fip_id,
|
||||
router_id=router_id,
|
||||
nuage_fip_id=nuage_fip_id)
|
||||
session.add(fip)
|
||||
return fip
|
||||
|
||||
|
||||
def delete_fip_mapping(session, fip_mapping):
|
||||
session.delete(fip_mapping)
|
||||
|
||||
|
||||
def add_fip_pool_mapping(session, fip_pool_id, net_id, router_id=None):
|
||||
fip_pool_mapping = nuage_models.FloatingIPPoolMapping(
|
||||
fip_pool_id=fip_pool_id,
|
||||
net_id=net_id,
|
||||
router_id=router_id)
|
||||
session.add(fip_pool_mapping)
|
||||
return fip_pool_mapping
|
||||
|
||||
|
||||
def delete_fip_pool_mapping(session, fip_pool_mapping):
|
||||
session.delete(fip_pool_mapping)
|
||||
|
||||
|
||||
def get_fip_pool_by_id(session, id):
|
||||
query = session.query(nuage_models.FloatingIPPoolMapping)
|
||||
return query.filter_by(fip_pool_id=id).first()
|
||||
|
||||
|
||||
def get_fip_pool_from_netid(session, net_id):
|
||||
query = session.query(nuage_models.FloatingIPPoolMapping)
|
||||
return query.filter_by(net_id=net_id).first()
|
||||
|
||||
|
||||
def get_fip_mapping_by_id(session, id):
|
||||
qry = session.query(nuage_models.FloatingIPMapping)
|
||||
return qry.filter_by(fip_id=id).first()
|
||||
|
||||
|
||||
def update_fip_pool_mapping(fip_pool_mapping, new_dict):
|
||||
fip_pool_mapping.update(new_dict)
|
||||
|
@ -33,6 +33,7 @@ from neutron.db import extraroute_db
|
||||
from neutron.db import l3_db
|
||||
from neutron.db import models_v2
|
||||
from neutron.db import quota_db # noqa
|
||||
from neutron.extensions import external_net
|
||||
from neutron.extensions import l3
|
||||
from neutron.extensions import portbindings
|
||||
from neutron.openstack.common import excutils
|
||||
@ -300,11 +301,48 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
self._process_l3_create(context, net, network['network'])
|
||||
return net
|
||||
|
||||
def _validate_update_network(self, context, id, network):
|
||||
req_data = network['network']
|
||||
is_external_set = req_data.get(external_net.EXTERNAL)
|
||||
if not attributes.is_attr_set(is_external_set):
|
||||
return (None, None)
|
||||
neutron_net = self.get_network(context, id)
|
||||
if neutron_net.get(external_net.EXTERNAL) == is_external_set:
|
||||
return (None, None)
|
||||
subnet = self._validate_nuage_sharedresource(context, 'network', id)
|
||||
if subnet and not is_external_set:
|
||||
msg = _('External network with subnets can not be '
|
||||
'changed to non-external network')
|
||||
raise nuage_exc.OperationNotSupported(msg=msg)
|
||||
return (is_external_set, subnet)
|
||||
|
||||
def update_network(self, context, id, network):
|
||||
with context.session.begin(subtransactions=True):
|
||||
is_external_set, subnet = self._validate_update_network(context,
|
||||
id,
|
||||
network)
|
||||
net = super(NuagePlugin, self).update_network(context, id,
|
||||
network)
|
||||
self._process_l3_update(context, net, network['network'])
|
||||
if subnet and is_external_set:
|
||||
subn = subnet[0]
|
||||
subnet_l2dom = nuagedb.get_subnet_l2dom_by_id(context.session,
|
||||
subn['id'])
|
||||
if subnet_l2dom:
|
||||
nuage_subnet_id = subnet_l2dom['nuage_subnet_id']
|
||||
nuage_l2dom_tid = subnet_l2dom['nuage_l2dom_tmplt_id']
|
||||
user_id = subnet_l2dom['nuage_user_id']
|
||||
group_id = subnet_l2dom['nuage_group_id']
|
||||
self.nuageclient.delete_subnet(nuage_subnet_id,
|
||||
nuage_l2dom_tid)
|
||||
self.nuageclient.delete_user(user_id)
|
||||
self.nuageclient.delete_group(group_id)
|
||||
nuagedb.delete_subnetl2dom_mapping(context.session,
|
||||
subnet_l2dom)
|
||||
self._add_nuage_sharedresource(context,
|
||||
subnet[0],
|
||||
id,
|
||||
constants.SR_TYPE_FLOATING)
|
||||
return net
|
||||
|
||||
def delete_network(self, context, id):
|
||||
@ -341,18 +379,46 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
msg = "no-gateway option not supported with subnets"
|
||||
raise nuage_exc.OperationNotSupported(msg=msg)
|
||||
|
||||
def create_subnet(self, context, subnet):
|
||||
def _delete_nuage_sharedresource(self, context, net_id):
|
||||
sharedresource_id = self.nuageclient.delete_nuage_sharedresource(
|
||||
net_id)
|
||||
if sharedresource_id:
|
||||
fip_pool_mapping = nuagedb.get_fip_pool_by_id(context.session,
|
||||
sharedresource_id)
|
||||
if fip_pool_mapping:
|
||||
with context.session.begin(subtransactions=True):
|
||||
nuagedb.delete_fip_pool_mapping(context.session,
|
||||
fip_pool_mapping)
|
||||
|
||||
def _validate_nuage_sharedresource(self, context, resource, net_id):
|
||||
filter = {'network_id': [net_id]}
|
||||
existing_subn = self.get_subnets(context, filters=filter)
|
||||
if len(existing_subn) > 1:
|
||||
msg = _('Only one subnet is allowed per '
|
||||
'external network %s') % net_id
|
||||
raise nuage_exc.OperationNotSupported(msg=msg)
|
||||
return existing_subn
|
||||
|
||||
def _add_nuage_sharedresource(self, context, subnet, net_id, type):
|
||||
net = netaddr.IPNetwork(subnet['cidr'])
|
||||
params = {
|
||||
'neutron_subnet': subnet,
|
||||
'net': net,
|
||||
'type': type
|
||||
}
|
||||
fip_pool_id = self.nuageclient.create_nuage_sharedresource(params)
|
||||
nuagedb.add_fip_pool_mapping(context.session, fip_pool_id, net_id)
|
||||
|
||||
def _create_nuage_sharedresource(self, context, subnet, type):
|
||||
subn = subnet['subnet']
|
||||
net_id = subn['network_id']
|
||||
self._validate_nuage_sharedresource(context, 'subnet', net_id)
|
||||
with context.session.begin(subtransactions=True):
|
||||
subn = super(NuagePlugin, self).create_subnet(context, subnet)
|
||||
self._add_nuage_sharedresource(context, subn, net_id, type)
|
||||
return subn
|
||||
|
||||
if self._network_is_external(context, net_id):
|
||||
return super(NuagePlugin, self).create_subnet(context, subnet)
|
||||
|
||||
self._validate_create_subnet(subn)
|
||||
|
||||
net_partition = self._get_net_partition_for_subnet(context, subnet)
|
||||
neutron_subnet = super(NuagePlugin, self).create_subnet(context,
|
||||
subnet)
|
||||
def _create_nuage_subnet(self, context, neutron_subnet, net_partition):
|
||||
net = netaddr.IPNetwork(neutron_subnet['cidr'])
|
||||
params = {
|
||||
'net_partition': net_partition,
|
||||
@ -372,21 +438,36 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
user_id = nuage_subnet['nuage_userid']
|
||||
group_id = nuage_subnet['nuage_groupid']
|
||||
id = nuage_subnet['nuage_l2domain_id']
|
||||
session = context.session
|
||||
with session.begin(subtransactions=True):
|
||||
nuagedb.add_subnetl2dom_mapping(session,
|
||||
with context.session.begin(subtransactions=True):
|
||||
nuagedb.add_subnetl2dom_mapping(context.session,
|
||||
neutron_subnet['id'],
|
||||
id,
|
||||
net_partition['id'],
|
||||
l2dom_id=l2dom_id,
|
||||
nuage_user_id=user_id,
|
||||
nuage_group_id=group_id)
|
||||
|
||||
def create_subnet(self, context, subnet):
|
||||
subn = subnet['subnet']
|
||||
net_id = subn['network_id']
|
||||
|
||||
if self._network_is_external(context, net_id):
|
||||
return self._create_nuage_sharedresource(
|
||||
context, subnet, constants.SR_TYPE_FLOATING)
|
||||
|
||||
self._validate_create_subnet(subn)
|
||||
|
||||
net_partition = self._get_net_partition_for_subnet(context, subnet)
|
||||
neutron_subnet = super(NuagePlugin, self).create_subnet(context,
|
||||
subnet)
|
||||
self._create_nuage_subnet(context, neutron_subnet, net_partition)
|
||||
return neutron_subnet
|
||||
|
||||
def delete_subnet(self, context, id):
|
||||
subnet = self.get_subnet(context, id)
|
||||
if self._network_is_external(context, subnet['network_id']):
|
||||
return super(NuagePlugin, self).delete_subnet(context, id)
|
||||
super(NuagePlugin, self).delete_subnet(context, id)
|
||||
return self._delete_nuage_sharedresource(context, id)
|
||||
|
||||
subnet_l2dom = nuagedb.get_subnet_l2dom_by_id(context.session, id)
|
||||
if subnet_l2dom:
|
||||
@ -523,6 +604,11 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
with session.begin(subtransactions=True):
|
||||
subnet_l2dom = nuagedb.get_subnet_l2dom_by_id(session,
|
||||
subnet_id)
|
||||
if not subnet_l2dom:
|
||||
return super(NuagePlugin,
|
||||
self).remove_router_interface(context,
|
||||
router_id,
|
||||
interface_info)
|
||||
nuage_subn_id = subnet_l2dom['nuage_subnet_id']
|
||||
if self.nuageclient.vms_on_l2domain(nuage_subn_id):
|
||||
msg = (_("Subnet %s has one or more active VMs "
|
||||
@ -727,7 +813,6 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
if net_partition:
|
||||
with session.begin(subtransactions=True):
|
||||
nuagedb.delete_net_partition(session, net_partition)
|
||||
|
||||
self._create_net_partition(session, default_net_part)
|
||||
|
||||
def create_net_partition(self, context, net_partition):
|
||||
@ -767,3 +852,146 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
fields=fields)
|
||||
return [self._make_net_partition_dict(net_partition, fields)
|
||||
for net_partition in net_partitions]
|
||||
|
||||
def _check_floatingip_update(self, context, port):
|
||||
filter = {'fixed_port_id': [port['id']]}
|
||||
local_fip = self.get_floatingips(context,
|
||||
filters=filter)
|
||||
if local_fip:
|
||||
fip = local_fip[0]
|
||||
self._create_update_floatingip(context,
|
||||
fip, port['id'])
|
||||
|
||||
def _create_update_floatingip(self, context,
|
||||
neutron_fip, port_id):
|
||||
rtr_id = neutron_fip['router_id']
|
||||
net_id = neutron_fip['floating_network_id']
|
||||
|
||||
fip_pool_mapping = nuagedb.get_fip_pool_from_netid(context.session,
|
||||
net_id)
|
||||
fip_mapping = nuagedb.get_fip_mapping_by_id(context.session,
|
||||
neutron_fip['id'])
|
||||
|
||||
if not fip_mapping:
|
||||
ent_rtr_mapping = nuagedb.get_ent_rtr_mapping_by_rtrid(
|
||||
context.session, rtr_id)
|
||||
if not ent_rtr_mapping:
|
||||
msg = _('router %s is not associated with '
|
||||
'any net-partition') % rtr_id
|
||||
raise n_exc.BadRequest(resource='floatingip',
|
||||
msg=msg)
|
||||
params = {
|
||||
'nuage_rtr_id': ent_rtr_mapping['nuage_router_id'],
|
||||
'nuage_fippool_id': fip_pool_mapping['fip_pool_id'],
|
||||
'neutron_fip_ip': neutron_fip['floating_ip_address']
|
||||
}
|
||||
nuage_fip_id = self.nuageclient.create_nuage_floatingip(params)
|
||||
nuagedb.add_fip_mapping(context.session,
|
||||
neutron_fip['id'],
|
||||
rtr_id, nuage_fip_id)
|
||||
else:
|
||||
if rtr_id != fip_mapping['router_id']:
|
||||
msg = _('Floating IP can not be associated to VM in '
|
||||
'different router context')
|
||||
raise nuage_exc.OperationNotSupported(msg=msg)
|
||||
nuage_fip_id = fip_mapping['nuage_fip_id']
|
||||
|
||||
fip_pool_dict = {'router_id': neutron_fip['router_id']}
|
||||
nuagedb.update_fip_pool_mapping(fip_pool_mapping,
|
||||
fip_pool_dict)
|
||||
|
||||
# Update VM if required
|
||||
port_mapping = nuagedb.get_port_mapping_by_id(context.session,
|
||||
port_id)
|
||||
if port_mapping:
|
||||
params = {
|
||||
'nuage_vport_id': port_mapping['nuage_vport_id'],
|
||||
'nuage_fip_id': nuage_fip_id
|
||||
}
|
||||
self.nuageclient.update_nuage_vm_vport(params)
|
||||
|
||||
def create_floatingip(self, context, floatingip):
|
||||
fip = floatingip['floatingip']
|
||||
with context.session.begin(subtransactions=True):
|
||||
neutron_fip = super(NuagePlugin, self).create_floatingip(
|
||||
context, floatingip)
|
||||
if not neutron_fip['router_id']:
|
||||
return neutron_fip
|
||||
try:
|
||||
self._create_update_floatingip(context, neutron_fip,
|
||||
fip['port_id'])
|
||||
except (nuage_exc.OperationNotSupported, n_exc.BadRequest):
|
||||
with excutils.save_and_reraise_exception():
|
||||
super(NuagePlugin, self).delete_floatingip(
|
||||
context, neutron_fip['id'])
|
||||
return neutron_fip
|
||||
|
||||
def disassociate_floatingips(self, context, port_id):
|
||||
super(NuagePlugin, self).disassociate_floatingips(context, port_id)
|
||||
port_mapping = nuagedb.get_port_mapping_by_id(context.session,
|
||||
port_id)
|
||||
if port_mapping:
|
||||
params = {
|
||||
'nuage_vport_id': port_mapping['nuage_vport_id'],
|
||||
'nuage_fip_id': None
|
||||
}
|
||||
self.nuageclient.update_nuage_vm_vport(params)
|
||||
|
||||
def update_floatingip(self, context, id, floatingip):
|
||||
fip = floatingip['floatingip']
|
||||
orig_fip = self._get_floatingip(context, id)
|
||||
port_id = orig_fip['fixed_port_id']
|
||||
with context.session.begin(subtransactions=True):
|
||||
neutron_fip = super(NuagePlugin, self).update_floatingip(
|
||||
context, id, floatingip)
|
||||
if fip['port_id'] is not None:
|
||||
if not neutron_fip['router_id']:
|
||||
ret_msg = 'floating-ip is not associated yet'
|
||||
raise n_exc.BadRequest(resource='floatingip',
|
||||
msg=ret_msg)
|
||||
|
||||
try:
|
||||
self._create_update_floatingip(context,
|
||||
neutron_fip,
|
||||
fip['port_id'])
|
||||
except nuage_exc.OperationNotSupported:
|
||||
with excutils.save_and_reraise_exception():
|
||||
super(NuagePlugin,
|
||||
self).disassociate_floatingips(context,
|
||||
fip['port_id'])
|
||||
except n_exc.BadRequest:
|
||||
with excutils.save_and_reraise_exception():
|
||||
super(NuagePlugin, self).delete_floatingip(context,
|
||||
id)
|
||||
else:
|
||||
port_mapping = nuagedb.get_port_mapping_by_id(context.session,
|
||||
port_id)
|
||||
if port_mapping:
|
||||
params = {
|
||||
'nuage_vport_id': port_mapping['nuage_vport_id'],
|
||||
'nuage_fip_id': None
|
||||
}
|
||||
self.nuageclient.update_nuage_vm_vport(params)
|
||||
return neutron_fip
|
||||
|
||||
def delete_floatingip(self, context, id):
|
||||
fip = self._get_floatingip(context, id)
|
||||
port_id = fip['fixed_port_id']
|
||||
with context.session.begin(subtransactions=True):
|
||||
if port_id:
|
||||
port_mapping = nuagedb.get_port_mapping_by_id(context.session,
|
||||
port_id)
|
||||
if (port_mapping and
|
||||
port_mapping['nuage_vport_id'] is not None):
|
||||
params = {
|
||||
'nuage_vport_id': port_mapping['nuage_vport_id'],
|
||||
'nuage_fip_id': None
|
||||
}
|
||||
self.nuageclient.update_nuage_vm_vport(params)
|
||||
fip_mapping = nuagedb.get_fip_mapping_by_id(context.session,
|
||||
id)
|
||||
if fip_mapping:
|
||||
self.nuageclient.delete_nuage_floatingip(
|
||||
fip_mapping['nuage_fip_id'])
|
||||
nuagedb.delete_fip_mapping(context.session, fip_mapping)
|
||||
super(NuagePlugin, self).delete_floatingip(context, id)
|
||||
|
@ -14,7 +14,7 @@
|
||||
#
|
||||
# @author: Ronak Shah, Aniket Dandekar, Nuage Networks, Alcatel-Lucent USA Inc.
|
||||
|
||||
import uuid
|
||||
from neutron.openstack.common import uuidutils
|
||||
|
||||
|
||||
class FakeNuageClient(object):
|
||||
@ -30,10 +30,10 @@ class FakeNuageClient(object):
|
||||
|
||||
def create_subnet(self, neutron_subnet, params):
|
||||
nuage_subnet = {
|
||||
'nuage_l2template_id': str(uuid.uuid4()),
|
||||
'nuage_userid': str(uuid.uuid4()),
|
||||
'nuage_groupid': str(uuid.uuid4()),
|
||||
'nuage_l2domain_id': str(uuid.uuid4())
|
||||
'nuage_l2template_id': uuidutils.generate_uuid(),
|
||||
'nuage_userid': uuidutils.generate_uuid(),
|
||||
'nuage_groupid': uuidutils.generate_uuid(),
|
||||
'nuage_l2domain_id': uuidutils.generate_uuid()
|
||||
}
|
||||
return nuage_subnet
|
||||
|
||||
@ -42,10 +42,10 @@ class FakeNuageClient(object):
|
||||
|
||||
def create_router(self, neutron_router, router, params):
|
||||
nuage_router = {
|
||||
'nuage_userid': str(uuid.uuid4()),
|
||||
'nuage_groupid': str(uuid.uuid4()),
|
||||
'nuage_domain_id': str(uuid.uuid4()),
|
||||
'nuage_def_zone_id': str(uuid.uuid4()),
|
||||
'nuage_userid': uuidutils.generate_uuid(),
|
||||
'nuage_groupid': uuidutils.generate_uuid(),
|
||||
'nuage_domain_id': uuidutils.generate_uuid(),
|
||||
'nuage_def_zone_id': uuidutils.generate_uuid(),
|
||||
}
|
||||
return nuage_router
|
||||
|
||||
@ -66,9 +66,9 @@ class FakeNuageClient(object):
|
||||
|
||||
def create_net_partition(self, params):
|
||||
fake_net_partition = {
|
||||
'nuage_entid': str(uuid.uuid4()),
|
||||
'l3dom_id': str(uuid.uuid4()),
|
||||
'l2dom_id': str(uuid.uuid4()),
|
||||
'nuage_entid': uuidutils.generate_uuid(),
|
||||
'l3dom_id': uuidutils.generate_uuid(),
|
||||
'l2dom_id': uuidutils.generate_uuid(),
|
||||
}
|
||||
return fake_net_partition
|
||||
|
||||
@ -85,7 +85,22 @@ class FakeNuageClient(object):
|
||||
pass
|
||||
|
||||
def create_nuage_staticroute(self, params):
|
||||
return str(uuid.uuid4())
|
||||
return uuidutils.generate_uuid()
|
||||
|
||||
def delete_nuage_staticroute(self, id):
|
||||
pass
|
||||
|
||||
def create_nuage_sharedresource(self, params):
|
||||
return uuidutils.generate_uuid()
|
||||
|
||||
def delete_nuage_sharedresource(self, id):
|
||||
pass
|
||||
|
||||
def create_nuage_floatingip(self, params):
|
||||
return uuidutils.generate_uuid()
|
||||
|
||||
def delete_nuage_floatingip(self, id):
|
||||
pass
|
||||
|
||||
def update_nuage_vm_vport(self, params):
|
||||
pass
|
||||
|
@ -14,12 +14,14 @@
|
||||
#
|
||||
# @author: Ronak Shah, Aniket Dandekar, Nuage Networks, Alcatel-Lucent USA Inc.
|
||||
|
||||
import contextlib
|
||||
import os
|
||||
|
||||
import mock
|
||||
from oslo.config import cfg
|
||||
from webob import exc
|
||||
|
||||
from neutron.extensions import external_net
|
||||
from neutron.extensions import portbindings
|
||||
from neutron.plugins.nuage import extensions
|
||||
from neutron.plugins.nuage import plugin as nuage_plugin
|
||||
@ -67,6 +69,83 @@ class NuagePluginV2TestCase(test_db_plugin.NeutronDbPluginV2TestCase):
|
||||
super(NuagePluginV2TestCase, self).setUp(plugin=plugin,
|
||||
ext_mgr=ext_mgr)
|
||||
|
||||
def _assert_no_assoc_fip(self, fip):
|
||||
body = self._show('floatingips',
|
||||
fip['floatingip']['id'])
|
||||
self.assertIsNone(body['floatingip']['port_id'])
|
||||
self.assertIsNone(
|
||||
body['floatingip']['fixed_ip_address'])
|
||||
|
||||
def _associate_and_assert_fip(self, fip, port, allow=True):
|
||||
port_id = port['port']['id']
|
||||
ip_address = (port['port']['fixed_ips']
|
||||
[0]['ip_address'])
|
||||
if allow:
|
||||
body = self._update(
|
||||
'floatingips', fip['floatingip']['id'],
|
||||
{'floatingip': {'port_id': port_id}})
|
||||
self.assertEqual(
|
||||
body['floatingip']['port_id'], port_id)
|
||||
self.assertEqual(
|
||||
body['floatingip']['fixed_ip_address'],
|
||||
ip_address)
|
||||
return body['floatingip']['router_id']
|
||||
else:
|
||||
code = exc.HTTPInternalServerError.code
|
||||
self._update(
|
||||
'floatingips', fip['floatingip']['id'],
|
||||
{'floatingip': {'port_id': port_id}},
|
||||
expected_code=code)
|
||||
|
||||
def _test_floatingip_update_different_router(self):
|
||||
with contextlib.nested(self.subnet(cidr='10.0.0.0/24'),
|
||||
self.subnet(cidr='10.0.1.0/24')) as (
|
||||
s1, s2):
|
||||
with contextlib.nested(self.port(subnet=s1),
|
||||
self.port(subnet=s2)) as (p1, p2):
|
||||
private_sub1 = {'subnet':
|
||||
{'id':
|
||||
p1['port']['fixed_ips'][0]['subnet_id']}}
|
||||
private_sub2 = {'subnet':
|
||||
{'id':
|
||||
p2['port']['fixed_ips'][0]['subnet_id']}}
|
||||
with self.subnet(cidr='12.0.0.0/24') as public_sub:
|
||||
with contextlib.nested(
|
||||
self.floatingip_no_assoc_with_public_sub(
|
||||
private_sub1, public_sub=public_sub),
|
||||
self.floatingip_no_assoc_with_public_sub(
|
||||
private_sub2, public_sub=public_sub)) as (
|
||||
(fip1, r1), (fip2, r2)):
|
||||
|
||||
self._assert_no_assoc_fip(fip1)
|
||||
self._assert_no_assoc_fip(fip2)
|
||||
|
||||
fip1_r1_res = self._associate_and_assert_fip(fip1, p1)
|
||||
self.assertEqual(fip1_r1_res, r1['router']['id'])
|
||||
# The following operation will associate the floating
|
||||
# ip to a different router and should fail
|
||||
self._associate_and_assert_fip(fip1, p2, allow=False)
|
||||
# disassociate fip1
|
||||
self._update(
|
||||
'floatingips', fip1['floatingip']['id'],
|
||||
{'floatingip': {'port_id': None}})
|
||||
fip2_r2_res = self._associate_and_assert_fip(fip2, p2)
|
||||
self.assertEqual(fip2_r2_res, r2['router']['id'])
|
||||
|
||||
def _test_network_update_external_failure(self):
|
||||
with self.router() as r:
|
||||
with self.subnet() as s1:
|
||||
self._set_net_external(s1['subnet']['network_id'])
|
||||
self._add_external_gateway_to_router(
|
||||
r['router']['id'],
|
||||
s1['subnet']['network_id'])
|
||||
self._update('networks', s1['subnet']['network_id'],
|
||||
{'network': {external_net.EXTERNAL: False}},
|
||||
expected_code=exc.HTTPInternalServerError.code)
|
||||
self._remove_external_gateway_from_router(
|
||||
r['router']['id'],
|
||||
s1['subnet']['network_id'])
|
||||
|
||||
|
||||
class TestNuageBasicGet(NuagePluginV2TestCase,
|
||||
test_db_plugin.TestBasicGet):
|
||||
@ -161,7 +240,12 @@ class TestNuagePortsV2(NuagePluginV2TestCase,
|
||||
|
||||
class TestNuageL3NatTestCase(NuagePluginV2TestCase,
|
||||
test_l3_plugin.L3NatDBIntTestCase):
|
||||
pass
|
||||
|
||||
def test_floatingip_update_different_router(self):
|
||||
self._test_floatingip_update_different_router()
|
||||
|
||||
def test_network_update_external_failure(self):
|
||||
self._test_network_update_external_failure()
|
||||
|
||||
|
||||
class TestNuageExtrarouteTestCase(NuagePluginV2TestCase,
|
||||
@ -191,3 +275,9 @@ class TestNuageExtrarouteTestCase(NuagePluginV2TestCase,
|
||||
r['router']['id'],
|
||||
None,
|
||||
p['port']['id'])
|
||||
|
||||
def test_floatingip_update_different_router(self):
|
||||
self._test_floatingip_update_different_router()
|
||||
|
||||
def test_network_update_external_failure(self):
|
||||
self._test_network_update_external_failure()
|
||||
|
Loading…
Reference in New Issue
Block a user