]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Decompose db_base_plugin_v2.py
authorPavel Bondar <pbondar@infoblox.com>
Wed, 3 Jun 2015 11:22:29 +0000 (14:22 +0300)
committerPavel Bondar <pbondar@infoblox.com>
Wed, 3 Jun 2015 14:35:19 +0000 (17:35 +0300)
Moved private getters and simple helpers into db_base_plugin_common.
This change is part of bigger refactoring for supporting Pluggable IPAM.
Main purpose is to make getters accessible by IPAM code.

Partially-Implements: blueprint neutron-ipam

Change-Id: I1eac61c258541bca80e14be4b7c75519a014ffae

neutron/db/db_base_plugin_common.py [new file with mode: 0644]
neutron/db/db_base_plugin_v2.py

diff --git a/neutron/db/db_base_plugin_common.py b/neutron/db/db_base_plugin_common.py
new file mode 100644 (file)
index 0000000..f0a75ed
--- /dev/null
@@ -0,0 +1,251 @@
+# Copyright (c) 2015 OpenStack Foundation.
+# All Rights Reserved.
+#
+#    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.
+
+import netaddr
+
+from oslo_config import cfg
+from oslo_log import log as logging
+from sqlalchemy.orm import exc
+
+from neutron.api.v2 import attributes
+from neutron.common import constants
+from neutron.common import exceptions as n_exc
+from neutron.common import utils
+from neutron.db import common_db_mixin
+from neutron.db import models_v2
+from neutron.ipam import utils as ipam_utils
+
+LOG = logging.getLogger(__name__)
+
+
+class DbBasePluginCommon(common_db_mixin.CommonDbMixin):
+    """Stores getters and helper methods for db_base_plugin_v2
+
+    All private getters and simple helpers like _make_*_dict were moved from
+    db_base_plugin_v2.
+    More complicated logic and public methods left in db_base_plugin_v2.
+    Main purpose of this class is to make getters accessible for Ipam
+    backends.
+    """
+
+    @staticmethod
+    def _generate_mac():
+        return utils.get_random_mac(cfg.CONF.base_mac.split(':'))
+
+    @staticmethod
+    def _delete_ip_allocation(context, network_id, subnet_id, ip_address):
+
+        # Delete the IP address from the IPAllocate table
+        LOG.debug("Delete allocated IP %(ip_address)s "
+                  "(%(network_id)s/%(subnet_id)s)",
+                  {'ip_address': ip_address,
+                   'network_id': network_id,
+                   'subnet_id': subnet_id})
+        context.session.query(models_v2.IPAllocation).filter_by(
+            network_id=network_id,
+            ip_address=ip_address,
+            subnet_id=subnet_id).delete()
+
+    @staticmethod
+    def _store_ip_allocation(context, ip_address, network_id, subnet_id,
+                             port_id):
+        LOG.debug("Allocated IP %(ip_address)s "
+                  "(%(network_id)s/%(subnet_id)s/%(port_id)s)",
+                  {'ip_address': ip_address,
+                   'network_id': network_id,
+                   'subnet_id': subnet_id,
+                   'port_id': port_id})
+        allocated = models_v2.IPAllocation(
+            network_id=network_id,
+            port_id=port_id,
+            ip_address=ip_address,
+            subnet_id=subnet_id
+        )
+        context.session.add(allocated)
+
+    @classmethod
+    def _check_gateway_in_subnet(cls, cidr, gateway):
+        """Validate that the gateway is on the subnet."""
+        ip = netaddr.IPAddress(gateway)
+        if ip.version == 4 or (ip.version == 6 and not ip.is_link_local()):
+            return ipam_utils.check_subnet_ip(cidr, gateway)
+        return True
+
+    def _make_subnet_dict(self, subnet, fields=None):
+        res = {'id': subnet['id'],
+               'name': subnet['name'],
+               'tenant_id': subnet['tenant_id'],
+               'network_id': subnet['network_id'],
+               'ip_version': subnet['ip_version'],
+               'cidr': subnet['cidr'],
+               'subnetpool_id': subnet.get('subnetpool_id'),
+               'allocation_pools': [{'start': pool['first_ip'],
+                                     'end': pool['last_ip']}
+                                    for pool in subnet['allocation_pools']],
+               'gateway_ip': subnet['gateway_ip'],
+               'enable_dhcp': subnet['enable_dhcp'],
+               'ipv6_ra_mode': subnet['ipv6_ra_mode'],
+               'ipv6_address_mode': subnet['ipv6_address_mode'],
+               'dns_nameservers': [dns['address']
+                                   for dns in subnet['dns_nameservers']],
+               'host_routes': [{'destination': route['destination'],
+                                'nexthop': route['nexthop']}
+                               for route in subnet['routes']],
+               'shared': subnet['shared']
+               }
+        # Call auxiliary extend functions, if any
+        self._apply_dict_extend_functions(attributes.SUBNETS, res, subnet)
+        return self._fields(res, fields)
+
+    def _make_subnetpool_dict(self, subnetpool, fields=None):
+        default_prefixlen = str(subnetpool['default_prefixlen'])
+        min_prefixlen = str(subnetpool['min_prefixlen'])
+        max_prefixlen = str(subnetpool['max_prefixlen'])
+        res = {'id': subnetpool['id'],
+               'name': subnetpool['name'],
+               'tenant_id': subnetpool['tenant_id'],
+               'default_prefixlen': default_prefixlen,
+               'min_prefixlen': min_prefixlen,
+               'max_prefixlen': max_prefixlen,
+               'shared': subnetpool['shared'],
+               'prefixes': [prefix['cidr']
+                            for prefix in subnetpool['prefixes']],
+               'ip_version': subnetpool['ip_version'],
+               'default_quota': subnetpool['default_quota']}
+        return self._fields(res, fields)
+
+    def _make_port_dict(self, port, fields=None,
+                        process_extensions=True):
+        res = {"id": port["id"],
+               'name': port['name'],
+               "network_id": port["network_id"],
+               'tenant_id': port['tenant_id'],
+               "mac_address": port["mac_address"],
+               "admin_state_up": port["admin_state_up"],
+               "status": port["status"],
+               "fixed_ips": [{'subnet_id': ip["subnet_id"],
+                              'ip_address': ip["ip_address"]}
+                             for ip in port["fixed_ips"]],
+               "device_id": port["device_id"],
+               "device_owner": port["device_owner"]}
+        # Call auxiliary extend functions, if any
+        if process_extensions:
+            self._apply_dict_extend_functions(
+                attributes.PORTS, res, port)
+        return self._fields(res, fields)
+
+    def _get_network(self, context, id):
+        try:
+            network = self._get_by_id(context, models_v2.Network, id)
+        except exc.NoResultFound:
+            raise n_exc.NetworkNotFound(net_id=id)
+        return network
+
+    def _get_subnet(self, context, id):
+        try:
+            subnet = self._get_by_id(context, models_v2.Subnet, id)
+        except exc.NoResultFound:
+            raise n_exc.SubnetNotFound(subnet_id=id)
+        return subnet
+
+    def _get_subnetpool(self, context, id):
+        try:
+            return self._get_by_id(context, models_v2.SubnetPool, id)
+        except exc.NoResultFound:
+            raise n_exc.SubnetPoolNotFound(subnetpool_id=id)
+
+    def _get_all_subnetpools(self, context):
+        # NOTE(tidwellr): see note in _get_all_subnets()
+        return context.session.query(models_v2.SubnetPool).all()
+
+    def _get_port(self, context, id):
+        try:
+            port = self._get_by_id(context, models_v2.Port, id)
+        except exc.NoResultFound:
+            raise n_exc.PortNotFound(port_id=id)
+        return port
+
+    def _get_dns_by_subnet(self, context, subnet_id):
+        dns_qry = context.session.query(models_v2.DNSNameServer)
+        return dns_qry.filter_by(subnet_id=subnet_id).all()
+
+    def _get_route_by_subnet(self, context, subnet_id):
+        route_qry = context.session.query(models_v2.SubnetRoute)
+        return route_qry.filter_by(subnet_id=subnet_id).all()
+
+    def _get_router_gw_ports_by_network(self, context, network_id):
+        port_qry = context.session.query(models_v2.Port)
+        return port_qry.filter_by(network_id=network_id,
+                device_owner=constants.DEVICE_OWNER_ROUTER_GW).all()
+
+    def _get_subnets_by_network(self, context, network_id):
+        subnet_qry = context.session.query(models_v2.Subnet)
+        return subnet_qry.filter_by(network_id=network_id).all()
+
+    def _get_subnets_by_subnetpool(self, context, subnetpool_id):
+        subnet_qry = context.session.query(models_v2.Subnet)
+        return subnet_qry.filter_by(subnetpool_id=subnetpool_id).all()
+
+    def _get_all_subnets(self, context):
+        # NOTE(salvatore-orlando): This query might end up putting
+        # a lot of stress on the db. Consider adding a cache layer
+        return context.session.query(models_v2.Subnet).all()
+
+    def _make_network_dict(self, network, fields=None,
+                           process_extensions=True):
+        res = {'id': network['id'],
+               'name': network['name'],
+               'tenant_id': network['tenant_id'],
+               'admin_state_up': network['admin_state_up'],
+               'mtu': network.get('mtu', constants.DEFAULT_NETWORK_MTU),
+               'status': network['status'],
+               'shared': network['shared'],
+               'subnets': [subnet['id']
+                           for subnet in network['subnets']]}
+        # TODO(pritesh): Move vlan_transparent to the extension module.
+        # vlan_transparent here is only added if the vlantransparent
+        # extension is enabled.
+        if ('vlan_transparent' in network and network['vlan_transparent'] !=
+            attributes.ATTR_NOT_SPECIFIED):
+            res['vlan_transparent'] = network['vlan_transparent']
+        # Call auxiliary extend functions, if any
+        if process_extensions:
+            self._apply_dict_extend_functions(
+                attributes.NETWORKS, res, network)
+        return self._fields(res, fields)
+
+    def _make_subnet_args(self, context, shared, detail,
+                          subnet, subnetpool_id=None):
+        args = {'tenant_id': detail.tenant_id,
+                'id': detail.subnet_id,
+                'name': subnet['name'],
+                'network_id': subnet['network_id'],
+                'ip_version': subnet['ip_version'],
+                'cidr': str(detail.subnet_cidr),
+                'subnetpool_id': subnetpool_id,
+                'enable_dhcp': subnet['enable_dhcp'],
+                'gateway_ip': self._gateway_ip_str(subnet, detail.subnet_cidr),
+                'shared': shared}
+        if subnet['ip_version'] == 6 and subnet['enable_dhcp']:
+            if attributes.is_attr_set(subnet['ipv6_ra_mode']):
+                args['ipv6_ra_mode'] = subnet['ipv6_ra_mode']
+            if attributes.is_attr_set(subnet['ipv6_address_mode']):
+                args['ipv6_address_mode'] = subnet['ipv6_address_mode']
+        return args
+
+    def _gateway_ip_str(self, subnet, cidr_net):
+        if subnet.get('gateway_ip') is attributes.ATTR_NOT_SPECIFIED:
+                return str(cidr_net.network + 1)
+        return subnet.get('gateway_ip')
index 29ffa85b4f2067019e1305031691d29e87197e73..87fd1d3dac9b5f6f48d72cb87d519ed5b7d84234 100644 (file)
@@ -35,7 +35,7 @@ from neutron.common import ipv6_utils
 from neutron.common import utils
 from neutron import context as ctx
 from neutron.db import api as db_api
-from neutron.db import common_db_mixin
+from neutron.db import db_base_plugin_common
 from neutron.db import models_v2
 from neutron.db import sqlalchemyutils
 from neutron.extensions import l3
@@ -70,8 +70,8 @@ def _check_subnet_not_used(context, subnet_id):
         raise n_exc.SubnetInUse(subnet_id=subnet_id, reason=e)
 
 
-class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
-                        common_db_mixin.CommonDbMixin):
+class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
+                        neutron_plugin_base_v2.NeutronPluginBaseV2):
     """V2 Neutron plugin interface implementation using SQLAlchemy models.
 
     Whenever a non-read call happens the plugin will call an event handler
@@ -100,98 +100,6 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
             event.listen(models_v2.Port.status, 'set',
                          self.nova_notifier.record_port_status_changed)
 
-    def _get_network(self, context, id):
-        try:
-            network = self._get_by_id(context, models_v2.Network, id)
-        except exc.NoResultFound:
-            raise n_exc.NetworkNotFound(net_id=id)
-        return network
-
-    def _get_subnet(self, context, id):
-        try:
-            subnet = self._get_by_id(context, models_v2.Subnet, id)
-        except exc.NoResultFound:
-            raise n_exc.SubnetNotFound(subnet_id=id)
-        return subnet
-
-    def _get_subnetpool(self, context, id):
-        try:
-            return self._get_by_id(context, models_v2.SubnetPool, id)
-        except exc.NoResultFound:
-            raise n_exc.SubnetPoolNotFound(subnetpool_id=id)
-
-    def _get_all_subnetpools(self, context):
-        # NOTE(tidwellr): see note in _get_all_subnets()
-        return context.session.query(models_v2.SubnetPool).all()
-
-    def _get_port(self, context, id):
-        try:
-            port = self._get_by_id(context, models_v2.Port, id)
-        except exc.NoResultFound:
-            raise n_exc.PortNotFound(port_id=id)
-        return port
-
-    def _get_dns_by_subnet(self, context, subnet_id):
-        dns_qry = context.session.query(models_v2.DNSNameServer)
-        return dns_qry.filter_by(subnet_id=subnet_id).all()
-
-    def _get_route_by_subnet(self, context, subnet_id):
-        route_qry = context.session.query(models_v2.SubnetRoute)
-        return route_qry.filter_by(subnet_id=subnet_id).all()
-
-    def _get_router_gw_ports_by_network(self, context, network_id):
-        port_qry = context.session.query(models_v2.Port)
-        return port_qry.filter_by(network_id=network_id,
-                device_owner=constants.DEVICE_OWNER_ROUTER_GW).all()
-
-    def _get_subnets_by_network(self, context, network_id):
-        subnet_qry = context.session.query(models_v2.Subnet)
-        return subnet_qry.filter_by(network_id=network_id).all()
-
-    def _get_subnets_by_subnetpool(self, context, subnetpool_id):
-        subnet_qry = context.session.query(models_v2.Subnet)
-        return subnet_qry.filter_by(subnetpool_id=subnetpool_id).all()
-
-    def _get_all_subnets(self, context):
-        # NOTE(salvatore-orlando): This query might end up putting
-        # a lot of stress on the db. Consider adding a cache layer
-        return context.session.query(models_v2.Subnet).all()
-
-    @staticmethod
-    def _generate_mac():
-        return utils.get_random_mac(cfg.CONF.base_mac.split(':'))
-
-    @staticmethod
-    def _delete_ip_allocation(context, network_id, subnet_id, ip_address):
-
-        # Delete the IP address from the IPAllocate table
-        LOG.debug("Delete allocated IP %(ip_address)s "
-                  "(%(network_id)s/%(subnet_id)s)",
-                  {'ip_address': ip_address,
-                   'network_id': network_id,
-                   'subnet_id': subnet_id})
-        context.session.query(models_v2.IPAllocation).filter_by(
-            network_id=network_id,
-            ip_address=ip_address,
-            subnet_id=subnet_id).delete()
-
-    @staticmethod
-    def _store_ip_allocation(context, ip_address, network_id, subnet_id,
-                             port_id):
-        LOG.debug("Allocated IP %(ip_address)s "
-                  "(%(network_id)s/%(subnet_id)s/%(port_id)s)",
-                  {'ip_address': ip_address,
-                   'network_id': network_id,
-                   'subnet_id': subnet_id,
-                   'port_id': port_id})
-        allocated = models_v2.IPAllocation(
-            network_id=network_id,
-            port_id=port_id,
-            ip_address=ip_address,
-            subnet_id=subnet_id
-        )
-        context.session.add(allocated)
-
     @staticmethod
     def _generate_ip(context, subnets):
         try:
@@ -341,14 +249,6 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
             return True
         return False
 
-    @classmethod
-    def _check_gateway_in_subnet(cls, cidr, gateway):
-        """Validate that the gateway is on the subnet."""
-        ip = netaddr.IPAddress(gateway)
-        if ip.version == 4 or (ip.version == 6 and not ip.is_link_local()):
-            return ipam_utils.check_subnet_ip(cidr, gateway)
-        return True
-
     @staticmethod
     def _check_ip_in_allocation_pool(context, subnet_id, gateway_ip,
                                      ip_address):
@@ -851,92 +751,6 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
             if old_ra_mode_set or old_address_mode_set:
                 raise n_exc.InvalidInput(error_message=msg)
 
-    def _make_network_dict(self, network, fields=None,
-                           process_extensions=True):
-        res = {'id': network['id'],
-               'name': network['name'],
-               'tenant_id': network['tenant_id'],
-               'admin_state_up': network['admin_state_up'],
-               'mtu': network.get('mtu', constants.DEFAULT_NETWORK_MTU),
-               'status': network['status'],
-               'shared': network['shared'],
-               'subnets': [subnet['id']
-                           for subnet in network['subnets']]}
-        # TODO(pritesh): Move vlan_transparent to the extension module.
-        # vlan_transparent here is only added if the vlantransparent
-        # extension is enabled.
-        if ('vlan_transparent' in network and network['vlan_transparent'] !=
-            attributes.ATTR_NOT_SPECIFIED):
-            res['vlan_transparent'] = network['vlan_transparent']
-        # Call auxiliary extend functions, if any
-        if process_extensions:
-            self._apply_dict_extend_functions(
-                attributes.NETWORKS, res, network)
-        return self._fields(res, fields)
-
-    def _make_subnet_dict(self, subnet, fields=None):
-        res = {'id': subnet['id'],
-               'name': subnet['name'],
-               'tenant_id': subnet['tenant_id'],
-               'network_id': subnet['network_id'],
-               'ip_version': subnet['ip_version'],
-               'cidr': subnet['cidr'],
-               'subnetpool_id': subnet.get('subnetpool_id'),
-               'allocation_pools': [{'start': pool['first_ip'],
-                                     'end': pool['last_ip']}
-                                    for pool in subnet['allocation_pools']],
-               'gateway_ip': subnet['gateway_ip'],
-               'enable_dhcp': subnet['enable_dhcp'],
-               'ipv6_ra_mode': subnet['ipv6_ra_mode'],
-               'ipv6_address_mode': subnet['ipv6_address_mode'],
-               'dns_nameservers': [dns['address']
-                                   for dns in subnet['dns_nameservers']],
-               'host_routes': [{'destination': route['destination'],
-                                'nexthop': route['nexthop']}
-                               for route in subnet['routes']],
-               'shared': subnet['shared']
-               }
-        # Call auxiliary extend functions, if any
-        self._apply_dict_extend_functions(attributes.SUBNETS, res, subnet)
-        return self._fields(res, fields)
-
-    def _make_subnetpool_dict(self, subnetpool, fields=None):
-        default_prefixlen = str(subnetpool['default_prefixlen'])
-        min_prefixlen = str(subnetpool['min_prefixlen'])
-        max_prefixlen = str(subnetpool['max_prefixlen'])
-        res = {'id': subnetpool['id'],
-               'name': subnetpool['name'],
-               'tenant_id': subnetpool['tenant_id'],
-               'default_prefixlen': default_prefixlen,
-               'min_prefixlen': min_prefixlen,
-               'max_prefixlen': max_prefixlen,
-               'shared': subnetpool['shared'],
-               'prefixes': [prefix['cidr']
-                            for prefix in subnetpool['prefixes']],
-               'ip_version': subnetpool['ip_version'],
-               'default_quota': subnetpool['default_quota']}
-        return self._fields(res, fields)
-
-    def _make_port_dict(self, port, fields=None,
-                        process_extensions=True):
-        res = {"id": port["id"],
-               'name': port['name'],
-               "network_id": port["network_id"],
-               'tenant_id': port['tenant_id'],
-               "mac_address": port["mac_address"],
-               "admin_state_up": port["admin_state_up"],
-               "status": port["status"],
-               "fixed_ips": [{'subnet_id': ip["subnet_id"],
-                              'ip_address': ip["ip_address"]}
-                             for ip in port["fixed_ips"]],
-               "device_id": port["device_id"],
-               "device_owner": port["device_owner"]}
-        # Call auxiliary extend functions, if any
-        if process_extensions:
-            self._apply_dict_extend_functions(
-                attributes.PORTS, res, port)
-        return self._fields(res, fields)
-
     def _create_bulk(self, resource, context, request_items):
         objects = []
         collection = "%ss" % resource
@@ -1240,25 +1054,6 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
 
         return subnet
 
-    def _make_subnet_args(self, context, shared, detail,
-                          subnet, subnetpool_id=None):
-        args = {'tenant_id': detail.tenant_id,
-                'id': detail.subnet_id,
-                'name': subnet['name'],
-                'network_id': subnet['network_id'],
-                'ip_version': subnet['ip_version'],
-                'cidr': str(detail.subnet_cidr),
-                'subnetpool_id': subnetpool_id,
-                'enable_dhcp': subnet['enable_dhcp'],
-                'gateway_ip': self._gateway_ip_str(subnet, detail.subnet_cidr),
-                'shared': shared}
-        if subnet['ip_version'] == 6 and subnet['enable_dhcp']:
-            if attributes.is_attr_set(subnet['ipv6_ra_mode']):
-                args['ipv6_ra_mode'] = subnet['ipv6_ra_mode']
-            if attributes.is_attr_set(subnet['ipv6_address_mode']):
-                args['ipv6_address_mode'] = subnet['ipv6_address_mode']
-        return args
-
     def _make_subnet_request(self, tenant_id, subnet, subnetpool):
         cidr = subnet.get('cidr')
         subnet_id = subnet.get('id', uuidutils.generate_uuid())
@@ -1279,11 +1074,6 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
                                               subnet_id,
                                               cidr)
 
-    def _gateway_ip_str(self, subnet, cidr_net):
-        if subnet.get('gateway_ip') is attributes.ATTR_NOT_SPECIFIED:
-                return str(cidr_net.network + 1)
-        return subnet.get('gateway_ip')
-
     @oslo_db_api.wrap_db_retry(max_retries=db_api.MAX_RETRIES,
                                retry_on_request=True,
                                retry_on_deadlock=True)