diff --git a/hooks/swift_hooks.py b/hooks/swift_hooks.py index 0e1acfb..a8d1e00 100755 --- a/hooks/swift_hooks.py +++ b/hooks/swift_hooks.py @@ -103,7 +103,7 @@ def install(): if is_elected_leader(SWIFT_HA_RES): log("Leader established, generating ring builders", level=INFO) # initialize new storage rings. - for ring, path in SWIFT_RINGS.iteritems(): + for path in SWIFT_RINGS.itervalues(): initialize_ring(path, config('partition-power'), config('replicas'), @@ -205,8 +205,7 @@ def storage_changed(): } if None in node_settings.itervalues(): - missing = [k for k, v in node_settings.iteritems() - if node_settings[k] is None] + missing = [k for k, v in node_settings.iteritems() if v is None] log("Relation not ready - some required values not provided by " "relation (missing=%s)" % (', '.join(missing)), level=INFO) return None @@ -271,7 +270,8 @@ def cluster_changed(): for rid in rel_ids: for unit in related_units(rid): units += 1 - disabled.append(relation_get('disable-proxy-service', rid=rid)) + disabled.append(relation_get('disable-proxy-service', rid=rid, + unit=unit)) disabled = [int(d) for d in disabled if d is not None] if not any(disabled) and len(set(disabled)) == 1: diff --git a/hooks/swift_utils.py b/hooks/swift_utils.py index fa9fbdd..4949de2 100644 --- a/hooks/swift_utils.py +++ b/hooks/swift_utils.py @@ -597,7 +597,7 @@ def update_min_part_hours(): performed and if setting has changed, rings will be resynced across the cluster. """ - if is_elected_leader(SWIFT_HA_RES): + if not is_elected_leader(SWIFT_HA_RES): # Only the leader can do this. return @@ -609,7 +609,7 @@ def update_min_part_hours(): min_part_hours = get_min_part_hours(path) if min_part_hours != new_min_part_hours: log("Setting ring %s min_part_hours to %s" % - (new_min_part_hours), level=INFO) + (ring, new_min_part_hours), level=INFO) set_min_part_hours(path, new_min_part_hours) resync_builders = True diff --git a/unit_tests/test_swift_context.py b/unit_tests/test_swift_context.py new file mode 100644 index 0000000..e0dbb6b --- /dev/null +++ b/unit_tests/test_swift_context.py @@ -0,0 +1,56 @@ +import mock +import os +import tempfile +import unittest +import uuid + + +with mock.patch('charmhelpers.core.hookenv.config'): + import swift_context + + +class SwiftContextTestCase(unittest.TestCase): + + @mock.patch('swift_context.config') + def test_get_swift_hash_file(self, mock_config): + expected = '##FILEHASH##' + with tempfile.NamedTemporaryFile() as tmpfile: + swift_context.SWIFT_HASH_FILE = tmpfile.name + tmpfile.write(expected) + tmpfile.seek(0) + os.fsync(tmpfile) + hash = swift_context.get_swift_hash() + + self.assertFalse(mock_config.called) + self.assertEqual(expected, hash) + + @mock.patch('swift_context.config') + def test_get_swift_hash_config(self, mock_config): + expected = '##CFGHASH##' + mock_config.return_value = expected + tmpfile = tempfile.mktemp() + swift_context.SWIFT_HASH_FILE = tmpfile + hash = swift_context.get_swift_hash() + + with open(tmpfile, 'r') as fd: + self.assertEqual(expected, fd.read()) + + self.assertTrue(mock_config.called) + self.assertEqual(expected, hash) + + @mock.patch('swift_context.service_name') + @mock.patch('swift_context.config') + def test_get_swift_hash_env(self, mock_config, mock_service_name): + mock_config.return_value = None + mock_service_name.return_value = "testsvc" + tmpfile = tempfile.mktemp() + swift_context.SWIFT_HASH_FILE = tmpfile + with mock.patch('swift_context.os.environ.get') as mock_env_get: + mock_env_get.return_value = str(uuid.uuid4()) + hash = swift_context.get_swift_hash() + mock_env_get.assert_called_with('JUJU_ENV_UUID') + + with open(tmpfile, 'r') as fd: + self.assertEqual(hash, fd.read()) + + self.assertTrue(mock_config.called) diff --git a/unit_tests/test_swift_utils.py b/unit_tests/test_swift_utils.py new file mode 100644 index 0000000..d138d0f --- /dev/null +++ b/unit_tests/test_swift_utils.py @@ -0,0 +1,87 @@ +import mock +import shutil +import tempfile +import unittest + + +with mock.patch('charmhelpers.core.hookenv.config'): + import swift_utils + + +class SwiftUtilsTestCase(unittest.TestCase): + + @mock.patch('swift_utils.log') + @mock.patch('swift_utils.os.path.exists') + @mock.patch('swift_utils.is_elected_leader') + @mock.patch('swift_utils.config') + @mock.patch('swift_utils.get_min_part_hours') + @mock.patch('swift_utils.set_min_part_hours') + @mock.patch('swift_utils.should_balance') + @mock.patch('swift_utils.balance_rings') + @mock.patch('swift_utils.notify_storage_rings_available') + @mock.patch('swift_utils.notify_peers_builders_available') + def test_update_min_part_hours(self, mock_notify_peers, + mock_notify_storage, mock_balance_rings, + mock_should_balance, mock_set_min_hours, + mock_get_min_hours, mock_config, + mock_is_elected_leader, mock_path_exists, + mock_log): + + # Test blocker 1 + mock_is_elected_leader.return_value = False + swift_utils.update_min_part_hours() + self.assertFalse(mock_config.called) + + # Test blocker 2 + mock_path_exists.return_value = False + mock_is_elected_leader.return_value = True + swift_utils.update_min_part_hours() + self.assertTrue(mock_config.called) + self.assertFalse(mock_get_min_hours.called) + + # Test blocker 3 + mock_path_exists.return_value = True + mock_is_elected_leader.return_value = True + mock_config.return_value = 10 + mock_get_min_hours.return_value = 10 + swift_utils.update_min_part_hours() + self.assertTrue(mock_config.called) + self.assertTrue(mock_get_min_hours.called) + self.assertFalse(mock_set_min_hours.called) + + # Test blocker 4 + mock_path_exists.return_value = True + mock_is_elected_leader.return_value = True + mock_config.return_value = 10 + mock_get_min_hours.return_value = 11 + mock_should_balance.return_value = False + swift_utils.update_min_part_hours() + self.assertTrue(mock_config.called) + self.assertTrue(mock_get_min_hours.called) + self.assertTrue(mock_set_min_hours.called) + self.assertFalse(mock_balance_rings.called) + self.assertFalse(mock_notify_storage.called) + self.assertFalse(mock_notify_peers.called) + + # Test go through + mock_path_exists.return_value = True + mock_is_elected_leader.return_value = True + mock_config.return_value = 10 + mock_get_min_hours.return_value = 11 + mock_should_balance.return_value = True + swift_utils.update_min_part_hours() + self.assertTrue(mock_config.called) + self.assertTrue(mock_get_min_hours.called) + self.assertTrue(mock_set_min_hours.called) + self.assertTrue(mock_balance_rings.called) + self.assertTrue(mock_notify_storage.called) + self.assertTrue(mock_notify_peers.called) + + @mock.patch('swift_utils.get_www_dir') + def test_mark_www_rings_deleted(self, mock_get_www_dir): + try: + tmpdir = tempfile.mkdtemp() + mock_get_www_dir.return_value = tmpdir + swift_utils.mark_www_rings_deleted() + finally: + shutil.rmtree(tmpdir)