def test_tenant_dn_root(self): manager = aci_tenant.AciTenantManager( 'tn-test', self.cfg_manager, aci_universe.AciUniverse.establish_aci_session(self.cfg_manager), aci_universe.get_websocket_context(self.cfg_manager)) self.assertEqual('uni/tn-test', manager.tenant.dn) manager = aci_tenant.AciTenantManager( 'phys-test', self.cfg_manager, aci_universe.AciUniverse.establish_aci_session(self.cfg_manager), aci_universe.get_websocket_context(self.cfg_manager)) self.assertEqual('uni/phys-test', manager.tenant.dn) manager = aci_tenant.AciTenantManager( 'pod-test', self.cfg_manager, aci_universe.AciUniverse.establish_aci_session(self.cfg_manager), aci_universe.get_websocket_context(self.cfg_manager)) self.assertEqual('topology/pod-test', manager.tenant.dn)
def serve(self, context, tenants): # Verify differences global serving_tenants if self.ws_context.is_session_reconnected is True: self.reset(context, serving_tenants) self.ws_context.is_session_reconnected = False return try: serving_tenant_copy = serving_tenants serving_tenants = {} remove = set(serving_tenant_copy.keys()) - set(tenants) for removed in remove: # pop from the current state. This is not thread safe, but the # caller will not asynchronously use the 'observe' method so we # are gonna be fine. Make it Thread safe if required self._state.pop(removed, None) try: serving_tenant_copy[removed].kill() except Exception as e: LOG.debug(traceback.format_exc()) LOG.error('Killing manager failed for tenant %s: %s' % (removed, str(e))) continue for added in tenants: if added in serving_tenant_copy: # Move it back to serving tenant, no need to restart # the Thread try: serving_tenants[added] = serving_tenant_copy[added] except KeyError: LOG.debug("%s not found in %s during serving copy" % (added, serving_tenant_copy)) if (added not in serving_tenants or serving_tenants[added].is_dead()): LOG.debug("Adding new tenant %s" % added) # Start thread or replace broken one # Checking the 'dead' state helps those cases in which # a kill successfully happened but then the state was # rolled back by a further exception if added in serving_tenants: LOG.info( "Tenant %s was served but needs to be replaced: " "dead-%s", added, serving_tenants[added].is_dead()) # Cleanup the tenant's state serving_tenants[added].kill() serving_tenants[added] = aci_tenant.AciTenantManager( added, self.conf_manager, self.aci_session, self.ws_context, self.creation_succeeded, self.tenant_creation_failed, self.aim_system_id, self.get_resources) # A subscription might be leaking here serving_tenants[added]._unsubscribe_tenant() serving_tenants[added].start() except Exception as e: LOG.error(traceback.format_exc()) LOG.error('Failed to serve new tenants %s' % tenants) # Rollback served tenants serving_tenants = serving_tenant_copy raise e
def test_event_loop_failure(self): manager = aci_tenant.AciTenantManager( 'tn-1', self.cfg_manager, aci_universe.AciUniverse.establish_aci_session(self.cfg_manager), aci_universe.get_websocket_context(self.cfg_manager)) manager.ws_context.has_event = mock.Mock(side_effect=KeyError) # Main loop is not raising manager._main_loop()
def setUp(self): super(TestAciTenant, self).setUp() self._do_aci_mocks() self.backend_state = {} universe = aci_universe.AciUniverse().initialize( aim_cfg.ConfigManager(self.ctx, 'h1'), []) self.manager = aci_tenant.AciTenantManager( 'tn-tenant-1', self.cfg_manager, aci_universe.AciUniverse.establish_aci_session(self.cfg_manager), aci_universe.get_websocket_context(self.cfg_manager), get_resources=universe.get_resources) self.manager._get_full_state = mock.Mock( return_value=[self.backend_state])
def test_tenant_reset(self): manager = aci_tenant.AciTenantManager( 'tn-1', self.cfg_manager, aci_universe.AciUniverse.establish_aci_session(self.cfg_manager), aci_universe.get_websocket_context(self.cfg_manager)) manager.polling_yield = 0 self.assertIsNone(getattr(manager, 'scheduled_reset', None)) min = time.time() + (aci_tenant.RESET_INTERVAL - aci_tenant.RESET_INTERVAL * 0.2) max = time.time() + (aci_tenant.RESET_INTERVAL + aci_tenant.RESET_INTERVAL * 0.2) + 1 manager._unsubscribe_tenant = mock.Mock() manager.num_loop_runs = 1 manager._main_loop() self.assertTrue(min < manager.scheduled_reset < max) manager.scheduled_reset = 0 # We don't want subscribe tenant to screw up the reset time manager._subscribe_tenant = mock.Mock() self.assertEqual(0, manager._unsubscribe_tenant.call_count) manager.num_loop_runs = 1 # Exception is raised here manager._main_loop() self.assertEqual(1, manager._unsubscribe_tenant.call_count)