From 31d67cfdee5b9f1ed77df2c9cda1c849fd7d6181 Mon Sep 17 00:00:00 2001 From: Sayaji Date: Thu, 17 Jul 2014 14:51:58 -0700 Subject: [PATCH] Changes to remove the use of mapping tables from Nuage plugin Nuage plugin maintains a mapping of Openstack and Nuage resources. With this change Nuage VSD can itself maintain this mapping, so the plugin doesn't have to store the information in the neutron DB. This eliminates potential out of sync and upgrade issues. Closes-Bug: #1338853 Change-Id: I03b32a83d792c742962e0195383a622c1967ae4f --- ...322991f59_nuage_removing_mapping_tables.py | 101 +++++ .../alembic_migrations/versions/HEAD | 2 +- neutron/plugins/nuage/nuage_models.py | 92 +---- neutron/plugins/nuage/nuagedb.py | 171 ++------ neutron/plugins/nuage/plugin.py | 382 +++++++++--------- neutron/tests/unit/nuage/fake_nuageclient.py | 48 +++ 6 files changed, 397 insertions(+), 399 deletions(-) create mode 100644 neutron/db/migration/alembic_migrations/versions/37f322991f59_nuage_removing_mapping_tables.py diff --git a/neutron/db/migration/alembic_migrations/versions/37f322991f59_nuage_removing_mapping_tables.py b/neutron/db/migration/alembic_migrations/versions/37f322991f59_nuage_removing_mapping_tables.py new file mode 100644 index 000000000..2c86547e9 --- /dev/null +++ b/neutron/db/migration/alembic_migrations/versions/37f322991f59_nuage_removing_mapping_tables.py @@ -0,0 +1,101 @@ +# 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. +# + +"""removing_mapping_tables + +Revision ID: 37f322991f59 +Revises: 2026156eab2f +Create Date: 2014-07-09 17:25:29.242948 + +""" + +# revision identifiers, used by Alembic. +revision = '37f322991f59' +down_revision = '2026156eab2f' + +# Change to ['*'] if this migration applies to all plugins + +migration_for_plugins = [ + '*' +] + +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.drop_table('nuage_floatingip_mapping') + op.drop_table('nuage_floatingip_pool_mapping') + op.drop_table('nuage_routerroutes_mapping') + op.drop_table('nuage_port_mapping') + op.drop_table('nuage_router_zone_mapping') + + +def downgrade(active_plugins=None, options=None): + if not migration.should_run(active_plugins, migration_for_plugins): + return + + op.create_table( + 'nuage_router_zone_mapping', + sa.Column('router_id', sa.String(length=36), nullable=False), + sa.Column('nuage_zone_id', sa.String(length=36), nullable=True), + sa.Column('nuage_user_id', sa.String(length=36), nullable=True), + sa.Column('nuage_group_id', sa.String(length=36), nullable=True), + sa.ForeignKeyConstraint(['router_id'], ['routers.id'], + ondelete='CASCADE'), + sa.PrimaryKeyConstraint('router_id'), + ) + op.create_table( + 'nuage_port_mapping', + sa.Column('port_id', sa.String(length=36), nullable=False), + sa.Column('nuage_vport_id', sa.String(length=36), nullable=True), + sa.Column('nuage_vif_id', sa.String(length=36), nullable=True), + sa.Column('static_ip', sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint(['port_id'], ['ports.id'], + ondelete='CASCADE'), + sa.PrimaryKeyConstraint('port_id'), + ) + op.create_table( + 'nuage_routerroutes_mapping', + sa.Column('router_id', sa.String(length=36), nullable=False), + sa.Column('nuage_route_id', sa.String(length=36), nullable=True), + sa.ForeignKeyConstraint(['router_id'], ['routers.id'], + ondelete='CASCADE'), + ) + 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'), + ) \ No newline at end of file diff --git a/neutron/db/migration/alembic_migrations/versions/HEAD b/neutron/db/migration/alembic_migrations/versions/HEAD index da886bc55..4bd668eab 100644 --- a/neutron/db/migration/alembic_migrations/versions/HEAD +++ b/neutron/db/migration/alembic_migrations/versions/HEAD @@ -1 +1 @@ -2026156eab2f +37f322991f59 \ No newline at end of file diff --git a/neutron/plugins/nuage/nuage_models.py b/neutron/plugins/nuage/nuage_models.py index f3ebcffa1..4c901cc01 100644 --- a/neutron/plugins/nuage/nuage_models.py +++ b/neutron/plugins/nuage/nuage_models.py @@ -15,7 +15,7 @@ # # @author: Ronak Shah, Nuage Networks, Alcatel-Lucent USA Inc. -from sqlalchemy import Boolean, Column, ForeignKey, String +import sqlalchemy as sa from neutron.db import model_base from neutron.db import models_v2 @@ -23,80 +23,32 @@ from neutron.db import models_v2 class NetPartition(model_base.BASEV2, models_v2.HasId): __tablename__ = 'nuage_net_partitions' - name = Column(String(64)) - l3dom_tmplt_id = Column(String(36)) - l2dom_tmplt_id = Column(String(36)) + name = sa.Column(sa.String(64)) + l3dom_tmplt_id = sa.Column(sa.String(36)) + l2dom_tmplt_id = sa.Column(sa.String(36)) class NetPartitionRouter(model_base.BASEV2): __tablename__ = "nuage_net_partition_router_mapping" - net_partition_id = Column(String(36), - ForeignKey('nuage_net_partitions.id', - ondelete="CASCADE"), - primary_key=True) - router_id = Column(String(36), - ForeignKey('routers.id', ondelete="CASCADE"), - primary_key=True) - nuage_router_id = Column(String(36)) - - -class RouterZone(model_base.BASEV2): - __tablename__ = "nuage_router_zone_mapping" - router_id = Column(String(36), - ForeignKey('routers.id', ondelete="CASCADE"), - primary_key=True) - nuage_zone_id = Column(String(36)) - nuage_user_id = Column(String(36)) - nuage_group_id = Column(String(36)) + net_partition_id = sa.Column(sa.String(36), + sa.ForeignKey('nuage_net_partitions.id', + ondelete="CASCADE"), + primary_key=True) + router_id = sa.Column(sa.String(36), + sa.ForeignKey('routers.id', ondelete="CASCADE"), + primary_key=True) + nuage_router_id = sa.Column(sa.String(36)) class SubnetL2Domain(model_base.BASEV2): __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('nuage_net_partitions.id', - ondelete="CASCADE")) - nuage_subnet_id = Column(String(36)) - nuage_l2dom_tmplt_id = Column(String(36)) - nuage_user_id = Column(String(36)) - nuage_group_id = Column(String(36)) - - -class PortVPortMapping(model_base.BASEV2): - __tablename__ = 'nuage_port_mapping' - port_id = Column(String(36), - ForeignKey('ports.id', ondelete="CASCADE"), - primary_key=True) - nuage_vport_id = Column(String(36)) - nuage_vif_id = Column(String(36)) - static_ip = Column(Boolean()) - - -class RouterRoutesMapping(model_base.BASEV2, models_v2.Route): - __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)) + subnet_id = sa.Column(sa.String(36), + sa.ForeignKey('subnets.id', ondelete="CASCADE"), + primary_key=True) + net_partition_id = sa.Column(sa.String(36), + sa.ForeignKey('nuage_net_partitions.id', + ondelete="CASCADE")) + nuage_subnet_id = sa.Column(sa.String(36)) + nuage_l2dom_tmplt_id = sa.Column(sa.String(36)) + nuage_user_id = sa.Column(sa.String(36)) + nuage_group_id = sa.Column(sa.String(36)) \ No newline at end of file diff --git a/neutron/plugins/nuage/nuagedb.py b/neutron/plugins/nuage/nuagedb.py index 2f0affeba..458fd4349 100644 --- a/neutron/plugins/nuage/nuagedb.py +++ b/neutron/plugins/nuage/nuagedb.py @@ -18,85 +18,6 @@ from neutron.db import common_db_mixin from neutron.plugins.nuage import nuage_models -def add_entrouter_mapping(session, np_id, - router_id, - n_l3id): - ent_rtr_mapping = nuage_models.NetPartitionRouter(net_partition_id=np_id, - router_id=router_id, - nuage_router_id=n_l3id) - session.add(ent_rtr_mapping) - - -def add_rtrzone_mapping(session, neutron_router_id, - nuage_zone_id, - nuage_user_id=None, - nuage_group_id=None): - rtr_zone_mapping = nuage_models.RouterZone(router_id=neutron_router_id, - nuage_zone_id=nuage_zone_id, - nuage_user_id=nuage_user_id, - nuage_group_id=nuage_group_id) - session.add(rtr_zone_mapping) - - -def add_subnetl2dom_mapping(session, neutron_subnet_id, - nuage_sub_id, - np_id, - l2dom_id=None, - nuage_user_id=None, - nuage_group_id=None): - subnet_l2dom = nuage_models.SubnetL2Domain(subnet_id=neutron_subnet_id, - nuage_subnet_id=nuage_sub_id, - net_partition_id=np_id, - nuage_l2dom_tmplt_id=l2dom_id, - nuage_user_id=nuage_user_id, - nuage_group_id=nuage_group_id) - session.add(subnet_l2dom) - - -def update_subnetl2dom_mapping(subnet_l2dom, - new_dict): - 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, - nuage_vport_id=nuage_vport_id, - nuage_vif_id=nuage_vif_id, - static_ip=static_ip) - session.add(port_mapping) - return port_mapping - - -def update_port_vport_mapping(port_mapping, - new_dict): - port_mapping.update(new_dict) - - -def get_port_mapping_by_id(session, id): - query = session.query(nuage_models.PortVPortMapping) - return query.filter_by(port_id=id).first() - - -def get_ent_rtr_mapping_by_rtrid(session, rtrid): - query = session.query(nuage_models.NetPartitionRouter) - return query.filter_by(router_id=rtrid).first() - - -def get_rtr_zone_mapping(session, router_id): - query = session.query(nuage_models.RouterZone) - return query.filter_by(router_id=router_id).first() - - -def get_subnet_l2dom_by_id(session, id): - query = session.query(nuage_models.SubnetL2Domain) - return query.filter_by(subnet_id=id).first() - - def add_net_partition(session, netpart_id, l3dom_id, l2dom_id, ent_name): @@ -112,12 +33,6 @@ def delete_net_partition(session, net_partition): session.delete(net_partition) -def get_ent_rtr_mapping_by_entid(session, - entid): - query = session.query(nuage_models.NetPartitionRouter) - return query.filter_by(net_partition_id=entid).all() - - def get_net_partition_by_name(session, name): query = session.query(nuage_models.NetPartition) return query.filter_by(name=name).first() @@ -137,66 +52,50 @@ def get_net_partitions(session, filters=None, fields=None): return query -def delete_static_route(session, static_route): - session.delete(static_route) - - -def get_router_route_mapping(session, id, route): - qry = session.query(nuage_models.RouterRoutesMapping) - return qry.filter_by(router_id=id, - destination=route['destination'], - nexthop=route['nexthop']).one() - - -def add_static_route(session, router_id, nuage_rtr_id, - destination, nexthop): - staticrt = nuage_models.RouterRoutesMapping(router_id=router_id, - nuage_route_id=nuage_rtr_id, - destination=destination, - 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_entrouter_mapping(session, np_id, + router_id, + n_l3id): + ent_rtr_mapping = nuage_models.NetPartitionRouter(net_partition_id=np_id, + router_id=router_id, + nuage_router_id=n_l3id) + session.add(ent_rtr_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 add_subnetl2dom_mapping(session, neutron_subnet_id, + nuage_sub_id, + np_id, + l2dom_id=None, + nuage_user_id=None, + nuage_group_id=None): + subnet_l2dom = nuage_models.SubnetL2Domain(subnet_id=neutron_subnet_id, + nuage_subnet_id=nuage_sub_id, + net_partition_id=np_id, + nuage_l2dom_tmplt_id=l2dom_id, + nuage_user_id=nuage_user_id, + nuage_group_id=nuage_group_id) + session.add(subnet_l2dom) -def delete_fip_pool_mapping(session, fip_pool_mapping): - session.delete(fip_pool_mapping) +def update_subnetl2dom_mapping(subnet_l2dom, + new_dict): + subnet_l2dom.update(new_dict) -def get_fip_pool_by_id(session, id): - query = session.query(nuage_models.FloatingIPPoolMapping) - return query.filter_by(fip_pool_id=id).first() +def delete_subnetl2dom_mapping(session, subnet_l2dom): + session.delete(subnet_l2dom) -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_subnet_l2dom_by_id(session, id): + query = session.query(nuage_models.SubnetL2Domain) + return query.filter_by(subnet_id=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 get_ent_rtr_mapping_by_entid(session, + entid): + query = session.query(nuage_models.NetPartitionRouter) + return query.filter_by(net_partition_id=entid).all() -def update_fip_pool_mapping(fip_pool_mapping, new_dict): - fip_pool_mapping.update(new_dict) +def get_ent_rtr_mapping_by_rtrid(session, rtrid): + query = session.query(nuage_models.NetPartitionRouter) + return query.filter_by(router_id=rtrid).first() \ No newline at end of file diff --git a/neutron/plugins/nuage/plugin.py b/neutron/plugins/nuage/plugin.py index c5257ae35..164154cfd 100644 --- a/neutron/plugins/nuage/plugin.py +++ b/neutron/plugins/nuage/plugin.py @@ -31,7 +31,6 @@ from neutron.db import db_base_plugin_v2 from neutron.db import external_net_db 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 @@ -109,58 +108,28 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, found_resource = found_resource[0] return found_resource - def _update_port_ip(self, context, port, new_ip): - subid = port['fixed_ips'][0]['subnet_id'] - new_fixed_ips = {} - new_fixed_ips['subnet_id'] = subid - new_fixed_ips['ip_address'] = new_ip - ips, prev_ips = self._update_ips_for_port(context, - port["network_id"], - port['id'], - port["fixed_ips"], - [new_fixed_ips]) - - # Update ips if necessary - for ip in ips: - allocated = models_v2.IPAllocation( - network_id=port['network_id'], port_id=port['id'], - ip_address=ip['ip_address'], subnet_id=ip['subnet_id']) - context.session.add(allocated) - def _create_update_port(self, context, port, - port_mapping, subnet_mapping): + netpart_id, parent_id): filters = {'device_id': [port['device_id']]} ports = self.get_ports(context, filters) - netpart_id = subnet_mapping['net_partition_id'] net_partition = nuagedb.get_net_partition_by_id(context.session, netpart_id) params = { + 'port_id': port['id'], 'id': port['device_id'], 'mac': port['mac_address'], - 'parent_id': subnet_mapping['nuage_subnet_id'], + 'parent_id': parent_id, 'net_partition': net_partition, - 'ip': None, + 'ip': port['fixed_ips'][0]['ip_address'], 'no_of_ports': len(ports), 'tenant': port['tenant_id'] } - if port_mapping['static_ip']: - params['ip'] = port['fixed_ips'][0]['ip_address'] - - nuage_vm = self.nuageclient.create_vms(params) - if nuage_vm: - if port['fixed_ips'][0]['ip_address'] != str(nuage_vm['ip']): - self._update_port_ip(context, port, nuage_vm['ip']) - port_dict = { - 'nuage_vport_id': nuage_vm['vport_id'], - 'nuage_vif_id': nuage_vm['vif_id'] - } - nuagedb.update_port_vport_mapping(port_mapping, - port_dict) + + self.nuageclient.create_vms(params) def create_port(self, context, port): session = context.session with session.begin(subtransactions=True): - p = port['port'] port = super(NuagePlugin, self).create_port(context, port) device_owner = port.get('device_owner', None) if (device_owner and @@ -171,25 +140,15 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, subnet_mapping = nuagedb.get_subnet_l2dom_by_id(session, subnet_id) if subnet_mapping: - static_ip = False - if (attributes.is_attr_set(p['fixed_ips']) and - 'ip_address' in p['fixed_ips'][0]): - static_ip = True - nuage_vport_id = None - nuage_vif_id = None - port_mapping = nuagedb.add_port_vport_mapping( - session, - port['id'], - nuage_vport_id, - nuage_vif_id, - static_ip) port_prefix = constants.NOVA_PORT_OWNER_PREF if port['device_owner'].startswith(port_prefix): #This request is coming from nova try: - self._create_update_port(context, port, - port_mapping, - subnet_mapping) + self._create_update_port( + context, + port, + subnet_mapping['net_partition_id'], + subnet_mapping['nuage_subnet_id']) except Exception: with excutils.save_and_reraise_exception(): super(NuagePlugin, self).delete_port( @@ -208,20 +167,25 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, if 'fixed_ips' not in port or len(port['fixed_ips']) == 0: return self._make_port_dict(port) subnet_id = port['fixed_ips'][0]['subnet_id'] + subnet_mapping = nuagedb.get_subnet_l2dom_by_id(session, subnet_id) if not subnet_mapping: msg = (_("Subnet %s not found on VSD") % subnet_id) raise n_exc.BadRequest(resource='port', msg=msg) - port_mapping = nuagedb.get_port_mapping_by_id(session, - id) - if not port_mapping: - msg = (_("Port-Mapping for port %s not " - " found on VSD") % id) + + params = { + 'neutron_port_id': id, + } + nuage_port = self.nuageclient.get_nuage_port_by_id(params) + if not nuage_port: + msg = (_("Port %s not found on VSD") % id) raise n_exc.BadRequest(resource='port', msg=msg) - if not port_mapping['nuage_vport_id']: + if not nuage_port['nuage_vport_id']: self._create_update_port(context, port, - port_mapping, subnet_mapping) + subnet_mapping[ + 'net_partition_id'], + subnet_mapping['nuage_subnet_id']) updated_port = self._make_port_dict(port) else: updated_port = super(NuagePlugin, self).update_port(context, id, @@ -232,22 +196,26 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, if l3_port_check: self.prevent_l3_port_deletion(context, id) port = self._get_port(context, id) - port_mapping = nuagedb.get_port_mapping_by_id(context.session, - id) + params = { + 'neutron_port_id': id, + } + nuage_port = self.nuageclient.get_nuage_port_by_id(params) + # This is required for to pass ut test_floatingip_port_delete self.disassociate_floatingips(context, id) if not port['fixed_ips']: return super(NuagePlugin, self).delete_port(context, id) sub_id = port['fixed_ips'][0]['subnet_id'] + subnet_mapping = nuagedb.get_subnet_l2dom_by_id(context.session, sub_id) if not subnet_mapping: return super(NuagePlugin, self).delete_port(context, id) - netpart_id = subnet_mapping['net_partition_id'] net_partition = nuagedb.get_net_partition_by_id(context.session, netpart_id) + # Need to call this explicitly to delete vport_vporttag_mapping if constants.NOVA_PORT_OWNER_PREF in port['device_owner']: # This was a VM Port @@ -258,7 +226,7 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, 'net_partition': net_partition, 'tenant': port['tenant_id'], 'mac': port['mac_address'], - 'nuage_vif_id': port_mapping['nuage_vif_id'], + 'nuage_vif_id': nuage_port['nuage_vif_id'], 'id': port['device_id'] } self.nuageclient.delete_vms(params) @@ -285,10 +253,10 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, return [self._fields(self._extend_port_dict_binding(context, port), fields) for port in ports] - def _check_router_subnet_for_tenant(self, context): + def _check_router_subnet_for_tenant(self, context, tenant_id): # Search router and subnet tables. # If no entry left delete user and group from VSD - filters = {'tenant_id': [context.tenant]} + filters = {'tenant_id': [tenant_id]} routers = self.get_routers(context, filters=filters) subnets = self.get_subnets(context, filters=filters) return bool(routers or subnets) @@ -314,6 +282,14 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, msg = _('External network with subnets can not be ' 'changed to non-external network') raise nuage_exc.OperationNotSupported(msg=msg) + if is_external_set: + # Check if there are vm ports attached to this network + # If there are, then updating the network is not allowed + ports = self.get_ports(context, filters={'network_id': [id]}) + for p in ports: + if p['device_owner'].startswith( + constants.NOVA_PORT_OWNER_PREF): + raise n_exc.NetworkInUse(net_id=id) return (is_external_set, subnet) def update_network(self, context, id, network): @@ -335,12 +311,14 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, 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], + if not self._check_router_subnet_for_tenant( + context, subn['tenant_id']): + self.nuageclient.delete_user(user_id) + self.nuageclient.delete_group(group_id) + + self._add_nuage_sharedresource(subnet[0], id, constants.SR_TYPE_FLOATING) return net @@ -355,15 +333,14 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, super(NuagePlugin, self).delete_network(context, id) def _get_net_partition_for_subnet(self, context, subnet): - subn = subnet['subnet'] - ent = subn.get('net_partition', None) + ent = subnet.get('net_partition', None) if not ent: def_net_part = cfg.CONF.RESTPROXY.default_net_partition_name net_partition = nuagedb.get_net_partition_by_name(context.session, def_net_part) else: net_partition = self._resource_finder(context, 'subnet', - 'net_partition', subn) + 'net_partition', subnet) if not net_partition: msg = _('Either net_partition is not provided with subnet OR ' 'default net_partition is not created at the start') @@ -379,16 +356,8 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, msg = "no-gateway option not supported with subnets" raise nuage_exc.OperationNotSupported(msg=msg) - 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 _delete_nuage_sharedresource(self, net_id): + self.nuageclient.delete_nuage_sharedresource(net_id) def _validate_nuage_sharedresource(self, context, resource, net_id): filter = {'network_id': [net_id]} @@ -399,15 +368,15 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, raise nuage_exc.OperationNotSupported(msg=msg) return existing_subn - def _add_nuage_sharedresource(self, context, subnet, net_id, type): + def _add_nuage_sharedresource(self, subnet, net_id, type): net = netaddr.IPNetwork(subnet['cidr']) params = { 'neutron_subnet': subnet, 'net': net, - 'type': type + 'type': type, + 'net_id': net_id } - fip_pool_id = self.nuageclient.create_nuage_sharedresource(params) - nuagedb.add_fip_pool_mapping(context.session, fip_pool_id, net_id) + self.nuageclient.create_nuage_sharedresource(params) def _create_nuage_sharedresource(self, context, subnet, type): subn = subnet['subnet'] @@ -415,13 +384,13 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, 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) + self._add_nuage_sharedresource(subn, net_id, type) return subn - def _create_nuage_subnet(self, context, neutron_subnet, net_partition): + def _create_nuage_subnet(self, context, neutron_subnet, netpart_id): net = netaddr.IPNetwork(neutron_subnet['cidr']) params = { - 'net_partition': net_partition, + 'netpart_id': netpart_id, 'tenant_id': neutron_subnet['tenant_id'], 'net': net } @@ -430,8 +399,9 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, params) except Exception: with excutils.save_and_reraise_exception(): - super(NuagePlugin, self).delete_subnet(context, - neutron_subnet['id']) + super(NuagePlugin, self).delete_subnet( + context, + neutron_subnet['id']) if nuage_subnet: l2dom_id = str(nuage_subnet['nuage_l2template_id']) @@ -442,7 +412,7 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, nuagedb.add_subnetl2dom_mapping(context.session, neutron_subnet['id'], id, - net_partition['id'], + netpart_id, l2dom_id=l2dom_id, nuage_user_id=user_id, nuage_group_id=group_id) @@ -457,31 +427,32 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, self._validate_create_subnet(subn) - net_partition = self._get_net_partition_for_subnet(context, subnet) + net_partition = self._get_net_partition_for_subnet(context, subn) neutron_subnet = super(NuagePlugin, self).create_subnet(context, subnet) - self._create_nuage_subnet(context, neutron_subnet, net_partition) + self._create_nuage_subnet(context, neutron_subnet, net_partition['id']) return neutron_subnet def delete_subnet(self, context, id): subnet = self.get_subnet(context, id) if self._network_is_external(context, subnet['network_id']): super(NuagePlugin, self).delete_subnet(context, id) - return self._delete_nuage_sharedresource(context, id) + return self._delete_nuage_sharedresource(id) subnet_l2dom = nuagedb.get_subnet_l2dom_by_id(context.session, id) if subnet_l2dom: - template_id = subnet_l2dom['nuage_l2dom_tmplt_id'] try: - self.nuageclient.delete_subnet(subnet_l2dom['nuage_subnet_id'], - template_id) + self.nuageclient.delete_subnet( + subnet_l2dom['nuage_subnet_id'], + subnet_l2dom['nuage_l2dom_tmplt_id']) except Exception: msg = (_('Unable to complete operation on subnet %s.' 'One or more ports have an IP allocation ' 'from this subnet.') % id) raise n_exc.BadRequest(resource='subnet', msg=msg) super(NuagePlugin, self).delete_subnet(context, id) - if subnet_l2dom and not self._check_router_subnet_for_tenant(context): + if subnet_l2dom and not self._check_router_subnet_for_tenant( + context, subnet['tenant_id']): self.nuageclient.delete_user(subnet_l2dom['nuage_user_id']) self.nuageclient.delete_group(subnet_l2dom['nuage_group_id']) @@ -494,23 +465,21 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, interface_info) subnet_id = rtr_if_info['subnet_id'] subn = self.get_subnet(context, subnet_id) - - rtr_zone_mapping = nuagedb.get_rtr_zone_mapping(session, - router_id) ent_rtr_mapping = nuagedb.get_ent_rtr_mapping_by_rtrid(session, router_id) - subnet_l2dom = nuagedb.get_subnet_l2dom_by_id(session, - subnet_id) - if not rtr_zone_mapping or not ent_rtr_mapping: + nuage_zone = self.nuageclient.get_zone_by_routerid(router_id) + if not nuage_zone or not ent_rtr_mapping: super(NuagePlugin, self).remove_router_interface(context, router_id, interface_info) msg = (_("Router %s does not hold default zone OR " - "net_partition mapping. Router-IF add failed") + "domain in VSD. Router-IF add failed") % router_id) raise n_exc.BadRequest(resource='router', msg=msg) + subnet_l2dom = nuagedb.get_subnet_l2dom_by_id(session, + subnet_id) if not subnet_l2dom: super(NuagePlugin, self).remove_router_interface(context, @@ -546,25 +515,28 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, net = netaddr.IPNetwork(subn['cidr']) params = { 'net': net, - 'zone_id': rtr_zone_mapping['nuage_zone_id'] + 'zone_id': nuage_zone['nuage_zone_id'], + 'neutron_subnet_id': subnet_id } if not attributes.is_attr_set(subn['gateway_ip']): subn['gateway_ip'] = str(netaddr.IPAddress(net.first + 1)) try: nuage_subnet = self.nuageclient.create_domain_subnet(subn, - params) + params) except Exception: with excutils.save_and_reraise_exception(): super(NuagePlugin, self).remove_router_interface(context, router_id, interface_info) + if nuage_subnet: ns_dict = {} ns_dict['nuage_subnet_id'] = nuage_subnet['nuage_subnetid'] ns_dict['nuage_l2dom_tmplt_id'] = None nuagedb.update_subnetl2dom_mapping(subnet_l2dom, ns_dict) + return rtr_if_info def remove_router_interface(self, context, router_id, interface_info): @@ -610,7 +582,7 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, router_id, interface_info) nuage_subn_id = subnet_l2dom['nuage_subnet_id'] - if self.nuageclient.vms_on_l2domain(nuage_subn_id): + if self.nuageclient.vms_on_subnet(nuage_subn_id): msg = (_("Subnet %s has one or more active VMs " "Router-IF delete not permitted") % subnet_id) raise n_exc.BadRequest(resource='subnet', msg=msg) @@ -624,14 +596,13 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, "assoc on Nuage VSD. Router-IF delete failed") % router_id) raise n_exc.BadRequest(resource='router', msg=msg) + net = netaddr.IPNetwork(neutron_subnet['cidr']) - net_part_id = ent_rtr_mapping['net_partition_id'] - net_partition = self.get_net_partition(context, - net_part_id) + netpart_id = ent_rtr_mapping['net_partition_id'] params = { - 'net_partition': net_partition, 'tenant_id': neutron_subnet['tenant_id'], - 'net': net + 'net': net, + 'netpart_id': netpart_id } nuage_subnet = self.nuageclient.create_subnet(neutron_subnet, params) @@ -639,6 +610,7 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, info = super(NuagePlugin, self).remove_router_interface(context, router_id, interface_info) + if nuage_subnet: tmplt_id = str(nuage_subnet['nuage_l2template_id']) ns_dict = {} @@ -648,8 +620,7 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, ns_dict) return info - def _get_net_partition_for_router(self, context, router): - rtr = router['router'] + def _get_net_partition_for_router(self, context, rtr): ent = rtr.get('net_partition', None) if not ent: def_net_part = cfg.CONF.RESTPROXY.default_net_partition_name @@ -680,19 +651,14 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, with excutils.save_and_reraise_exception(): super(NuagePlugin, self).delete_router(context, neutron_router['id']) + if nuage_router: - user_id = nuage_router['nuage_userid'] - group_id = nuage_router['nuage_groupid'] with context.session.begin(subtransactions=True): nuagedb.add_entrouter_mapping(context.session, net_partition['id'], neutron_router['id'], nuage_router['nuage_domain_id']) - nuagedb.add_rtrzone_mapping(context.session, - neutron_router['id'], - nuage_router['nuage_def_zone_id'], - nuage_user_id=user_id, - nuage_group_id=group_id) + return neutron_router def _validate_nuage_staticroutes(self, old_routes, added, removed): @@ -718,6 +684,7 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, added, removed = utils.diff_list_of_dict(old_routes, r['routes']) self._validate_nuage_staticroutes(old_routes, added, removed) + ent_rtr_mapping = nuagedb.get_ent_rtr_mapping_by_rtrid( context.session, id) if not ent_rtr_mapping: @@ -730,31 +697,30 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, id, router) for route in removed: - rtr_rt_mapping = nuagedb.get_router_route_mapping( - context.session, id, route) - if rtr_rt_mapping: - self.nuageclient.delete_nuage_staticroute( - rtr_rt_mapping['nuage_route_id']) - nuagedb.delete_static_route(context.session, - rtr_rt_mapping) + destaddr = route['destination'] + cidr = destaddr.split('/') + params = { + "address": cidr[0], + "nexthop": route['nexthop'], + "nuage_domain_id": ent_rtr_mapping['nuage_router_id'] + } + self.nuageclient.delete_nuage_staticroute(params) + for route in added: params = { 'parent_id': ent_rtr_mapping['nuage_router_id'], 'net': netaddr.IPNetwork(route['destination']), 'nexthop': route['nexthop'] } - nuage_rt_id = self.nuageclient.create_nuage_staticroute( + self.nuageclient.create_nuage_staticroute( params) - nuagedb.add_static_route(context.session, - id, nuage_rt_id, - route['destination'], - route['nexthop']) else: router_updated = super(NuagePlugin, self).update_router( context, id, router) return router_updated def delete_router(self, context, id): + neutron_router = self.get_router(context, id) session = context.session ent_rtr_mapping = nuagedb.get_ent_rtr_mapping_by_rtrid(session, id) @@ -766,13 +732,19 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, ports = self.get_ports(context, filters) if ports: raise l3.RouterInUse(router_id=id) - nuage_router_id = ent_rtr_mapping['nuage_router_id'] - self.nuageclient.delete_router(nuage_router_id) - router_zone = nuagedb.get_rtr_zone_mapping(session, id) + nuage_domain_id = ent_rtr_mapping['nuage_router_id'] + self.nuageclient.delete_router(nuage_domain_id) + super(NuagePlugin, self).delete_router(context, id) - if router_zone and not self._check_router_subnet_for_tenant(context): - self.nuageclient.delete_user(router_zone['nuage_user_id']) - self.nuageclient.delete_group(router_zone['nuage_group_id']) + + nuage_zone = self.nuageclient.get_zone_by_routerid(id) + if nuage_zone and not self._check_router_subnet_for_tenant( + context, neutron_router['tenant_id']): + user_id, group_id = self.nuageclient.get_usergroup( + neutron_router['tenant_id'], + ent_rtr_mapping['net_partition_id']) + self.nuageclient.delete_user(user_id) + self.nuageclient.delete_group(group_id) def _make_net_partition_dict(self, net_partition, fields=None): res = { @@ -830,9 +802,8 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, return self._create_net_partition(session, ent["name"]) def delete_net_partition(self, context, id): - ent_rtr_mapping = nuagedb.get_ent_rtr_mapping_by_entid( - context.session, - id) + ent_rtr_mapping = nuagedb.get_ent_rtr_mapping_by_entid(context.session, + id) if ent_rtr_mapping: msg = (_("One or more router still attached to " "net_partition %s.") % id) @@ -876,45 +847,54 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, 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']) + fip_pool = self.nuageclient.get_nuage_fip_pool_by_id(net_id) + if not fip_pool: + msg = _('sharedresource %s not found on VSD') % net_id + raise n_exc.BadRequest(resource='floatingip', + msg=msg) - 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) + 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 = { + 'router_id': ent_rtr_mapping['nuage_router_id'], + 'fip_id': neutron_fip['id'], + 'neutron_fip': neutron_fip + } + + fip = self.nuageclient.get_nuage_fip_by_id(params) + if not fip: 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_fippool_id': fip_pool['nuage_fip_pool_id'], + 'neutron_fip_ip': neutron_fip['floating_ip_address'], + 'neutron_fip_id': neutron_fip['id'] } 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']: + nuage_fip_id = fip['nuage_fip_id'] + + # Update VM if required + params = { + 'neutron_port_id': port_id, + 'nuage_fip_id': nuage_fip_id, + 'nuage_rtr_id': ent_rtr_mapping['nuage_router_id'] + } + nuage_port = self.nuageclient.get_nuage_port_by_id(params) + if nuage_port: + if (nuage_port['nuage_domain_id']) != ( + ent_rtr_mapping['nuage_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_vport_id': nuage_port['nuage_vport_id'], 'nuage_fip_id': nuage_fip_id } self.nuageclient.update_nuage_vm_vport(params) @@ -939,11 +919,13 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, router_ids = super(NuagePlugin, self).disassociate_floatingips( context, port_id, do_notify=do_notify) - port_mapping = nuagedb.get_port_mapping_by_id(context.session, - port_id) - if port_mapping: + params = { + 'neutron_port_id': port_id, + } + nuage_port = self.nuageclient.get_nuage_port_by_id(params) + if nuage_port: params = { - 'nuage_vport_id': port_mapping['nuage_vport_id'], + 'nuage_vport_id': nuage_port['nuage_vport_id'], 'nuage_fip_id': None } self.nuageclient.update_nuage_vm_vport(params) @@ -978,11 +960,13 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, super(NuagePlugin, self).delete_floatingip(context, id) else: - port_mapping = nuagedb.get_port_mapping_by_id(context.session, - port_id) - if port_mapping: + params = { + 'neutron_port_id': port_id, + } + nuage_port = self.nuageclient.get_nuage_port_by_id(params) + if nuage_port: params = { - 'nuage_vport_id': port_mapping['nuage_vport_id'], + 'nuage_vport_id': nuage_port['nuage_vport_id'], 'nuage_fip_id': None } self.nuageclient.update_nuage_vm_vport(params) @@ -997,19 +981,33 @@ class NuagePlugin(db_base_plugin_v2.NeutronDbPluginV2, 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 = { + 'neutron_port_id': id, + } + nuage_port = self.nuageclient.get_nuage_port_by_id(params) + if (nuage_port and + nuage_port['nuage_vport_id'] is not None): params = { - 'nuage_vport_id': port_mapping['nuage_vport_id'], + 'nuage_vport_id': nuage_port['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) + rtr_id = fip['last_known_router_id'] + if rtr_id: + 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 = { + 'router_id': ent_rtr_mapping['nuage_router_id'], + 'fip_id': id + } + fip = self.nuageclient.get_nuage_fip_by_id(params) + if fip: + self.nuageclient.delete_nuage_floatingip( + fip['nuage_fip_id']) + super(NuagePlugin, self).delete_floatingip(context, id) \ No newline at end of file diff --git a/neutron/tests/unit/nuage/fake_nuageclient.py b/neutron/tests/unit/nuage/fake_nuageclient.py index 2abcd8ddc..dfad78608 100644 --- a/neutron/tests/unit/nuage/fake_nuageclient.py +++ b/neutron/tests/unit/nuage/fake_nuageclient.py @@ -28,6 +28,9 @@ class FakeNuageClient(object): def vms_on_l2domain(self, l2dom_id): pass + def vms_on_subnet(self, subnet_id): + pass + def create_subnet(self, neutron_subnet, params): nuage_subnet = { 'nuage_l2template_id': uuidutils.generate_uuid(), @@ -113,3 +116,48 @@ class FakeNuageClient(object): def update_nuage_vm_vport(self, params): pass + + def get_nuage_fip_pool_by_id(self, net_id): + result = { + 'nuage_fip_pool_id': uuidutils.generate_uuid() + } + return result + + def get_nuage_fip_by_id(self, params): + if 'neutron_fip' in params: + neutron_fip = params['neutron_fip'] + if (neutron_fip['floating_ip_address'] == '12.0.0.3' and + neutron_fip['fixed_ip_address'] == '10.0.1.2') or ( + neutron_fip['floating_ip_address'] == '12.0.0.5' and + neutron_fip['fixed_ip_address'] == '10.0.1.3'): + result = { + 'nuage_fip_id': '1', + 'nuage_parent_id': '1' + } + return result + + def get_nuage_port_by_id(self, params): + if 'nuage_fip_id' in params and params['nuage_fip_id'] == '1': + domain_id = uuidutils.generate_uuid() + else: + if 'nuage_router_id' in params: + domain_id = params['nuage_router_id'] + else: + return + + result = { + 'nuage_vif_id': uuidutils.generate_uuid(), + 'nuage_vport_id': uuidutils.generate_uuid(), + 'nuage_domain_id': domain_id + } + + return result + + def get_zone_by_routerid(self, neutron_router_id): + result = { + 'nuage_zone_id': uuidutils.generate_uuid() + } + return result + + def get_usergroup(self, tenant, net_partition_id): + return uuidutils.generate_uuid(), uuidutils.generate_uuid() -- 2.45.2