diff --git a/neutron/db/extraroute_db.py b/neutron/db/extraroute_db.py index c4d2ada8a8..27cf11b934 100644 --- a/neutron/db/extraroute_db.py +++ b/neutron/db/extraroute_db.py @@ -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 diff --git a/neutron/db/l3_db.py b/neutron/db/l3_db.py index 203c998be3..58454ef62c 100644 --- a/neutron/db/l3_db.py +++ b/neutron/db/l3_db.py @@ -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', {}) diff --git a/neutron/db/l3_dvr_db.py b/neutron/db/l3_dvr_db.py index a77252de5d..c272dd2a77 100644 --- a/neutron/db/l3_dvr_db.py +++ b/neutron/db/l3_dvr_db.py @@ -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.""" diff --git a/neutron/db/l3_gwmode_db.py b/neutron/db/l3_gwmode_db.py index bb350f8e93..d0ec612fbd 100644 --- a/neutron/db/l3_gwmode_db.py +++ b/neutron/db/l3_gwmode_db.py @@ -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