コード例 #1
0
def fix_no_nat_l3out_ownership(aim_ctx):
    """Relinquish ownership of no-NAT L3Outs in AIM and APIC."""
    saved_l3out_table = sa.Table(
        'aim_lib_save_l3out',
        sa.MetaData(),
        sa.Column('tenant_name', sa.String(), primary_key=True),
        sa.Column('name', sa.String(), primary_key=True),
        sa.Column('monitored', nullable=True),
        sa.Column('vrf_name', nullable=True))
    session = aim_ctx.store.db_session
    bind = session.get_bind()
    with session.begin(subtransactions=True):
        if not saved_l3out_table.exists(bind=bind):
            return
        results = session.execute(
            saved_l3out_table.select(saved_l3out_table.c.monitored.is_(True)))
        click.echo("Fixing ownership of no-NAT L3Outs")
        rows = results.fetchall()
        if rows:
            cfg_mgr = config.ConfigManager(aim_ctx)
            system_id = cfg_mgr.get_option('aim_system_id', 'aim')
            aim_mgr = aim_manager.AimManager()
            apic = aci_universe.AciUniverse.establish_aci_session(cfg_mgr)
            for row in rows:
                l3out = resource.L3Outside(tenant_name=row['tenant_name'],
                                           name=row['name'])
                aim_mgr.update(aim_ctx, l3out, monitored=True)
                tag_dn = "/mo/" + l3out.dn + "/tag-" + system_id
                click.echo('Deleting AIM tag %s' % tag_dn)
                apic.DELETE(tag_dn + ".json")
    # drop the table after the transaction completes because databases
    # like MySQL hold locks on the table
    saved_l3out_table.drop(bind=bind)
コード例 #2
0
    def test_poll_and_execute(self):
        cfg_mgr = config.ConfigManager(self.ctx, 'h1')
        callback = mock.Mock()

        # Subscribe to apic hosts
        cfg_mgr.get_option_and_subscribe(callback, 'apic_hosts', 'apic')
        # Polling will have no effect at this time, since apic_hosts hasn't
        # changed
        cfg_mgr.subs_mgr._poll_and_execute()
        self.assertFalse(callback.called)

        # Update apic hosts
        self.set_override('apic_hosts', ['2.2.2.2'], 'apic')
        cfg_mgr.subs_mgr._poll_and_execute()
        callback.assert_called_once_with({
            'key': 'apic_hosts',
            'host': '',
            'group': 'apic',
            'value': ['2.2.2.2'],
            'version': mock.ANY
        })
        # Reset mock and verify that the call doesn't happen again
        callback.reset_mock()
        cfg_mgr.subs_mgr._poll_and_execute()
        self.assertFalse(callback.called)
コード例 #3
0
    def setUp(self, universe_klass=None):
        super(TestAciUniverseMixin, self).setUp()
        self._do_aci_mocks()
        self.backend_state = {}
        self.universe = (universe_klass
                         or aci_universe.AciUniverse)().initialize(
                             aim_cfg.ConfigManager(self.ctx, 'h1'), [])
        self.universe.get_relevant_state_for_read = mock.Mock(
            return_value=[self.backend_state])
        # Mock ACI tenant manager
        self.mock_start = mock.patch(
            'aim.agent.aid.universes.aci.tenant.AciTenantManager.start')
        self.mock_start.start()
        self.mock_is_dead = mock.patch(
            'aim.agent.aid.universes.aci.tenant.AciTenantManager.is_dead',
            return_value=False)
        self.mock_is_dead.start()
        self.mock_is_warm = mock.patch(
            'aim.agent.aid.universes.aci.tenant.AciTenantManager.is_warm',
            return_value=True)
        self.mock_is_warm.start()

        aci_tenant.AciTenantManager.kill = _kill_thread
        self.addCleanup(self.mock_start.stop)
        self.addCleanup(self.mock_is_dead.stop)
        self.addCleanup(self.mock_is_warm.stop)
コード例 #4
0
 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
コード例 #5
0
    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
コード例 #6
0
 def __init__(self, conf):
     self.host = aim_cfg.CONF.aim.aim_service_identifier
     self.context = context.AimContext(store=api.get_store())
     self.conf_manager = aim_cfg.ConfigManager(self.context, self.host)
     # TODO(ivar): heartbeat for these services?
     self.sender = event_handler.EventSender()
     self.sender.initialize(self.conf_manager)
     self.run_daemon_loop = True
コード例 #7
0
    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')
コード例 #8
0
    def test_poll_and_execute_exception(self):
        cfg_mgr = config.ConfigManager(self.ctx, 'h1')
        callback = mock.Mock(side_effect=Exception('expected exception'))

        cfg_mgr.get_option_and_subscribe(callback, 'apic_hosts', 'apic')
        self.set_override('apic_hosts', ['2.2.2.2'], 'apic')

        # Doesn't rise
        cfg_mgr.subs_mgr._poll_and_execute()
コード例 #9
0
 def test_polling_interval_changed(self):
     self._clean_subscriptions()
     cfg_mgr = config.ConfigManager(self.ctx, 'h1')
     # Call property before changing the config value
     cfg_mgr.subs_mgr.polling_interval
     self.set_override('config_polling_interval', 130, 'aim')
     self.assertNotEqual(130, cfg_mgr.subs_mgr.polling_interval)
     cfg_mgr.subs_mgr._poll_and_execute()
     self.assertEqual(130, cfg_mgr.subs_mgr.polling_interval)
コード例 #10
0
 def test_shared_served_tenants(self):
     operational = aci_universe.AciOperationalUniverse().initialize(
         aim_cfg.ConfigManager(self.ctx, ''), [])
     tenant_list = ['tn-%s' % x for x in range(10)]
     self.universe.serve(self.ctx, tenant_list)
     self.assertIs(self.universe.serving_tenants,
                   operational.serving_tenants)
     for key, value in self.universe.serving_tenants.iteritems():
         self.assertIs(operational.serving_tenants[key], value)
コード例 #11
0
 def test_config_multiple_hosts_same_item_fails(self):
     cfg_mgr = config.ConfigManager(self.ctx, 'h1')
     callback = mock.Mock()
     cfg_mgr.get_option_and_subscribe(callback, 'apic_hosts', 'apic')
     self.assertRaises(exc.OneHostPerCallbackItemSubscriptionAllowed,
                       cfg_mgr.get_option_and_subscribe,
                       callback,
                       'apic_hosts',
                       'apic',
                       host='h2')
コード例 #12
0
 def test_config_subscribe_noop_no_host(self):
     # Subscription fails if no host is specified
     cfg_mgr = config.ConfigManager(self.ctx)
     # Clean current map state for testing
     cfg_mgr.subs_mgr.map_by_callback_id = {}
     cfg_mgr.subs_mgr.subscription_map = {}
     self.cfg_mgr.get_option_and_subscribe(mock.Mock(), 'apic_hosts',
                                           'apic')
     self.assertEqual({}, cfg_mgr.subs_mgr.subscription_map)
     self.assertEqual({}, cfg_mgr.subs_mgr.map_by_callback_id)
コード例 #13
0
 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])
コード例 #14
0
    def test_ws_config_changed(self):
        # Refresh subscriptions
        self.universe.ws_context = aci_universe.WebSocketContext(
            aim_cfg.ConfigManager(self.ctx, 'h1'))
        current_ws = self.universe.ws_context.session
        self.set_override('apic_hosts', ['3.1.1.1'], 'apic', poll=True)
        # Callback modified parameters
        self.assertTrue(current_ws is not self.universe.ws_context.session)
        self.assertEqual(['3.1.1.1'], self.universe.ws_context.apic_hosts)
        self.assertTrue('3.1.1.1' in self.universe.ws_context.session.api)

        # Change again to same value, there'll be no effect
        current_ws = self.universe.ws_context.session
        self.set_override('apic_hosts', ['3.1.1.1'], 'apic')
        self.assertTrue(current_ws is self.universe.ws_context.session)
コード例 #15
0
 def setUp(self):
     super(TestDBConfig, self).setUp()
     self.manager = config.ConfigManager(self.ctx, '')
コード例 #16
0
 def test_subscriber_singleton(self):
     cfg_mgr1 = config.ConfigManager(self.ctx, 'h1')
     cfg_mgr2 = config.ConfigManager(self.ctx, 'h2')
     self.assertTrue(cfg_mgr1 is not cfg_mgr2)
     self.assertTrue(cfg_mgr1.subs_mgr is cfg_mgr2.subs_mgr)
コード例 #17
0
def config(ctx):
    aim_ctx = context.AimContext(store=api.get_store(expire_on_commit=True))
    ctx.obj['manager'] = aim_cfg.ConfigManager(aim_ctx, '')
コード例 #18
0
    def test_config_subscribe(self):
        # Get a manager with a host
        cfg_mgr = config.ConfigManager(self.ctx, 'h1')
        # Clean current map state for testing
        cfg_mgr.subs_mgr.map_by_callback_id = {}
        cfg_mgr.subs_mgr.subscription_map = {}
        callback = mock.Mock()
        call_id = cfg_mgr.subs_mgr._get_call_id(callback)
        expected = {
            'apic': {
                'apic_hosts': {
                    call_id: {
                        'hosts': set(['h1']),
                        'version': mock.ANY,
                        'callback': callback
                    }
                }
            }
        }
        expected_rev = {call_id: {'apic': set(['apic_hosts'])}}
        cfg_mgr.get_option_and_subscribe(callback, 'apic_hosts', 'apic')
        self.assertEqual(expected, cfg_mgr.subs_mgr.subscription_map)
        self.assertEqual(expected_rev, cfg_mgr.subs_mgr.map_by_callback_id)

        # Same callback
        cfg_mgr.get_option_and_subscribe(callback, 'aim_system_id', 'aim')
        expected.update({
            'aim': {
                'aim_system_id': {
                    call_id: {
                        'hosts': set(['h1']),
                        'version': mock.ANY,
                        'callback': callback
                    }
                }
            }
        })
        expected_rev[call_id].update({'aim': set(['aim_system_id'])})
        self.assertEqual(expected, cfg_mgr.subs_mgr.subscription_map)
        self.assertEqual(expected_rev, cfg_mgr.subs_mgr.map_by_callback_id)

        # Different callback on same option
        callback_2 = mock.Mock()
        call_id_2 = cfg_mgr.subs_mgr._get_call_id(callback_2)
        cfg_mgr.get_option_and_subscribe(callback_2, 'aim_system_id', 'aim')
        expected['aim']['aim_system_id'].update({
            call_id_2: {
                'hosts': set(['h1']),
                'version': mock.ANY,
                'callback': callback_2
            }
        })
        expected_rev.update({call_id_2: {'aim': set(['aim_system_id'])}})
        self.assertEqual(expected, cfg_mgr.subs_mgr.subscription_map)
        self.assertEqual(expected_rev, cfg_mgr.subs_mgr.map_by_callback_id)

        # Remove specific option
        cfg_mgr.option_unsubscribe(callback, 'apic_hosts', 'apic')
        # This will remove the apic group completely
        expected.pop('apic')
        expected_rev[call_id].pop('apic')
        self.assertEqual(expected, cfg_mgr.subs_mgr.subscription_map)
        self.assertEqual(expected_rev, cfg_mgr.subs_mgr.map_by_callback_id)

        # Now unsubscribe an entire callback
        cfg_mgr.callback_unsubscribe(callback_2)
        # This removed the callback from both maps
        expected_rev.pop(call_id_2)
        expected['aim']['aim_system_id'].pop(call_id_2)
        self.assertEqual(expected, cfg_mgr.subs_mgr.subscription_map)
        self.assertEqual(expected_rev, cfg_mgr.subs_mgr.map_by_callback_id)

        # Unsubscribe last option
        cfg_mgr.option_unsubscribe(callback, 'aim_system_id', 'aim')
        # Maps are now empty
        self.assertEqual({}, cfg_mgr.subs_mgr.subscription_map)
        self.assertEqual({}, cfg_mgr.subs_mgr.map_by_callback_id)