]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
l3_db: refactor L3_NAT_DB_mixin
authorIsaku Yamahata <isaku.yamahata@intel.com>
Tue, 22 Jul 2014 08:24:41 +0000 (17:24 +0900)
committerIsaku Yamahata <isaku.yamahata@intel.com>
Tue, 5 Aug 2014 03:18:23 +0000 (12:18 +0900)
This patch refactors L3_NAT_DB_mixin to split out db operation and
rpc notification.

l3 plugin for routervm will implement the method for REST resource
operation as something like
    def op_resource():
        additional operation
        with session
            additional db operation
            db operation of super class => super().db_op_resoruce
            additional db operation
        additional operation
        l3 rpc notification

However, The current L3_NAT_DB_mixin intermixes db operations with l3 rpc.
So it is difficult to reuse the db operation code without l3 rpc.
This patch splits db operation from l3 rpc notification so that
db operation logic can be reused easily. Thus the l3 plugin for routervm
will be simplified with this patch.

Related to blueprint cisco-routing-service-vm
Related to blueprint l3-plugin-brocade-vyatta-vrouter

Change-Id: I88f6574f921596426e1a31c9ff2251aa6f4674b8

neutron/db/extraroute_db.py
neutron/db/l3_db.py
neutron/db/l3_dvr_db.py
neutron/db/l3_gwmode_db.py

index c4d2ada8a872d6bb643dd764dd9165db789500f7..27cf11b9341eb2e58cec37ffcdf639131b981cb2 100644 (file)
@@ -51,11 +51,11 @@ class RouterRoute(model_base.BASEV2, models_v2.Route):
                                                   cascade='delete'))
 
 
-class ExtraRoute_db_mixin(l3_db.L3_NAT_db_mixin):
+class ExtraRoute_dbonly_mixin(l3_db.L3_NAT_dbonly_mixin):
     """Mixin class to support extra route configuration on router."""
 
     def _extend_router_dict_extraroute(self, router_res, router_db):
-        router_res['routes'] = (ExtraRoute_db_mixin.
+        router_res['routes'] = (ExtraRoute_dbonly_mixin.
                                 _make_extra_route_list(
                                     router_db['route_list']
                                 ))
@@ -71,7 +71,7 @@ class ExtraRoute_db_mixin(l3_db.L3_NAT_db_mixin):
             if 'routes' in r:
                 self._update_extra_routes(context, router_db, r['routes'])
             routes = self._get_extra_routes_by_router_id(context, id)
-        router_updated = super(ExtraRoute_db_mixin, self).update_router(
+        router_updated = super(ExtraRoute_dbonly_mixin, self).update_router(
             context, id, router)
         router_updated['routes'] = routes
 
@@ -159,7 +159,7 @@ class ExtraRoute_db_mixin(l3_db.L3_NAT_db_mixin):
 
     def get_router(self, context, id, fields=None):
         with context.session.begin(subtransactions=True):
-            router = super(ExtraRoute_db_mixin, self).get_router(
+            router = super(ExtraRoute_dbonly_mixin, self).get_router(
                 context, id, fields)
             return router
 
@@ -167,14 +167,15 @@ class ExtraRoute_db_mixin(l3_db.L3_NAT_db_mixin):
                     sorts=None, limit=None, marker=None,
                     page_reverse=False):
         with context.session.begin(subtransactions=True):
-            routers = super(ExtraRoute_db_mixin, self).get_routers(
+            routers = super(ExtraRoute_dbonly_mixin, self).get_routers(
                 context, filters, fields, sorts=sorts, limit=limit,
                 marker=marker, page_reverse=page_reverse)
             return routers
 
     def _confirm_router_interface_not_in_use(self, context, router_id,
                                              subnet_id):
-        super(ExtraRoute_db_mixin, self)._confirm_router_interface_not_in_use(
+        super(ExtraRoute_dbonly_mixin,
+            self)._confirm_router_interface_not_in_use(
             context, router_id, subnet_id)
         subnet_db = self._core_plugin._get_subnet(context, subnet_id)
         subnet_cidr = netaddr.IPNetwork(subnet_db['cidr'])
@@ -183,3 +184,8 @@ class ExtraRoute_db_mixin(l3_db.L3_NAT_db_mixin):
             if netaddr.all_matching_cidrs(route['nexthop'], [subnet_cidr]):
                 raise extraroute.RouterInterfaceInUseByRoute(
                     router_id=router_id, subnet_id=subnet_id)
+
+
+class ExtraRoute_db_mixin(ExtraRoute_dbonly_mixin, l3_db.L3_NAT_db_mixin):
+    """Mixin class to support extra route configuration on router with rpc."""
+    pass
index 203c998be398297275598c63acd1200ea56d87b0..58454ef62cd08ac94a5f2d7fbf58b861851be3b1 100644 (file)
@@ -78,7 +78,7 @@ class FloatingIP(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant):
     status = sa.Column(sa.String(16))
 
 
-class L3_NAT_db_mixin(l3.RouterPluginBase):
+class L3_NAT_dbonly_mixin(l3.RouterPluginBase):
     """Mixin class to add L3/NAT router methods to db_base_plugin_v2."""
 
     router_device_owners = (
@@ -87,16 +87,6 @@ class L3_NAT_db_mixin(l3.RouterPluginBase):
         DEVICE_OWNER_FLOATINGIP
     )
 
-    @property
-    def l3_rpc_notifier(self):
-        if not hasattr(self, '_l3_rpc_notifier'):
-            self._l3_rpc_notifier = l3_rpc_agent_api.L3AgentNotifyAPI()
-        return self._l3_rpc_notifier
-
-    @l3_rpc_notifier.setter
-    def l3_rpc_notifier(self, value):
-        self._l3_rpc_notifier = value
-
     @property
     def _core_plugin(self):
         return manager.NeutronManager.get_plugin()
@@ -169,17 +159,13 @@ class L3_NAT_db_mixin(l3.RouterPluginBase):
         if gw_info != attributes.ATTR_NOT_SPECIFIED:
             candidates = self._check_router_needs_rescheduling(
                 context, id, gw_info)
-            payload = {'gw_exists': True}
         else:
             candidates = None
-            payload = {'gw_exists': False}
         router_db = self._update_router_db(context, id, r, gw_info)
         if candidates:
             l3_plugin = manager.NeutronManager.get_service_plugins().get(
                 constants.L3_ROUTER_NAT)
             l3_plugin.reschedule_router(context, id, candidates)
-        self.l3_rpc_notifier.routers_updated(context, [router_db['id']],
-                                             None, payload)
         return self._make_router_dict(router_db)
 
     def _check_router_needs_rescheduling(self, context, router_id, gw_info):
@@ -357,8 +343,6 @@ class L3_NAT_db_mixin(l3.RouterPluginBase):
                 self._core_plugin._delete_port(context.elevated(),
                                                ports[0]['id'])
 
-        self.l3_rpc_notifier.router_deleted(context, id)
-
     def get_router(self, context, id, fields=None):
         router = self._get_router(context, id)
         return self._make_router_dict(router, fields)
@@ -469,23 +453,15 @@ class L3_NAT_db_mixin(l3.RouterPluginBase):
              'device_owner': owner,
              'name': ''}})
 
-    def notify_router_interface_action(
-            self, context, router_id, tenant_id, port_id, subnet_id, action):
-        l3_method = '%s_router_interface' % action
-        self.l3_rpc_notifier.routers_updated(context, [router_id],
-            l3_method, {'subnet_id': subnet_id})
-
-        mapping = {'add': 'create', 'remove': 'delete'}
-        info = {
+    @staticmethod
+    def _make_router_interface_info(
+            router_id, tenant_id, port_id, subnet_id):
+        return {
             'id': router_id,
             'tenant_id': tenant_id,
             'port_id': port_id,
             'subnet_id': subnet_id
         }
-        notifier = n_rpc.get_notifier('network')
-        router_event = 'router.interface.%s' % mapping[action]
-        notifier.info(context, router_event, {'router_interface': info})
-        return info
 
     def add_router_interface(self, context, router_id, interface_info):
         add_by_port, add_by_sub = self._validate_interface_info(interface_info)
@@ -498,9 +474,9 @@ class L3_NAT_db_mixin(l3.RouterPluginBase):
             port = self._add_interface_by_subnet(
                 context, router_id, interface_info['subnet_id'], device_owner)
 
-        return self.notify_router_interface_action(
-            context, router_id, port['tenant_id'], port['id'],
-            port['fixed_ips'][0]['subnet_id'], 'add')
+        return self._make_router_interface_info(
+            router_id, port['tenant_id'], port['id'],
+            port['fixed_ips'][0]['subnet_id'])
 
     def _confirm_router_interface_not_in_use(self, context, router_id,
                                              subnet_id):
@@ -568,9 +544,8 @@ class L3_NAT_db_mixin(l3.RouterPluginBase):
             port, subnet = self._remove_interface_by_subnet(
                 context, router_id, subnet_id, device_owner)
 
-        return self.notify_router_interface_action(
-            context, router_id, port['tenant_id'], port['id'],
-            subnet['id'], 'remove')
+        return self._make_router_interface_info(router_id, port['tenant_id'],
+                                                port['id'], subnet['id'])
 
     def _get_floatingip(self, context, id):
         try:
@@ -739,9 +714,8 @@ class L3_NAT_db_mixin(l3.RouterPluginBase):
                               'router_id': router_id,
                               'last_known_router_id': previous_router_id})
 
-    def create_floatingip(
-        self, context, floatingip,
-        initial_status=l3_constants.FLOATINGIP_STATUS_ACTIVE):
+    def create_floatingip(self, context, floatingip,
+            initial_status=l3_constants.FLOATINGIP_STATUS_ACTIVE):
         fip = floatingip['floatingip']
         tenant_id = self._get_tenant_id_for_create(context, fip)
         fip_id = uuidutils.generate_uuid()
@@ -785,34 +759,30 @@ class L3_NAT_db_mixin(l3.RouterPluginBase):
                                    floatingip_db, external_port)
             context.session.add(floatingip_db)
 
-        router_id = floatingip_db['router_id']
-        if router_id:
-            self.l3_rpc_notifier.routers_updated(
-                context, [router_id],
-                'create_floatingip', {})
         return self._make_floatingip_dict(floatingip_db)
 
-    def update_floatingip(self, context, id, floatingip):
+    def _update_floatingip(self, context, id, floatingip):
         fip = floatingip['floatingip']
         with context.session.begin(subtransactions=True):
             floatingip_db = self._get_floatingip(context, id)
+            old_floatingip = self._make_floatingip_dict(floatingip_db)
             fip['tenant_id'] = floatingip_db['tenant_id']
             fip['id'] = id
             fip_port_id = floatingip_db['floating_port_id']
-            before_router_id = floatingip_db['router_id']
             self._update_fip_assoc(context, fip, floatingip_db,
                                    self._core_plugin.get_port(
                                        context.elevated(), fip_port_id))
-        router_ids = []
-        if before_router_id:
-            router_ids.append(before_router_id)
-        router_id = floatingip_db['router_id']
-        if router_id and router_id != before_router_id:
-            router_ids.append(router_id)
-        if router_ids:
-            self.l3_rpc_notifier.routers_updated(
-                context, router_ids, 'update_floatingip', {})
-        return self._make_floatingip_dict(floatingip_db)
+        return old_floatingip, self._make_floatingip_dict(floatingip_db)
+
+    def _floatingips_to_router_ids(self, floatingips):
+        return list(set([floatingip['router_id']
+                         for floatingip in floatingips
+                         if floatingip['router_id']]))
+
+    def update_floatingip(self, context, id, floatingip):
+        _old_floatingip, floatingip = self._update_floatingip(
+            context, id, floatingip)
+        return floatingip
 
     def update_floatingip_status(self, context, floatingip_id, status):
         """Update operational status for floating IP in neutron DB."""
@@ -820,7 +790,7 @@ class L3_NAT_db_mixin(l3.RouterPluginBase):
             FloatingIP.id == floatingip_id)
         fip_query.update({'status': status}, synchronize_session=False)
 
-    def delete_floatingip(self, context, id):
+    def _delete_floatingip(self, context, id):
         floatingip = self._get_floatingip(context, id)
         router_id = floatingip['router_id']
         with context.session.begin(subtransactions=True):
@@ -828,10 +798,10 @@ class L3_NAT_db_mixin(l3.RouterPluginBase):
             self._core_plugin.delete_port(context.elevated(),
                                           floatingip['floating_port_id'],
                                           l3_port_check=False)
-        if router_id:
-            self.l3_rpc_notifier.routers_updated(
-                context, [router_id],
-                'delete_floatingip', {})
+        return router_id
+
+    def delete_floatingip(self, context, id):
+        self._delete_floatingip(context, id)
 
     def get_floatingip(self, context, id, fields=None):
         floatingip = self._get_floatingip(context, id)
@@ -890,7 +860,7 @@ class L3_NAT_db_mixin(l3.RouterPluginBase):
                           {'port_id': port_db['id'],
                            'port_owner': port_db['device_owner']})
 
-    def disassociate_floatingips(self, context, port_id, do_notify=True):
+    def disassociate_floatingips(self, context, port_id):
         """Disassociate all floating IPs linked to specific port.
 
         @param port_id: ID of the port to disassociate floating IPs.
@@ -908,20 +878,8 @@ class L3_NAT_db_mixin(l3.RouterPluginBase):
                 floating_ip.update({'fixed_port_id': None,
                                     'fixed_ip_address': None,
                                     'router_id': None})
-        if do_notify:
-            self.notify_routers_updated(context, router_ids)
-            # since caller assumes that we handled notifications on its
-            # behalf, return nothing
-            return
-
         return router_ids
 
-    def notify_routers_updated(self, context, router_ids):
-        if router_ids:
-            self.l3_rpc_notifier.routers_updated(
-                context, list(router_ids),
-                'disassociate_floatingips', {})
-
     def _build_routers_list(self, context, routers, gw_ports):
         for router in routers:
             gw_port_id = router['gw_port_id']
@@ -1069,3 +1027,122 @@ class L3_NAT_db_mixin(l3.RouterPluginBase):
         self._process_floating_ips(context, routers_dict, floating_ips)
         self._process_interfaces(routers_dict, interfaces)
         return routers_dict.values()
+
+
+class L3RpcNotifierMixin(object):
+    """Mixin class to add rpc notifier attribute to db_base_plugin_v2."""
+
+    @property
+    def l3_rpc_notifier(self):
+        if not hasattr(self, '_l3_rpc_notifier'):
+            self._l3_rpc_notifier = l3_rpc_agent_api.L3AgentNotifyAPI()
+        return self._l3_rpc_notifier
+
+    @l3_rpc_notifier.setter
+    def l3_rpc_notifier(self, value):
+        self._l3_rpc_notifier = value
+
+    def notify_router_updated(self, context, router_id,
+                              operation=None, data=None):
+        if router_id:
+            self.l3_rpc_notifier.routers_updated(
+                context, [router_id], operation, data)
+
+    def notify_routers_updated(self, context, router_ids,
+                               operation=None, data=None):
+        if router_ids:
+            self.l3_rpc_notifier.routers_updated(
+                context, router_ids, operation, data)
+
+    def notify_router_deleted(self, context, router_id):
+        self.l3_rpc_notifier.router_deleted(context, router_id)
+
+
+class L3_NAT_db_mixin(L3_NAT_dbonly_mixin, L3RpcNotifierMixin):
+    """Mixin class to add rpc notifier methods to db_base_plugin_v2."""
+
+    def update_router(self, context, id, router):
+        r = router['router']
+        payload = {'gw_exists':
+                   r.get(EXTERNAL_GW_INFO, attributes.ATTR_NOT_SPECIFIED) !=
+                   attributes.ATTR_NOT_SPECIFIED}
+        router_dict = super(L3_NAT_db_mixin, self).update_router(context,
+                                                                 id, router)
+        self.notify_router_updated(context, router_dict['id'], None, payload)
+        return router_dict
+
+    def delete_router(self, context, id):
+        super(L3_NAT_db_mixin, self).delete_router(context, id)
+        self.notify_router_deleted(context, id)
+
+    def notify_router_interface_action(
+            self, context, router_interface_info, action):
+        l3_method = '%s_router_interface' % action
+        super(L3_NAT_db_mixin, self).notify_routers_updated(
+            context, [router_interface_info['id']], l3_method,
+            {'subnet_id': router_interface_info['subnet_id']})
+
+        mapping = {'add': 'create', 'remove': 'delete'}
+        notifier = n_rpc.get_notifier('network')
+        router_event = 'router.interface.%s' % mapping[action]
+        notifier.info(context, router_event,
+                      {'router_interface': router_interface_info})
+
+    def add_router_interface(self, context, router_id, interface_info):
+        router_interface_info = super(
+            L3_NAT_db_mixin, self).add_router_interface(
+                context, router_id, interface_info)
+        self.notify_router_interface_action(
+            context, router_interface_info, 'add')
+        return router_interface_info
+
+    def remove_router_interface(self, context, router_id, interface_info):
+        router_interface_info = super(
+            L3_NAT_db_mixin, self).remove_router_interface(
+                context, router_id, interface_info)
+        self.notify_router_interface_action(
+            context, router_interface_info, 'remove')
+        return router_interface_info
+
+    def create_floatingip(self, context, floatingip,
+            initial_status=l3_constants.FLOATINGIP_STATUS_ACTIVE):
+        floatingip_dict = super(L3_NAT_db_mixin, self).create_floatingip(
+            context, floatingip, initial_status)
+        router_id = floatingip_dict['router_id']
+        self.notify_router_updated(context, router_id, 'create_floatingip', {})
+        return floatingip_dict
+
+    def update_floatingip(self, context, id, floatingip):
+        old_floatingip, floatingip = self._update_floatingip(
+            context, id, floatingip)
+        router_ids = self._floatingips_to_router_ids(
+            [old_floatingip, floatingip])
+        super(L3_NAT_db_mixin, self).notify_routers_updated(
+            context, router_ids, 'update_floatingip', {})
+        return floatingip
+
+    def delete_floatingip(self, context, id):
+        router_id = self._delete_floatingip(context, id)
+        self.notify_router_updated(context, router_id, 'delete_floatingip', {})
+
+    def disassociate_floatingips(self, context, port_id, do_notify=True):
+        """Disassociate all floating IPs linked to specific port.
+
+        @param port_id: ID of the port to disassociate floating IPs.
+        @param do_notify: whether we should notify routers right away.
+        @return: set of router-ids that require notification updates
+                 if do_notify is False, otherwise None.
+        """
+        router_ids = super(L3_NAT_db_mixin, self).disassociate_floatingips(
+            context, port_id)
+        if do_notify:
+            self.notify_routers_updated(context, router_ids)
+            # since caller assumes that we handled notifications on its
+            # behalf, return nothing
+            return
+
+        return router_ids
+
+    def notify_routers_updated(self, context, router_ids):
+        super(L3_NAT_db_mixin, self).notify_routers_updated(
+            context, list(router_ids), 'disassociate_floatingips', {})
index a77252de5dfd840b0d3d3cc2ee9ee515e50256d7..c272dd2a77f78a67fb97fdb4194daed25c3e0e1c 100644 (file)
@@ -180,9 +180,12 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin,
                 context.elevated(), router_id, port['network_id'],
                 port['fixed_ips'][0]['subnet_id'])
 
-        return self.notify_router_interface_action(
-            context, router_id, port['tenant_id'], port['id'],
-            port['fixed_ips'][0]['subnet_id'], 'add')
+        router_interface_info = self._make_router_interface_info(
+            router_id, port['tenant_id'], port['id'],
+            port['fixed_ips'][0]['subnet_id'])
+        self.notify_router_interface_action(
+            context, router_interface_info, 'add')
+        return router_interface_info
 
     def remove_router_interface(self, context, router_id, interface_info):
         if not interface_info:
@@ -205,9 +208,12 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin,
             self.delete_csnat_router_interface_ports(
                 context.elevated(), router, subnet_id=subnet_id)
 
-        return self.notify_router_interface_action(
-            context, router_id, port['tenant_id'], port['id'],
-            subnet['id'], 'remove')
+        router_interface_info = self._make_router_interface_info(
+            router_id, port['tenant_id'], port['id'],
+            port['fixed_ips'][0]['subnet_id'])
+        self.notify_router_interface_action(
+            context, router_interface_info, 'remove')
+        return router_interface_info
 
     def get_snat_sync_interfaces(self, context, router_ids):
         """Query router interfaces that relate to list of router_ids."""
index bb350f8e93b7d14116a1b2f4366192f1e2c54711..d0ec612fbdbe4f06aa581be181ad368dc07bc3ed 100644 (file)
@@ -31,7 +31,7 @@ setattr(l3_db.Router, 'enable_snat',
                   nullable=False))
 
 
-class L3_NAT_db_mixin(l3_db.L3_NAT_db_mixin):
+class L3_NAT_dbonly_mixin(l3_db.L3_NAT_dbonly_mixin):
     """Mixin class to add configurable gateway modes."""
 
     # Register dict extend functions for ports and networks
@@ -56,7 +56,7 @@ class L3_NAT_db_mixin(l3_db.L3_NAT_db_mixin):
             router.enable_snat = enable_snat
 
         # Calls superclass, pass router db object for avoiding re-loading
-        super(L3_NAT_db_mixin, self)._update_router_gw_info(
+        super(L3_NAT_dbonly_mixin, self)._update_router_gw_info(
             context, router_id, info, router=router)
         # Returning the router might come back useful if this
         # method is overridden in child classes
@@ -70,3 +70,7 @@ class L3_NAT_db_mixin(l3_db.L3_NAT_db_mixin):
                 # Add enable_snat key
                 rtr['enable_snat'] = rtr[EXTERNAL_GW_INFO]['enable_snat']
         return routers
+
+
+class L3_NAT_db_mixin(L3_NAT_dbonly_mixin, l3_db.L3_NAT_db_mixin):
+    pass