From 1111fb8cafd459fa38028e68292054100e0f2ee0 Mon Sep 17 00:00:00 2001 From: Salvatore Orlando Date: Mon, 2 Feb 2015 06:01:49 -0800 Subject: [PATCH] NSX DB models split, part 1 This patch introduces a new module for hosting NSX DB model classes, and populates it with models for the 'network gateway' extension, which are then removed from the model hosting the network gateway mixin. This patch is part of a set of minor refactorings in the NSX plugin which will then lead to a semi-full decomposition by the end of the Kilo release cycle. Related-to blueprint core-vendor-decomposition Change-Id: Ie04f6c94055ac20b938c17cea251ec6532a1e16a --- neutron/plugins/vmware/dbexts/networkgw_db.py | 99 ++++--------------- neutron/plugins/vmware/dbexts/nsx_models.py | 88 +++++++++++++++++ neutron/plugins/vmware/plugins/base.py | 17 ++-- .../unit/vmware/extensions/test_networkgw.py | 13 +-- 4 files changed, 123 insertions(+), 94 deletions(-) create mode 100644 neutron/plugins/vmware/dbexts/nsx_models.py diff --git a/neutron/plugins/vmware/dbexts/networkgw_db.py b/neutron/plugins/vmware/dbexts/networkgw_db.py index 7d3404fd0..8f23a9d6b 100644 --- a/neutron/plugins/vmware/dbexts/networkgw_db.py +++ b/neutron/plugins/vmware/dbexts/networkgw_db.py @@ -12,18 +12,14 @@ # License for the specific language governing permissions and limitations # under the License. -import sqlalchemy as sa - -from sqlalchemy import orm from sqlalchemy.orm import exc as sa_orm_exc from neutron.api.v2 import attributes from neutron.common import exceptions from neutron.common import utils -from neutron.db import model_base -from neutron.db import models_v2 from neutron.openstack.common import log as logging from neutron.openstack.common import uuidutils +from neutron.plugins.vmware.dbexts import nsx_models from neutron.plugins.vmware.extensions import networkgw @@ -90,67 +86,6 @@ class NetworkGatewayUnchangeable(exceptions.InUse): "cannot be updated or deleted") -class NetworkConnection(model_base.BASEV2, models_v2.HasTenant): - """Defines a connection between a network gateway and a network.""" - # We use port_id as the primary key as one can connect a gateway - # to a network in multiple ways (and we cannot use the same port form - # more than a single gateway) - network_gateway_id = sa.Column(sa.String(36), - sa.ForeignKey('networkgateways.id', - ondelete='CASCADE')) - network_id = sa.Column(sa.String(36), - sa.ForeignKey('networks.id', ondelete='CASCADE')) - segmentation_type = sa.Column( - sa.Enum('flat', 'vlan', - name='networkconnections_segmentation_type')) - segmentation_id = sa.Column(sa.Integer) - __table_args__ = (sa.UniqueConstraint(network_gateway_id, - segmentation_type, - segmentation_id), - model_base.BASEV2.__table_args__) - # Also, storing port id comes back useful when disconnecting a network - # from a gateway - port_id = sa.Column(sa.String(36), - sa.ForeignKey('ports.id', ondelete='CASCADE'), - primary_key=True) - - -class NetworkGatewayDeviceReference(model_base.BASEV2): - id = sa.Column(sa.String(36), primary_key=True) - network_gateway_id = sa.Column(sa.String(36), - sa.ForeignKey('networkgateways.id', - ondelete='CASCADE'), - primary_key=True) - interface_name = sa.Column(sa.String(64), primary_key=True) - - -class NetworkGatewayDevice(model_base.BASEV2, models_v2.HasId, - models_v2.HasTenant): - nsx_id = sa.Column(sa.String(36)) - # Optional name for the gateway device - name = sa.Column(sa.String(255)) - # Transport connector type. Not using enum as range of - # connector types might vary with backend version - connector_type = sa.Column(sa.String(10)) - # Transport connector IP Address - connector_ip = sa.Column(sa.String(64)) - # operational status - status = sa.Column(sa.String(16)) - - -class NetworkGateway(model_base.BASEV2, models_v2.HasId, - models_v2.HasTenant): - """Defines the data model for a network gateway.""" - name = sa.Column(sa.String(255)) - # Tenant id is nullable for this resource - tenant_id = sa.Column(sa.String(36)) - default = sa.Column(sa.Boolean()) - devices = orm.relationship(NetworkGatewayDeviceReference, - backref='networkgateways', - cascade='all,delete') - network_connections = orm.relationship(NetworkConnection, lazy='joined') - - class NetworkGatewayMixin(networkgw.NetworkGatewayPluginBase): gateway_resource = networkgw.GATEWAY_RESOURCE_NAME @@ -158,7 +93,7 @@ class NetworkGatewayMixin(networkgw.NetworkGatewayPluginBase): def _get_network_gateway(self, context, gw_id): try: - gw = self._get_by_id(context, NetworkGateway, gw_id) + gw = self._get_by_id(context, nsx_models.NetworkGateway, gw_id) except sa_orm_exc.NoResultFound: raise GatewayNotFound(gateway_id=gw_id) return gw @@ -225,18 +160,18 @@ class NetworkGatewayMixin(networkgw.NetworkGatewayPluginBase): if v and k != NETWORK_ID: filters[k] = [v] query = self._get_collection_query(context, - NetworkConnection, + nsx_models.NetworkConnection, filters) return query.one() if only_one else query.all() def _unset_default_network_gateways(self, context): with context.session.begin(subtransactions=True): - context.session.query(NetworkGateway).update( - {NetworkGateway.default: False}) + context.session.query(nsx_models.NetworkGateway).update( + {nsx_models.NetworkGateway.default: False}) def _set_default_network_gateway(self, context, gw_id): with context.session.begin(subtransactions=True): - gw = (context.session.query(NetworkGateway). + gw = (context.session.query(nsx_models.NetworkGateway). filter_by(id=gw_id).one()) gw['default'] = True @@ -271,7 +206,7 @@ class NetworkGatewayMixin(networkgw.NetworkGatewayPluginBase): gw_data = network_gateway[self.gateway_resource] tenant_id = self._get_tenant_id_for_create(context, gw_data) with context.session.begin(subtransactions=True): - gw_db = NetworkGateway( + gw_db = nsx_models.NetworkGateway( id=gw_data.get('id', uuidutils.generate_uuid()), tenant_id=tenant_id, name=gw_data.get('name')) @@ -279,8 +214,9 @@ class NetworkGatewayMixin(networkgw.NetworkGatewayPluginBase): # might still either not exist or belong to a different tenant if validate_device_list: self._validate_device_list(context, tenant_id, gw_data) - gw_db.devices.extend([NetworkGatewayDeviceReference(**device) - for device in gw_data['devices']]) + gw_db.devices.extend( + [nsx_models.NetworkGatewayDeviceReference(**device) + for device in gw_data['devices']]) context.session.add(gw_db) LOG.debug("Created network gateway with id:%s", gw_db['id']) return self._make_network_gateway_dict(gw_db) @@ -316,7 +252,7 @@ class NetworkGatewayMixin(networkgw.NetworkGatewayPluginBase): page_reverse=False): marker_obj = self._get_marker_obj( context, 'network_gateway', limit, marker) - return self._get_collection(context, NetworkGateway, + return self._get_collection(context, nsx_models.NetworkGateway, self._make_network_gateway_dict, filters=filters, fields=fields, sorts=sorts, limit=limit, @@ -384,7 +320,7 @@ class NetworkGatewayMixin(networkgw.NetworkGatewayPluginBase): network_mapping_info['port_id'] = port_id network_mapping_info['tenant_id'] = tenant_id gw_db.network_connections.append( - NetworkConnection(**network_mapping_info)) + nsx_models.NetworkConnection(**network_mapping_info)) port_id = port['id'] # now deallocate and recycle ip from the port for fixed_ip in port.get('fixed_ips', []): @@ -445,13 +381,16 @@ class NetworkGatewayMixin(networkgw.NetworkGatewayPluginBase): def _get_gateway_device(self, context, device_id): try: - return self._get_by_id(context, NetworkGatewayDevice, device_id) + return self._get_by_id(context, + nsx_models.NetworkGatewayDevice, + device_id) except sa_orm_exc.NoResultFound: raise GatewayDeviceNotFound(device_id=device_id) def _is_device_in_use(self, context, device_id): query = self._get_collection_query( - context, NetworkGatewayDeviceReference, {'id': [device_id]}) + context, nsx_models.NetworkGatewayDeviceReference, + {'id': [device_id]}) return query.first() def get_gateway_device(self, context, device_id, fields=None, @@ -467,7 +406,7 @@ class NetworkGatewayMixin(networkgw.NetworkGatewayPluginBase): marker_obj = self._get_marker_obj( context, 'gateway_device', limit, marker) return self._get_collection_query(context, - NetworkGatewayDevice, + nsx_models.NetworkGatewayDevice, filters=filters, sorts=sorts, limit=limit, @@ -487,7 +426,7 @@ class NetworkGatewayMixin(networkgw.NetworkGatewayPluginBase): device_data = gateway_device[self.device_resource] tenant_id = self._get_tenant_id_for_create(context, device_data) with context.session.begin(subtransactions=True): - device_db = NetworkGatewayDevice( + device_db = nsx_models.NetworkGatewayDevice( id=device_data.get('id', uuidutils.generate_uuid()), tenant_id=tenant_id, name=device_data.get('name'), diff --git a/neutron/plugins/vmware/dbexts/nsx_models.py b/neutron/plugins/vmware/dbexts/nsx_models.py new file mode 100644 index 000000000..c2e3bc687 --- /dev/null +++ b/neutron/plugins/vmware/dbexts/nsx_models.py @@ -0,0 +1,88 @@ +# Copyright 2015 VMware, Inc. +# +# 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. + +""" +NSX data models. + +This module defines data models used by the VMware NSX plugin family. + +""" + +import sqlalchemy as sa + +from sqlalchemy import orm + +from neutron.db import model_base +from neutron.db import models_v2 + + +class NetworkConnection(model_base.BASEV2, models_v2.HasTenant): + """Defines a connection between a network gateway and a network.""" + # We use port_id as the primary key as one can connect a gateway + # to a network in multiple ways (and we cannot use the same port form + # more than a single gateway) + network_gateway_id = sa.Column(sa.String(36), + sa.ForeignKey('networkgateways.id', + ondelete='CASCADE')) + network_id = sa.Column(sa.String(36), + sa.ForeignKey('networks.id', ondelete='CASCADE')) + segmentation_type = sa.Column( + sa.Enum('flat', 'vlan', + name='networkconnections_segmentation_type')) + segmentation_id = sa.Column(sa.Integer) + __table_args__ = (sa.UniqueConstraint(network_gateway_id, + segmentation_type, + segmentation_id), + model_base.BASEV2.__table_args__) + # Also, storing port id comes back useful when disconnecting a network + # from a gateway + port_id = sa.Column(sa.String(36), + sa.ForeignKey('ports.id', ondelete='CASCADE'), + primary_key=True) + + +class NetworkGatewayDeviceReference(model_base.BASEV2): + id = sa.Column(sa.String(36), primary_key=True) + network_gateway_id = sa.Column(sa.String(36), + sa.ForeignKey('networkgateways.id', + ondelete='CASCADE'), + primary_key=True) + interface_name = sa.Column(sa.String(64), primary_key=True) + + +class NetworkGatewayDevice(model_base.BASEV2, models_v2.HasId, + models_v2.HasTenant): + nsx_id = sa.Column(sa.String(36)) + # Optional name for the gateway device + name = sa.Column(sa.String(255)) + # Transport connector type. Not using enum as range of + # connector types might vary with backend version + connector_type = sa.Column(sa.String(10)) + # Transport connector IP Address + connector_ip = sa.Column(sa.String(64)) + # operational status + status = sa.Column(sa.String(16)) + + +class NetworkGateway(model_base.BASEV2, models_v2.HasId, + models_v2.HasTenant): + """Defines the data model for a network gateway.""" + name = sa.Column(sa.String(255)) + # Tenant id is nullable for this resource + tenant_id = sa.Column(sa.String(36)) + default = sa.Column(sa.Boolean()) + devices = orm.relationship(NetworkGatewayDeviceReference, + backref='networkgateways', + cascade='all,delete') + network_connections = orm.relationship(NetworkConnection, lazy='joined') diff --git a/neutron/plugins/vmware/plugins/base.py b/neutron/plugins/vmware/plugins/base.py index 16155cef0..caa5a5d97 100644 --- a/neutron/plugins/vmware/plugins/base.py +++ b/neutron/plugins/vmware/plugins/base.py @@ -66,6 +66,7 @@ from neutron.plugins.vmware.common import utils as c_utils from neutron.plugins.vmware.dbexts import db as nsx_db from neutron.plugins.vmware.dbexts import maclearning as mac_db from neutron.plugins.vmware.dbexts import networkgw_db +from neutron.plugins.vmware.dbexts import nsx_models from neutron.plugins.vmware.dbexts import qos_db from neutron.plugins.vmware import dhcpmeta_modes from neutron.plugins.vmware.extensions import maclearning as mac_ext @@ -2115,8 +2116,8 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin, "because of an error in the NSX backend"), device_id) with context.session.begin(subtransactions=True): query = self._model_query( - context, networkgw_db.NetworkGatewayDevice).filter( - networkgw_db.NetworkGatewayDevice.id == device_id) + context, nsx_models.NetworkGatewayDevice).filter( + nsx_models.NetworkGatewayDevice.id == device_id) if is_create: query.delete(synchronize_session=False) else: @@ -2151,8 +2152,8 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin, # set NSX GW device in neutron database and update status with context.session.begin(subtransactions=True): query = self._model_query( - context, networkgw_db.NetworkGatewayDevice).filter( - networkgw_db.NetworkGatewayDevice.id == neutron_id) + context, nsx_models.NetworkGatewayDevice).filter( + nsx_models.NetworkGatewayDevice.id == neutron_id) query.update({'status': device_status, 'nsx_id': nsx_res['uuid']}, synchronize_session=False) @@ -2190,8 +2191,8 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin, # update status with context.session.begin(subtransactions=True): query = self._model_query( - context, networkgw_db.NetworkGatewayDevice).filter( - networkgw_db.NetworkGatewayDevice.id == neutron_id) + context, nsx_models.NetworkGatewayDevice).filter( + nsx_models.NetworkGatewayDevice.id == neutron_id) query.update({'status': device_status}, synchronize_session=False) LOG.debug("Neutron gateway device: %(neutron_id)s; " @@ -2225,8 +2226,8 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin, # Update status in database with context.session.begin(subtransactions=True): query = self._model_query( - context, networkgw_db.NetworkGatewayDevice).filter( - networkgw_db.NetworkGatewayDevice.id == device_id) + context, nsx_models.NetworkGatewayDevice).filter( + nsx_models.NetworkGatewayDevice.id == device_id) query.update({'status': device_status}, synchronize_session=False) gw_device['status'] = device_status diff --git a/neutron/tests/unit/vmware/extensions/test_networkgw.py b/neutron/tests/unit/vmware/extensions/test_networkgw.py index 5aaebbc17..993b8cb6e 100644 --- a/neutron/tests/unit/vmware/extensions/test_networkgw.py +++ b/neutron/tests/unit/vmware/extensions/test_networkgw.py @@ -28,6 +28,7 @@ from neutron import manager from neutron.plugins.vmware.api_client import exception as api_exc from neutron.plugins.vmware.common import exceptions as nsx_exc from neutron.plugins.vmware.dbexts import networkgw_db +from neutron.plugins.vmware.dbexts import nsx_models from neutron.plugins.vmware.extensions import networkgw from neutron.plugins.vmware import nsxlib from neutron.plugins.vmware.nsxlib import l2gateway as l2gwlib @@ -579,11 +580,11 @@ class NetworkGatewayDbTestCase(test_db_plugin.NeutronDbPluginV2TestCase): # Verify nothing left on db session = db_api.get_session() dev_query = session.query( - networkgw_db.NetworkGatewayDevice).filter( - networkgw_db.NetworkGatewayDevice.id == device_id) + nsx_models.NetworkGatewayDevice).filter( + nsx_models.NetworkGatewayDevice.id == device_id) self.assertIsNone(dev_query.first()) - gw_query = session.query(networkgw_db.NetworkGateway).filter( - networkgw_db.NetworkGateway.id == gw_id) + gw_query = session.query(nsx_models.NetworkGateway).filter( + nsx_models.NetworkGateway.id == gw_id) self.assertIsNone(gw_query.first()) def test_update_network_gateway(self): @@ -905,8 +906,8 @@ class NetworkGatewayDbTestCase(test_db_plugin.NeutronDbPluginV2TestCase): dev_id = dev[self.dev_resource]['id'] # Verify nothing left on db session = db_api.get_session() - dev_query = session.query(networkgw_db.NetworkGatewayDevice) - dev_query.filter(networkgw_db.NetworkGatewayDevice.id == dev_id) + dev_query = session.query(nsx_models.NetworkGatewayDevice) + dev_query.filter(nsx_models.NetworkGatewayDevice.id == dev_id) self.assertIsNone(dev_query.first()) -- 2.45.2