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)