class AgentStoreConversionTests(unittest.TestCase): def setUp(self): super(AgentStoreConversionTests, self).setUp() self.config = ConfigStore(tempfile.mkdtemp()) def tearDown(self): super(AgentStoreConversionTests, self).tearDown() shutil.rmtree(self.config.path) def _create_agentstore_config(self): import uuid import json import string self.old_server_conf = {'url': 'http://foo.bar.baz/'} with open(os.path.join(self.config.path, 'server_conf'), 'w') as f: json.dump(self.old_server_conf, f) self.old_target_configs = {} for i in xrange(0, 15): bdev = '/dev/sd%s' % string.ascii_lowercase[i] mntpt = '/mnt/target%04d' % i uuid_str = str(uuid.uuid4()) target_config = dict(bdev=bdev, mntpt=mntpt) with open(os.path.join(self.config.path, uuid_str), 'w') as f: json.dump(target_config, f) self.old_target_configs[uuid_str] = target_config def test_agentstore_conversion(self): with patch('chroma_agent.action_plugins.settings_management.config', new=self.config): self._create_agentstore_config() from chroma_agent.action_plugins.settings_management import _convert_agentstore_config _convert_agentstore_config() self.assertDictEqual(self.config.get('settings', 'server'), self.old_server_conf) for uuid, old_target_conf in self.old_target_configs.items(): self.assertDictEqual(self.config.get('targets', uuid), old_target_conf)
class AgentStoreConversionTests(unittest.TestCase): def setUp(self): super(AgentStoreConversionTests, self).setUp() self.env_path_patch = patch("chroma_agent.conf.ENV_PATH", new=tempfile.mkdtemp()) self.env_path = self.env_path_patch.start() self.config = ConfigStore(tempfile.mkdtemp()) def tearDown(self): super(AgentStoreConversionTests, self).tearDown() self.env_path_patch.stop() shutil.rmtree(self.env_path) shutil.rmtree(self.config.path) def _create_agentstore_config(self): import uuid import json import string self.old_server_conf = {"url": "http://foo.bar.baz/"} with open(os.path.join(self.config.path, "server_conf"), "w") as f: json.dump(self.old_server_conf, f) self.old_target_configs = {} for i in xrange(0, 15): bdev = "/dev/sd%s" % string.ascii_lowercase[i] mntpt = "/mnt/target%04d" % i uuid_str = str(uuid.uuid4()) target_config = dict(bdev=bdev, mntpt=mntpt) with open(os.path.join(self.config.path, uuid_str), "w") as f: json.dump(target_config, f) self.old_target_configs[uuid_str] = target_config def test_agentstore_conversion(self): with patch("chroma_agent.action_plugins.settings_management.config", new=self.config): self._create_agentstore_config() from chroma_agent.action_plugins.settings_management import ( _convert_agentstore_config, ) _convert_agentstore_config() with open(os.path.join(self.env_path, "manager-url.conf"), "r") as f: self.assertEqual( f.read(), "IML_MANAGER_URL={}\n".format( self.old_server_conf.get("url")), ) for uuid, old_target_conf in self.old_target_configs.items(): self.assertDictEqual(self.config.get("targets", uuid), old_target_conf)
class TestCopytoolManagement(CommandCaptureTestCase, AgentUnitTestCase): def setUp(self): super(TestCopytoolManagement, self).setUp() from chroma_agent.config_store import ConfigStore self.mock_config = ConfigStore(tempfile.mkdtemp()) mock.patch('chroma_agent.action_plugins.manage_copytool.config', self.mock_config).start() mock.patch('chroma_agent.copytool_monitor.config', self.mock_config).start() mock.patch('chroma_agent.action_plugins.settings_management.config', self.mock_config).start() mock.patch('chroma_agent.action_plugins.manage_copytool._write_service_init').start() self.mock_os_remove = mock.MagicMock() mock.patch('os.remove', self.mock_os_remove).start() from chroma_agent.action_plugins.settings_management import reset_agent_config reset_agent_config() self.ct_id = '42' self.ct_index = 0 self.ct_archive = 1 self.ct_bin_path = '/usr/sbin/lhsmtool_foo' self.ct_arguments = '-p /archive/testfs' self.ct_filesystem = 'testfs' self.ct_mountpoint = '/mnt/testfs' self._configure_copytool() self.ct_vars = _copytool_vars(self.ct_id) self.addCleanup(mock.patch.stopall) def tearDown(self): super(TestCopytoolManagement, self).tearDown() mock.patch.stopall() shutil.rmtree(self.mock_config.path) def _configure_copytool(self): self.ct_id = configure_copytool(self.ct_id, self.ct_index, self.ct_bin_path, self.ct_archive, self.ct_filesystem, self.ct_mountpoint, self.ct_arguments) def test_start_monitored_copytool(self): self.single_commands(CommandCaptureCommand(('systemctl', 'daemon-reload')), CommandCaptureCommand(('systemctl', 'is-active', 'chroma-copytool-monitor-%s' % self.ct_id), rc=1), CommandCaptureCommand(('systemctl', 'start', 'chroma-copytool-monitor-%s' % self.ct_id)), CommandCaptureCommand(('systemctl', 'is-active', 'chroma-copytool-monitor-%s' % self.ct_id)), CommandCaptureCommand(('systemctl', 'daemon-reload')), CommandCaptureCommand(('systemctl', 'is-active', 'chroma-copytool-%s' % self.ct_id), rc=1), CommandCaptureCommand(('systemctl', 'start', 'chroma-copytool-%s' % self.ct_id)), CommandCaptureCommand(('systemctl', 'is-active', 'chroma-copytool-%s' % self.ct_id))) self.assertAgentOK(start_monitored_copytool(self.ct_id)) self.assertRanAllCommandsInOrder() def test_stop_monitored_copytool(self): self.single_commands(CommandCaptureCommand(('systemctl', 'is-active', 'chroma-copytool-monitor-%s' % self.ct_id)), CommandCaptureCommand(('systemctl', 'stop', 'chroma-copytool-monitor-%s' % self.ct_id)), CommandCaptureCommand(('systemctl', 'is-active', 'chroma-copytool-monitor-%s' % self.ct_id), rc=1), CommandCaptureCommand(('systemctl', 'daemon-reload')), CommandCaptureCommand(('systemctl', 'is-active', 'chroma-copytool-%s' % self.ct_id)), CommandCaptureCommand(('systemctl', 'stop', 'chroma-copytool-%s' % self.ct_id)), CommandCaptureCommand(('systemctl', 'is-active', 'chroma-copytool-%s' % self.ct_id), rc=1), CommandCaptureCommand(('systemctl', 'daemon-reload'))) with mock.patch('os.path.exists', return_value=True): self.assertAgentOK(stop_monitored_copytool(self.ct_id)) self.assertRanAllCommandsInOrder() self.assertEqual(self.mock_os_remove.call_count, 2) self.mock_os_remove.assert_called_with('/etc/init.d/chroma-copytool-%s' % self.ct_id) def test_start_should_be_idempotent(self): self.single_commands(CommandCaptureCommand(('systemctl', 'daemon-reload')), CommandCaptureCommand(('systemctl', 'is-active', 'chroma-copytool-monitor-%s' % self.ct_id)), CommandCaptureCommand(('systemctl', 'stop', 'chroma-copytool-monitor-%s' % self.ct_id)), CommandCaptureCommand(('systemctl', 'is-active', 'chroma-copytool-monitor-%s' % self.ct_id), rc=1), CommandCaptureCommand(('systemctl', 'start', 'chroma-copytool-monitor-%s' % self.ct_id)), CommandCaptureCommand(('systemctl', 'is-active', 'chroma-copytool-monitor-%s' % self.ct_id)), CommandCaptureCommand(('systemctl', 'daemon-reload')), CommandCaptureCommand(('systemctl', 'is-active', 'chroma-copytool-%s' % self.ct_id)), CommandCaptureCommand(('systemctl', 'stop', 'chroma-copytool-%s' % self.ct_id)), CommandCaptureCommand(('systemctl', 'is-active', 'chroma-copytool-%s' % self.ct_id), rc=1), CommandCaptureCommand(('systemctl', 'start', 'chroma-copytool-%s' % self.ct_id)), CommandCaptureCommand(('systemctl', 'is-active', 'chroma-copytool-%s' % self.ct_id))) self.assertAgentOK(start_monitored_copytool(self.ct_id)) self.assertRanAllCommandsInOrder() def test_stop_should_be_idempotent1(self): self.single_commands(CommandCaptureCommand(('systemctl', 'is-active', 'chroma-copytool-monitor-%s' % self.ct_id)), CommandCaptureCommand(('systemctl', 'stop', 'chroma-copytool-monitor-%s' % self.ct_id)), CommandCaptureCommand(('systemctl', 'is-active', 'chroma-copytool-monitor-%s' % self.ct_id), rc=1), CommandCaptureCommand(('systemctl', 'daemon-reload')), CommandCaptureCommand(('systemctl', 'is-active', 'chroma-copytool-%s' % self.ct_id)), CommandCaptureCommand(('systemctl', 'stop', 'chroma-copytool-%s' % self.ct_id)), CommandCaptureCommand(('systemctl', 'is-active', 'chroma-copytool-%s' % self.ct_id), rc=1), CommandCaptureCommand(('systemctl', 'daemon-reload')), CommandCaptureCommand(('systemctl', 'daemon-reload')), CommandCaptureCommand(('systemctl', 'daemon-reload'))) with mock.patch('os.path.exists', return_value=True): self.assertAgentOK(stop_monitored_copytool(self.ct_id)) with mock.patch('os.path.exists', return_value=False): self.assertAgentOK(stop_monitored_copytool(self.ct_id)) self.assertRanAllCommandsInOrder() def test_stop_should_be_idempotent2(self): self.single_commands(CommandCaptureCommand(('systemctl', 'is-active', 'chroma-copytool-monitor-%s' % self.ct_id), rc=1), CommandCaptureCommand(('systemctl', 'daemon-reload')), CommandCaptureCommand(('systemctl', 'is-active', 'chroma-copytool-%s' % self.ct_id), rc=1), CommandCaptureCommand(('systemctl', 'daemon-reload'))) with mock.patch('os.path.exists', return_value=True): self.assertAgentOK(stop_monitored_copytool(self.ct_id)) self.assertRanAllCommandsInOrder() def test_configure_should_be_idempotent(self): expected_kwargs = dict( index = self.ct_index, bin_path = self.ct_bin_path, filesystem = self.ct_filesystem, mountpoint = self.ct_mountpoint, archive_number = self.ct_archive, hsm_arguments = self.ct_arguments ) with mock.patch('chroma_agent.action_plugins.manage_copytool.update_copytool') as patched_update_copytool: self._configure_copytool() patched_update_copytool.assert_called_with(self.ct_id, **expected_kwargs) @mock.patch('chroma_agent.action_plugins.manage_copytool.stop_monitored_copytool') def test_unconfigure_copytool(self, stop_monitored_copytool): # NB: configure_copytool is implicitly tested numerous times as # part of setUp(). Kind of hacky but whatever. unconfigure_copytool(self.ct_id) stop_monitored_copytool.assert_called_with(self.ct_id) @mock.patch('chroma_agent.action_plugins.manage_copytool.stop_monitored_copytool') @mock.patch('chroma_agent.action_plugins.manage_copytool.start_monitored_copytool') def test_update_copytool(self, start_monitored_copytool, stop_monitored_copytool): update_copytool(self.ct_id, archive_number=2) stop_monitored_copytool.assert_called_with(self.ct_id) self.assertEquals(self.mock_config.get('copytools', self.ct_id)['archive_number'], 2) start_monitored_copytool.assert_called_with(self.ct_id) def test_list_copytools(self): self.assertDictEqual(list_copytools(), {'raw_result': self.ct_id})
class ConfigStoreTests(unittest.TestCase): def setUp(self): super(ConfigStoreTests, self).setUp() self.config = ConfigStore(tempfile.mkdtemp()) self.data = { 'foo': 1, 'bar': "1", 'baz': ['qux', 'quux', 'corge'], 'grault': { 'garply': "waldo", 'fred': ['plugh', 'xyzzy'] }, 'thud': False } def tearDown(self): super(ConfigStoreTests, self).tearDown() shutil.rmtree(self.config.path) def test_set(self): self.config.set("barfy", "cow", self.data) self.assertEqual(self.data, self.config.get("barfy", "cow")) with self.assertRaises(ConfigKeyExistsError): self.config.set("barfy", "cow", self.data) def test_update(self): self.config.set("barfy", "cow", self.data) self.data['thud'] = True self.config.update("barfy", "cow", self.data) self.assertEqual(self.data, self.config.get("barfy", "cow")) def test_delete(self): self.config.set("barfy", "cow", self.data) self.config.delete("barfy", "cow") with self.assertRaises(KeyError): self.config.get("barfy", "cow") def test_delete_idempotent(self): # Shouldn't fail -- if it's not there, then the intended goal # was accomplished. self.config.delete("barfy", "cow") def test_delete_section(self): self.config.set("barfy", "cow", self.data) self.config.delete_section("barfy") with self.assertRaises(TypeError): self.config.get("barfy", "cow") def test_get_nonexistent_section(self): self.assertListEqual([], self.config.get_section_keys('foo')) self.assertDictEqual({}, self.config.get_section('foo')) def test_sections(self): maladies = ["barfy", "gassy", "sad", "grumpy"] for malady in maladies: self.config.set(malady, "cow", self.data) self.assertListEqual(sorted(maladies), self.config.sections) def test_get_section(self): self.config.set("barfy", "cow", self.data) self.assertDictEqual({'cow': self.data}, self.config.get_section("barfy")) def test_get_all(self): maladies = ["barfy", "gassy", "sad", "grumpy"] for malady in maladies: self.config.set(malady, "cow", self.data) self.assertDictEqual( { 'barfy': { 'cow': self.data }, 'gassy': { 'cow': self.data }, 'sad': { 'cow': self.data }, 'grumpy': { 'cow': self.data } }, self.config.get_all()) def test_clear(self): maladies = ["barfy", "gassy", "sad", "grumpy"] for malady in maladies: self.config.set(malady, "cow", self.data) self.config.clear() self.assertListEqual([], self.config.sections) def test_bad_identifiers(self): badkey = object() with self.assertRaises(InvalidConfigIdentifier): self.config.set('whoops', badkey, "foobar") with self.assertRaises(InvalidConfigIdentifier): self.config.set(badkey, 'whoops', "foobar") def test_unicode_identifiers(self): test_id = u'should work' self.config.set('ok', test_id, self.data) self.assertDictEqual(self.data, self.config.get('ok', test_id)) self.config.set(test_id, 'ok', self.data) self.assertDictEqual(self.data, self.config.get(test_id, 'ok')) def test_thread_safety(self): import Queue config = self.config data = self.data testcase = self exceptions = Queue.Queue() class ThreadA(threading.Thread): def __init__(self): super(ThreadA, self).__init__() self.config = config self.data = data self.testcase = testcase def run(self): try: with self.config.lock: self.config.set("barfy", "cow", self.data) time.sleep(1) self.testcase.assertDictEqual( self.data, self.config.get("barfy", "cow")) except Exception as e: exceptions.put(e) class ThreadB(threading.Thread): def __init__(self): super(ThreadB, self).__init__() self.config = config def run(self): try: self.config.clear() except Exception as e: exceptions.put(e) a = ThreadA() b = ThreadB() self.assertEqual(a.config, b.config) a.start() b.start() a.join() b.join() with self.assertRaises(Queue.Empty): raise RuntimeError("Thread safety check failed: %s" % exceptions.get(block=False)) def test_multiprocess_safety(self): from multiprocessing import Queue from Queue import Empty config = self.config data = self.data testcase = self exceptions = Queue() class ProcessA(multiprocessing.Process): def __init__(self): super(ProcessA, self).__init__() self.config = config self.data = data self.testcase = testcase def run(self): try: with self.config.lock: self.config.set("barfy", "cow", self.data) time.sleep(1) self.testcase.assertDictEqual( self.data, self.config.get("barfy", "cow")) except Exception as e: exceptions.put(e) class ProcessB(multiprocessing.Process): def __init__(self): super(ProcessB, self).__init__() self.config = config def run(self): try: self.config.clear() except Exception as e: exceptions.put(e) a = ProcessA() b = ProcessB() self.assertEqual(a.config, b.config) a.start() b.start() a.join() b.join() with self.assertRaises(Empty): raise RuntimeError("Multi-process safety check failed: %s" % exceptions.get(block=False)) def test_profile_managed_true(self): self.config.set('settings', 'profile', {'managed': True}) self.assertEqual(self.config.profile_managed, True) def test_profile_managed_false(self): self.config.set('settings', 'profile', {'managed': False}) self.assertEqual(self.config.profile_managed, False) def test_profile_managed_missing_false_section(self): self.assertEqual(self.config.profile_managed, False) def test_profile_managed_missing_false_ket(self): self.config.set('settings', 'profile', {'trevor': 'andy'}) self.assertEqual(self.config.profile_managed, False)
class ConfigStoreTests(unittest.TestCase): def setUp(self): super(ConfigStoreTests, self).setUp() self.config = ConfigStore(tempfile.mkdtemp()) self.data = { "foo": 1, "bar": "1", "baz": ["qux", "quux", "corge"], "grault": { "garply": "waldo", "fred": ["plugh", "xyzzy"] }, "thud": False, } def tearDown(self): super(ConfigStoreTests, self).tearDown() shutil.rmtree(self.config.path) def test_set(self): self.config.set("barfy", "cow", self.data) self.assertEqual(self.data, self.config.get("barfy", "cow")) with self.assertRaises(ConfigKeyExistsError): self.config.set("barfy", "cow", self.data) def test_update(self): self.config.set("barfy", "cow", self.data) self.data["thud"] = True self.config.update("barfy", "cow", self.data) self.assertEqual(self.data, self.config.get("barfy", "cow")) def test_delete(self): self.config.set("barfy", "cow", self.data) self.config.delete("barfy", "cow") with self.assertRaises(KeyError): self.config.get("barfy", "cow") def test_delete_idempotent(self): # Shouldn't fail -- if it's not there, then the intended goal # was accomplished. self.config.delete("barfy", "cow") def test_delete_section(self): self.config.set("barfy", "cow", self.data) self.config.delete_section("barfy") with self.assertRaises(TypeError): self.config.get("barfy", "cow") def test_get_nonexistent_section(self): self.assertListEqual([], self.config.get_section_keys("foo")) self.assertDictEqual({}, self.config.get_section("foo")) def test_sections(self): maladies = ["barfy", "gassy", "sad", "grumpy"] for malady in maladies: self.config.set(malady, "cow", self.data) self.assertListEqual(sorted(maladies), self.config.sections) def test_get_section(self): self.config.set("barfy", "cow", self.data) self.assertDictEqual({"cow": self.data}, self.config.get_section("barfy")) def test_get_all(self): maladies = ["barfy", "gassy", "sad", "grumpy"] for malady in maladies: self.config.set(malady, "cow", self.data) self.assertDictEqual( { "barfy": { "cow": self.data }, "gassy": { "cow": self.data }, "sad": { "cow": self.data }, "grumpy": { "cow": self.data }, }, self.config.get_all(), ) def test_clear(self): maladies = ["barfy", "gassy", "sad", "grumpy"] for malady in maladies: self.config.set(malady, "cow", self.data) self.config.clear() self.assertListEqual([], self.config.sections) def test_bad_identifiers(self): badkey = object() with self.assertRaises(InvalidConfigIdentifier): self.config.set("whoops", badkey, "foobar") with self.assertRaises(InvalidConfigIdentifier): self.config.set(badkey, "whoops", "foobar") def test_unicode_identifiers(self): test_id = u"should work" self.config.set("ok", test_id, self.data) self.assertDictEqual(self.data, self.config.get("ok", test_id)) self.config.set(test_id, "ok", self.data) self.assertDictEqual(self.data, self.config.get(test_id, "ok")) def test_thread_safety(self): import Queue config = self.config data = self.data testcase = self exceptions = Queue.Queue() class ThreadA(threading.Thread): def __init__(self): super(ThreadA, self).__init__() self.config = config self.data = data self.testcase = testcase def run(self): try: with self.config.lock: self.config.set("barfy", "cow", self.data) time.sleep(1) self.testcase.assertDictEqual( self.data, self.config.get("barfy", "cow")) except Exception as e: exceptions.put(e) class ThreadB(threading.Thread): def __init__(self): super(ThreadB, self).__init__() self.config = config def run(self): try: self.config.clear() except Exception as e: exceptions.put(e) a = ThreadA() b = ThreadB() self.assertEqual(a.config, b.config) a.start() b.start() a.join() b.join() with self.assertRaises(Queue.Empty): raise RuntimeError("Thread safety check failed: %s" % exceptions.get(block=False)) def test_multiprocess_safety(self): from multiprocessing import Queue from Queue import Empty config = self.config data = self.data testcase = self exceptions = Queue() class ProcessA(multiprocessing.Process): def __init__(self): super(ProcessA, self).__init__() self.config = config self.data = data self.testcase = testcase def run(self): try: with self.config.lock: self.config.set("barfy", "cow", self.data) time.sleep(1) self.testcase.assertDictEqual( self.data, self.config.get("barfy", "cow")) except Exception as e: exceptions.put(e) class ProcessB(multiprocessing.Process): def __init__(self): super(ProcessB, self).__init__() self.config = config def run(self): try: self.config.clear() except Exception as e: exceptions.put(e) a = ProcessA() b = ProcessB() self.assertEqual(a.config, b.config) a.start() b.start() a.join() b.join() with self.assertRaises(Empty): raise RuntimeError("Multi-process safety check failed: %s" % exceptions.get(block=False)) def test_profile_managed_true(self): self.config.set("settings", "profile", {"managed": True}) self.assertEqual(self.config.profile_managed, True) def test_profile_managed_false(self): self.config.set("settings", "profile", {"managed": False}) self.assertEqual(self.config.profile_managed, False) def test_profile_managed_missing_false_section(self): self.assertEqual(self.config.profile_managed, False) def test_profile_managed_missing_false_ket(self): self.config.set("settings", "profile", {"trevor": "andy"}) self.assertEqual(self.config.profile_managed, False)