def setUp(self, klass=aim_universe.AimDbUniverse): super(TestAimDbUniverseBase, self).setUp() self.klass = klass self.universe = self.klass().initialize( aim_cfg.ConfigManager(self.ctx, ''), []) self.tree_mgr = tree_manager.HashTreeManager() self.monitor_universe = False
def hashtree(ctx): aim_ctx = context.AimContext(store=api.get_store(expire_on_commit=True)) tree_mgr = tree_manager.HashTreeManager() manager = aim_manager.AimManager() ctx.obj['manager'] = manager ctx.obj['tree_mgr'] = tree_mgr ctx.obj['aim_ctx'] = aim_ctx
def test_cleanup_state(self, tree_type=tree_manager.CONFIG_TREE): tree_mgr = tree_manager.HashTreeManager() aim_mgr = aim_manager.AimManager() aim_mgr.create(self.ctx, resource.Tenant(name='t1')) bd1 = resource.BridgeDomain(tenant_name='t1', name='bd1', display_name='somestuff', vrf_name='vrf') bd1_fault = aim_status.AciFault( fault_code='901', external_identifier='uni/tn-t1/BD-bd1/fault-901', description='failure901') aim_mgr.create(self.ctx, bd1) aim_mgr.set_fault(self.ctx, bd1, bd1_fault) self.assertRaises(Exception, self.universe.cleanup_state, 'tn-t1') trees = tree_mgr.find(self.ctx, tree=tree_type) # tenant still there, trees not empty. self.assertEqual(1, len(trees)) aim_mgr.clear_fault(self.ctx, bd1_fault) aim_mgr.delete(self.ctx, resource.Tenant(name='t1'), cascade=True) self.universe.cleanup_state(self.ctx, 'tn-t1') trees = tree_mgr.find(self.ctx, tree=tree_type) self.assertEqual(0, len(trees))
def __init__(self, conf): self.run_daemon_loop = True self.host = conf.aim.aim_service_identifier aim_ctx = context.AimContext(store=api.get_store()) # This config manager is shared between multiple threads. Therefore # all DB activity through this config manager will use the same # DB session which can result in conflicts. # TODO(amitbose) Fix ConfigManager to not use cached AimContext self.conf_manager = aim_cfg.ConfigManager(aim_ctx, self.host) self.k8s_watcher = None self.single_aid = False if conf.aim.aim_store == 'k8s': self.single_aid = True self.k8s_watcher = k8s_watcher.K8sWatcher() self.k8s_watcher.run() self.multiverse = [] # Define multiverse pairs, First position is desired state self.multiverse += [ # Configuration Universe (AIM to ACI) {DESIRED: aim_universe.AimDbUniverse().initialize( self.conf_manager, self.multiverse), CURRENT: aci_universe.AciUniverse().initialize( self.conf_manager, self.multiverse)}, # Operational Universe (ACI to AIM) {DESIRED: aci_universe.AciOperationalUniverse().initialize( self.conf_manager, self.multiverse), CURRENT: aim_universe.AimDbOperationalUniverse().initialize( self.conf_manager, self.multiverse)}, # Monitored Universe (ACI to AIM) {DESIRED: aci_universe.AciMonitoredUniverse().initialize( self.conf_manager, self.multiverse), CURRENT: aim_universe.AimDbMonitoredUniverse().initialize( self.conf_manager, self.multiverse)}, ] # Operational Universes. ACI operational info will be synchronized into # AIM's self.manager = aim_manager.AimManager() self.tree_manager = tree_manager.HashTreeManager() self.agent_id = 'aid-%s' % self.host self.agent = resource.Agent(id=self.agent_id, agent_type=AGENT_TYPE, host=self.host, binary_file=AGENT_BINARY, description=AGENT_DESCRIPTION, version=AGENT_VERSION) # Register agent self.agent = self.manager.create(aim_ctx, self.agent, overwrite=True) # Report procedure should happen asynchronously self.polling_interval = self.conf_manager.get_option_and_subscribe( self._change_polling_interval, 'agent_polling_interval', group='aim') self.report_interval = self.conf_manager.get_option_and_subscribe( self._change_report_interval, 'agent_report_interval', group='aim') self.squash_time = self.conf_manager.get_option_and_subscribe( self._change_squash_time, 'agent_event_squash_time', group='aim') self._spawn_heartbeat_loop() self.events = event_handler.EventHandler().initialize( self.conf_manager) self.max_down_time = 4 * self.report_interval
def setUp(self, initialize_hooks=True): super(TestAimDBBase, self).setUp() self.test_id = uuidutils.generate_uuid() aim_cfg.OPTION_SUBSCRIBER_MANAGER = None aci_universe.ws_context = None if not os.environ.get(K8S_STORE_VENV): CONF.set_override('aim_store', 'sql', 'aim') self.engine = api.get_engine() if not TestAimDBBase._TABLES_ESTABLISHED: model_base.Base.metadata.create_all(self.engine) TestAimDBBase._TABLES_ESTABLISHED = True # Uncomment the line below to log SQL statements. Additionally, to # log results of queries, change INFO to DEBUG # # logging.getLogger('sqlalchemy.engine').setLevel(logging.DEBUG) def clear_tables(): with self.engine.begin() as conn: for table in reversed( model_base.Base.metadata.sorted_tables): conn.execute(table.delete()) self.addCleanup(clear_tables) self.old_add_commit_hook = ( aim_store.SqlAlchemyStore.add_commit_hook) aim_store.SqlAlchemyStore.add_commit_hook = _add_commit_hook def restore_commit_hook(): aim_store.SqlAlchemyStore.add_commit_hook = ( self.old_add_commit_hook) self.addCleanup(restore_commit_hook) aim_store.SqlAlchemyStore._after_transaction_end_2 = ( _after_transaction_end_2) else: CONF.set_override('aim_store', 'k8s', 'aim') CONF.set_override('k8s_namespace', self.test_id, 'aim_k8s') k8s_config_path = os.environ.get(K8S_CONFIG_ENV) if k8s_config_path: CONF.set_override('k8s_config_path', k8s_config_path, 'aim_k8s') aim_store.K8sStore._post_delete = _k8s_post_delete aim_store.K8sStore._post_create = _k8s_post_create global k8s_watcher_instance k8s_watcher_instance = k8s_watcher.K8sWatcher() k8s_watcher_instance.event_handler = mock.Mock() k8s_watcher_instance._renew_klient_watch = mock.Mock() self.addCleanup(self._cleanup_objects) self.store = api.get_store(expire_on_commit=True, initialize_hooks=initialize_hooks) self.ctx = context.AimContext(store=self.store) self.cfg_manager = aim_cfg.ConfigManager(self.ctx, '') self.tt_mgr = tree_manager.HashTreeManager() resource.ResourceBase.__eq__ = resource_equal self.cfg_manager.replace_all(CONF) self.sys_id = self.cfg_manager.get_option('aim_system_id', 'aim')
def initialize(self, store, conf_mgr, multiverse): super(AimDbUniverse, self).initialize(store, conf_mgr, multiverse) self.tree_manager = tree_manager.HashTreeManager() self.context = context.AimContext(store=store) self._converter = converter.AciToAimModelConverter() self._converter_aim_to_aci = converter.AimToAciModelConverter() self._served_tenants = set() self._monitored_state_update_failures = 0 self._max_monitored_state_update_failures = 5 return self
def initialize(self, conf_mgr, multiverse): super(AimDbUniverse, self).initialize(conf_mgr, multiverse) self.tree_manager = tree_manager.HashTreeManager() self._converter = converter.AciToAimModelConverter() self._converter_aim_to_aci = converter.AimToAciModelConverter() self._served_tenants = set() self._monitored_state_update_failures = 0 self._max_monitored_state_update_failures = 5 self._recovery_interval = conf_mgr.get_option( 'error_state_recovery_interval', 'aim') self.schedule_next_recovery() return self
def __init__(self, ctx=None, *args, **kwargs): self.ctx = ctx or context.AimContext(store=api.get_store()) if 'streaming' not in self.ctx.store.features: # TODO(ivar) raise something meaningful raise Exception self.mgr = aim_manager.AimManager() self.tt_mgr = tree_manager.HashTreeManager() self.tt_maker = tree_manager.AimHashTreeMaker() self.tt_builder = tree_manager.HashTreeBuilder(self.mgr) self.klient = self.ctx.store.klient self.namespace = self.ctx.store.namespace self.trees = {} self.q = queue.Queue() self.event_handler = event_handler.EventHandler self._stop = False self._http_resp = None # Tenants whose trees need to be saved in AIM self.affected_tenants = set() self._observe_thread_state = {} self._k8s_types_to_observe = set([]) self._k8s_aim_type_map = {} self._k8s_kinds = set([]) self._needs_init = True for aim_res in aim_manager.AimManager.aim_resources: if issubclass(aim_res, resource.AciResourceBase): k8s_type = self.ctx.store.resource_to_db_type(aim_res) for ktype in ([k8s_type] + k8s_type.aux_objects.values()): self._k8s_types_to_observe.add(ktype) self._k8s_kinds.add(ktype.kind) if ktype != api_v1.AciContainersObject: self._k8s_aim_type_map[ktype.kind] = (aim_res, k8s_type) self._event_filters = { api_v1.Pod: self._pod_event_filter, api_v1.Endpoints: self._endpoints_event_filter }
def test_get_aim_resources(self, tree_type=tree_manager.CONFIG_TREE): tree_mgr = tree_manager.HashTreeManager() aim_mgr = aim_manager.AimManager() t1 = resource.Tenant(name='t1') t2 = resource.Tenant(name='t2') t1_fault = aim_status.AciFault( fault_code='101', external_identifier='uni/tn-t1/fault-101', description='failure101') t2_fault = aim_status.AciFault( fault_code='102', external_identifier='uni/tn-t2/fault-102', description='failure102') # Create Resources on a couple of tenants bd1 = resource.BridgeDomain( tenant_name='t1', name='bd1', display_name='somestuff', vrf_name='vrf') bd1_fault = aim_status.AciFault( fault_code='901', external_identifier='uni/tn-t1/BD-bd1/fault-901', description='failure901') bd1_fault2 = aim_status.AciFault( fault_code='902', external_identifier='uni/tn-t1/BD-bd1/fault-902', description='failure902') bd2 = resource.BridgeDomain( tenant_name='t2', name='bd1', display_name='somestuff', vrf_name='vrf2') dc1 = aim_service_graph.DeviceCluster( tenant_name='t1', name='clus1', devices=[{'name': '1'}]) dc1_fault = aim_status.AciFault( fault_code='901', external_identifier='uni/tn-t1/lDevVip-clus1/fault-901', description='failure901') sg1 = aim_service_graph.ServiceGraph( tenant_name='t1', name='gr1', linear_chain_nodes=[{'name': 'N1', 'device_cluster_name': 'cl1'}]) sg1_fault = aim_status.AciFault( fault_code='901', external_identifier='uni/tn-t1/AbsGraph-gr1/fault-901', description='failure901') srp1 = aim_service_graph.ServiceRedirectPolicy( tenant_name='t1', name='srp1', destinations=[{'ip': '1.1.1.1', 'mac': 'aa:bb:cc:dd:ee:ff'}]) srp1_fault = aim_status.AciFault( fault_code='901', external_identifier=('uni/tn-t1/svcCont/svcRedirectPol-srp1' '/fault-901'), description='failure901') dc_ctx1 = aim_service_graph.DeviceClusterContext( tenant_name='t1', contract_name='contract1', service_graph_name='graph1', node_name='N1', device_cluster_name='cluster1', device_cluster_tenant_name='common', bridge_domain_name='svc_bd', service_redirect_policy_name='srp1') dc_ctx1_fault = aim_status.AciFault( fault_code='901', external_identifier=('uni/tn-t1/ldevCtx-c-contract1-' 'g-graph1-n-N1/fault-901'), description='failure901') if tree_type == tree_manager.MONITORED_TREE: bd1.monitored = True bd2.monitored = True t1.monitored = True t2.monitored = True dc1.monitored = True sg1.monitored = True srp1.monitored = True dc_ctx1.monitored = True aim_mgr.create(self.ctx, t1) aim_mgr.create(self.ctx, t2) aim_mgr.create(self.ctx, bd1) aim_mgr.set_fault(self.ctx, t1, t1_fault) aim_mgr.set_fault(self.ctx, t2, t2_fault) aim_mgr.set_fault(self.ctx, bd1, bd1_fault) aim_mgr.set_fault(self.ctx, bd1, bd1_fault2) aim_mgr.create(self.ctx, bd2) aim_mgr.set_resource_sync_synced(self.ctx, t1) aim_mgr.set_resource_sync_synced(self.ctx, t2) aim_mgr.set_resource_sync_synced(self.ctx, bd2) aim_mgr.set_resource_sync_synced(self.ctx, bd1) aim_mgr.create(self.ctx, dc1) aim_mgr.create(self.ctx, sg1) aim_mgr.create(self.ctx, srp1) aim_mgr.create(self.ctx, dc_ctx1) aim_mgr.set_fault(self.ctx, dc1, dc1_fault) aim_mgr.set_fault(self.ctx, sg1, sg1_fault) aim_mgr.set_fault(self.ctx, srp1, srp1_fault) aim_mgr.set_fault(self.ctx, dc_ctx1, dc_ctx1_fault) aim_mgr.set_resource_sync_synced(self.ctx, dc1) aim_mgr.set_resource_sync_synced(self.ctx, sg1) aim_mgr.set_resource_sync_synced(self.ctx, srp1) aim_mgr.set_resource_sync_synced(self.ctx, dc_ctx1) # Two trees exist trees = tree_mgr.find(self.ctx, tree=tree_type) self.assertEqual(2, len(trees)) # Calculate the different with empty trees to retrieve missing keys diff_tn_1 = trees[0].diff(tree.StructuredHashTree()) diff_tn_2 = trees[1].diff(tree.StructuredHashTree()) self.universe.get_relevant_state_for_read = mock.Mock( return_value=[{'tn-t1': trees[0], 'tn-t2': trees[1]}]) result = self.universe.get_resources(diff_tn_1.get('add', []) + diff_tn_1.get('remove', []) + diff_tn_2.get('add', []) + diff_tn_2.get('remove', [])) converted = converter.AciToAimModelConverter().convert( converter.AimToAciModelConverter().convert( [bd1, bd2, dc1, sg1, srp1, dc_ctx1, t1, t2])) if tree_type == tree_manager.MONITORED_TREE: for x in converted: x.monitored = True if tree_type in [tree_manager.CONFIG_TREE, tree_manager.MONITORED_TREE]: self.assertEqual(len(converted), len(result)) for item in converted: self.assertTrue(item in result) elif tree_type == tree_manager.OPERATIONAL_TREE: self.assertEqual(8, len(result)) self.assertTrue(bd1_fault in result) self.assertTrue(bd1_fault2 in result) self.assertTrue(dc1_fault in result) self.assertTrue(sg1_fault in result) self.assertTrue(srp1_fault in result) self.assertTrue(dc_ctx1_fault in result)
def setUp(self): super(TestHashTreeDbListenerNoMockStore, self).setUp(mock_store=False) self.tt_mgr = tree_manager.HashTreeManager() self.mgr = aim_manager.AimManager() self.db_l = ht_db_l.HashTreeDbListener(aim_manager.AimManager())
def setUp(self): super(TestHashTreeDbListener, self).setUp() self.tt_mgr = tree_manager.HashTreeManager() self.mgr = aim_manager.AimManager() self.db_l = ht_db_l.HashTreeDbListener(aim_manager.AimManager())
def __init__(self, aim_manager): self.aim_manager = aim_manager self.tt_mgr = tree_manager.HashTreeManager() self.tt_maker = tree_manager.AimHashTreeMaker() self.tt_builder = tree_manager.HashTreeBuilder(self.aim_manager)