def test_updates(self): primary = queue.ExclusiveResourceProcessor(FAKE_ID) not_primary = queue.ExclusiveResourceProcessor(FAKE_ID) primary.queue_update(queue.ResourceUpdate(FAKE_ID, 0)) not_primary.queue_update(queue.ResourceUpdate(FAKE_ID, 0)) for update in not_primary.updates(): raise Exception("Only the primary should process a resource") self.assertEqual(2, len([i for i in primary.updates()]))
def test_updates(self): master = queue.ExclusiveResourceProcessor(FAKE_ID) not_master = queue.ExclusiveResourceProcessor(FAKE_ID) master.queue_update(queue.ResourceUpdate(FAKE_ID, 0)) not_master.queue_update(queue.ResourceUpdate(FAKE_ID, 0)) for update in not_master.updates(): raise Exception("Only the master should process a resource") self.assertEqual(2, len([i for i in master.updates()]))
def create_pd_router_update(self): router_id = None update = queue.ResourceUpdate(router_id, PRIORITY_PD_UPDATE, timestamp=timeutils.utcnow(), action=PD_UPDATE) self._queue.add(update)
def router_removed_from_agent(self, context, payload): LOG.debug('Got router removed from agent :%r', payload) router_id = payload['router_id'] update = queue.ResourceUpdate(router_id, PRIORITY_RPC, action=DELETE_ROUTER) self._queue.add(update)
def router_deleted(self, context, router_id): """Deal with router deletion RPC message.""" LOG.debug('Got router deleted notification for %s', router_id) update = queue.ResourceUpdate(router_id, PRIORITY_RPC, action=DELETE_ROUTER) self._queue.add(update)
def subnet_update_end(self, context, payload): """Handle the subnet.update.end notification event.""" update = queue.ResourceUpdate(payload['subnet']['network_id'], payload.get('priority', DEFAULT_PRIORITY), action='_subnet_update', resource=payload) self._queue.add(update)
def test_hit_retry_limit(self): tries = 1 rpqueue = queue.ResourceProcessingQueue() update = queue.ResourceUpdate(FAKE_ID, PRIORITY_RPC, tries=tries) rpqueue.add(update) self.assertFalse(update.hit_retry_limit()) rpqueue.add(update) self.assertTrue(update.hit_retry_limit())
def port_create_end(self, context, payload): """Handle the port.create.end notification event.""" created_port = dhcp.DictModel(payload['port']) update = queue.ResourceUpdate(created_port.network_id, payload.get('priority', DEFAULT_PRIORITY), action='_port_create', resource=created_port) self._queue.add(update)
def network_update(self, context, **kwargs): network_id = kwargs['network']['id'] LOG.debug("Got network %s update", network_id) for ri in self.router_info.values(): update = queue.ResourceUpdate(ri.router_id, PRIORITY_RPC, action=UPDATE_NETWORK, resource=network_id) self._queue.add(update)
def routers_updated(self, context, routers): """Deal with routers modification and creation RPC message.""" LOG.debug('Got routers updated notification :%s', routers) if routers: # This is needed for backward compatibility if isinstance(routers[0], dict): routers = [router['id'] for router in routers] for id in routers: update = queue.ResourceUpdate(id, PRIORITY_RPC) self._queue.add(update)
def port_delete_end(self, context, payload): """Handle the port.delete.end notification event.""" network_id = self._get_network_lock_id(payload) if not network_id: return update = queue.ResourceUpdate(network_id, payload.get('priority', DEFAULT_PRIORITY), action='_port_delete', resource=payload) self._queue.add(update)
def network_update(self, context, **kwargs): network_id = kwargs['network']['id'] for ri in self.router_info.values(): ports = list(ri.internal_ports) if ri.ex_gw_port: ports.append(ri.ex_gw_port) port_belongs = lambda p: p['network_id'] == network_id if any(port_belongs(p) for p in ports): update = queue.ResourceUpdate(ri.router_id, PRIORITY_SYNC_ROUTERS_TASK) self._resync_router(update)
def port_update_end(self, context, payload): """Handle the port.update.end notification event.""" updated_port = dhcp.DictModel(payload['port']) if self.cache.is_port_message_stale(updated_port): LOG.debug("Discarding stale port update: %s", updated_port) return update = queue.ResourceUpdate(updated_port.network_id, payload.get('priority', DEFAULT_PRIORITY), action='_port_update', resource=updated_port) self._queue.add(update)
def _process_network_update(self, router_id, network_id): ri = self.router_info.get(router_id) if not ri: return LOG.debug("Checking if router %s is plugged to the network %s", ri, network_id) ports = list(ri.internal_ports) if ri.ex_gw_port: ports.append(ri.ex_gw_port) port_belongs = lambda p: p['network_id'] == network_id if any(port_belongs(p) for p in ports): update = queue.ResourceUpdate( ri.router_id, PRIORITY_SYNC_ROUTERS_TASK) self._resync_router(update)
def _process_routers_if_compatible(self, routers, update): process_result = True for router in routers: if router['id'] != update.id: # Don't do the work here, instead create a new update and # enqueue it, since there could be another thread working # on it already and we don't want to race. new_action = RELATED_ACTION_MAP.get(update.action, ADD_UPDATE_RELATED_ROUTER) new_update = queue.ResourceUpdate( router['id'], priority=PRIORITY_RELATED_ROUTER, action=new_action) self._queue.add(new_update) LOG.debug( 'Queued a router update for %(router_id)s ' '(related router %(related_router_id)s). ' 'Original event action %(action)s, ' 'priority %(priority)s. ' 'New event action %(new_action)s, ' 'priority %(new_priority)s', { 'router_id': router['id'], 'related_router_id': update.id, 'action': update.action, 'priority': update.priority, 'new_action': new_update.action, 'new_priority': new_update.priority }) continue try: self._process_router_if_compatible(router) except l3_exc.RouterNotCompatibleWithAgent as e: log_verbose_exc(e.msg, router) # Was the router previously handled by this agent? if router['id'] in self.router_info: LOG.error("Removing incompatible router '%s'", router['id']) self._safe_router_removed(router['id']) except Exception: log_verbose_exc( "Failed to process compatible router: %s" % update.id, router) process_result = False return process_result
def fetch_and_sync_all_routers(self, context, ns_manager): prev_router_ids = set(self.router_info) curr_router_ids = set() timestamp = timeutils.utcnow() router_ids = [] chunk = [] is_snat_agent = (self.conf.agent_mode == lib_const.L3_AGENT_MODE_DVR_SNAT) try: router_ids = self.plugin_rpc.get_router_ids(context) # fetch routers by chunks to reduce the load on server and to # start router processing earlier for i in range(0, len(router_ids), self.sync_routers_chunk_size): chunk = router_ids[i:i + self.sync_routers_chunk_size] routers = self.plugin_rpc.get_routers(context, chunk) LOG.debug('Processing :%r', routers) for r in routers: curr_router_ids.add(r['id']) ns_manager.keep_router(r['id']) if r.get('distributed'): # need to keep fip namespaces as well ext_net_id = (r['external_gateway_info'] or {}).get( 'network_id') if ext_net_id: ns_manager.keep_ext_net(ext_net_id) elif is_snat_agent and not r.get('ha'): ns_manager.ensure_snat_cleanup(r['id']) update = queue.ResourceUpdate( r['id'], PRIORITY_SYNC_ROUTERS_TASK, resource=r, action=ADD_UPDATE_ROUTER, timestamp=timestamp) self._queue.add(update) except oslo_messaging.MessagingTimeout: if self.sync_routers_chunk_size > SYNC_ROUTERS_MIN_CHUNK_SIZE: self.sync_routers_chunk_size = max( self.sync_routers_chunk_size // 2, SYNC_ROUTERS_MIN_CHUNK_SIZE) LOG.error('Server failed to return info for routers in ' 'required time, decreasing chunk size to: %s', self.sync_routers_chunk_size) else: LOG.error('Server failed to return info for routers in ' 'required time even with min chunk size: %s. ' 'It might be under very high load or ' 'just inoperable', self.sync_routers_chunk_size) raise except oslo_messaging.MessagingException: failed_routers = chunk or router_ids LOG.exception("Failed synchronizing routers '%s' " "due to RPC error", failed_routers) raise l3_exc.AbortSyncRouters() self.fullsync = False LOG.debug("periodic_sync_routers_task successfully completed") # adjust chunk size after successful sync if self.sync_routers_chunk_size < SYNC_ROUTERS_MAX_CHUNK_SIZE: self.sync_routers_chunk_size = min( self.sync_routers_chunk_size + SYNC_ROUTERS_MIN_CHUNK_SIZE, SYNC_ROUTERS_MAX_CHUNK_SIZE) # Delete routers that have disappeared since the last sync for router_id in prev_router_ids - curr_router_ids: ns_manager.keep_router(router_id) update = queue.ResourceUpdate(router_id, PRIORITY_SYNC_ROUTERS_TASK, timestamp=timestamp, action=DELETE_ROUTER) self._queue.add(update)