diff --git a/doc/source/development_saio.rst b/doc/source/development_saio.rst index 9d71fbd389..4cc661e7a0 100644 --- a/doc/source/development_saio.rst +++ b/doc/source/development_saio.rst @@ -318,7 +318,8 @@ Sample configuration files are provided with all defaults in line-by-line commen #. Create `/etc/swift/swift.conf`:: [swift-hash] - # random unique string that can never change (DO NOT LOSE) + # random unique strings that can never change (DO NOT LOSE) + swift_hash_path_prefix = changeme swift_hash_path_suffix = changeme #. Create `/etc/swift/account-server/1.conf`:: diff --git a/doc/source/howto_installmultinode.rst b/doc/source/howto_installmultinode.rst index 0a6681725c..f4174cceb4 100644 --- a/doc/source/howto_installmultinode.rst +++ b/doc/source/howto_installmultinode.rst @@ -73,7 +73,8 @@ General OS configuration and partitioning for each node cat >/etc/swift/swift.conf <<EOF [swift-hash] - # random unique string that can never change (DO NOT LOSE) + # random unique strings that can never change (DO NOT LOSE) + swift_hash_path_prefix = `od -t x8 -N 8 -A n </dev/random` swift_hash_path_suffix = `od -t x8 -N 8 -A n </dev/random` EOF diff --git a/swift/common/utils.py b/swift/common/utils.py index 74b7872488..c35569bdfd 100644 --- a/swift/common/utils.py +++ b/swift/common/utils.py @@ -76,12 +76,18 @@ FALLOCATE_RESERVE = 0 # will end up with would also require knowing this suffix. hash_conf = ConfigParser() HASH_PATH_SUFFIX = '' +HASH_PATH_PREFIX = '' if hash_conf.read('/etc/swift/swift.conf'): try: HASH_PATH_SUFFIX = hash_conf.get('swift-hash', 'swift_hash_path_suffix') except (NoSectionError, NoOptionError): pass + try: + HASH_PATH_PREFIX = hash_conf.get('swift-hash', + 'swift_hash_path_prefix') + except (NoSectionError, NoOptionError): + pass def backward(f, blocksize=4096): @@ -134,8 +140,9 @@ def noop_libc_function(*args): def validate_configuration(): - if HASH_PATH_SUFFIX == '': - sys.exit("Error: [swift-hash]: swift_hash_path_suffix missing " + if not HASH_PATH_SUFFIX and not HASH_PATH_PREFIX: + sys.exit("Error: [swift-hash]: both swift_hash_path_suffix " + "and swift_hash_path_prefix are missing " "from /etc/swift/swift.conf") @@ -991,9 +998,11 @@ def hash_path(account, container=None, object=None, raw_digest=False): if object: paths.append(object) if raw_digest: - return md5('/' + '/'.join(paths) + HASH_PATH_SUFFIX).digest() + return md5(HASH_PATH_PREFIX + '/' + '/'.join(paths) + + HASH_PATH_SUFFIX).digest() else: - return md5('/' + '/'.join(paths) + HASH_PATH_SUFFIX).hexdigest() + return md5(HASH_PATH_PREFIX + '/' + '/'.join(paths) + + HASH_PATH_SUFFIX).hexdigest() @contextmanager diff --git a/test/unit/common/middleware/test_list_endpoints.py b/test/unit/common/middleware/test_list_endpoints.py index 642c01f9d1..eaafd0397c 100644 --- a/test/unit/common/middleware/test_list_endpoints.py +++ b/test/unit/common/middleware/test_list_endpoints.py @@ -36,6 +36,7 @@ def start_response(*args): class TestListEndpoints(unittest.TestCase): def setUp(self): utils.HASH_PATH_SUFFIX = 'endcap' + utils.HASH_PATH_PREFIX = '' self.testdir = os.path.join(os.path.dirname(__file__), 'ring') rmtree(self.testdir, ignore_errors=1) os.mkdir(self.testdir) diff --git a/test/unit/common/ring/test_ring.py b/test/unit/common/ring/test_ring.py index 00606d5666..3646eda832 100644 --- a/test/unit/common/ring/test_ring.py +++ b/test/unit/common/ring/test_ring.py @@ -97,6 +97,7 @@ class TestRing(unittest.TestCase): def setUp(self): utils.HASH_PATH_SUFFIX = 'endcap' + utils.HASH_PATH_PREFIX = '' self.testdir = os.path.join(os.path.dirname(__file__), 'ring') rmtree(self.testdir, ignore_errors=1) os.mkdir(self.testdir) @@ -133,11 +134,14 @@ class TestRing(unittest.TestCase): self.assertEquals(self.ring.serialized_path, self.testgz) # test invalid endcap _orig_hash_path_suffix = utils.HASH_PATH_SUFFIX + _orig_hash_path_prefix = utils.HASH_PATH_PREFIX try: utils.HASH_PATH_SUFFIX = '' + utils.HASH_PATH_PREFIX = '' self.assertRaises(SystemExit, ring.Ring, self.testdir, 'whatever') finally: utils.HASH_PATH_SUFFIX = _orig_hash_path_suffix + utils.HASH_PATH_PREFIX = _orig_hash_path_prefix def test_has_changed(self): self.assertEquals(self.ring.has_changed(), False) diff --git a/test/unit/common/test_daemon.py b/test/unit/common/test_daemon.py index f2da86965b..267d2cecad 100644 --- a/test/unit/common/test_daemon.py +++ b/test/unit/common/test_daemon.py @@ -62,6 +62,7 @@ class TestRunDaemon(unittest.TestCase): def setUp(self): utils.HASH_PATH_SUFFIX = 'endcap' + utils.HASH_PATH_PREFIX = 'startcap' utils.drop_privileges = lambda *args: None utils.capture_stdio = lambda *args: None diff --git a/test/unit/common/test_utils.py b/test/unit/common/test_utils.py index c817c725b1..094a7301a8 100644 --- a/test/unit/common/test_utils.py +++ b/test/unit/common/test_utils.py @@ -127,6 +127,7 @@ class TestUtils(unittest.TestCase): def setUp(self): utils.HASH_PATH_SUFFIX = 'endcap' + utils.HASH_PATH_PREFIX = 'startcap' def test_normalize_timestamp(self): """ Test swift.common.utils.normalize_timestamp """ @@ -626,20 +627,28 @@ class TestUtils(unittest.TestCase): self.assert_('127.0.0.1' in myips) def test_hash_path(self): + _prefix = utils.HASH_PATH_PREFIX + utils.HASH_PATH_PREFIX = '' # Yes, these tests are deliberately very fragile. We want to make sure # that if someones changes the results hash_path produces, they know it - self.assertEquals(utils.hash_path('a'), - '1c84525acb02107ea475dcd3d09c2c58') - self.assertEquals(utils.hash_path('a', 'c'), - '33379ecb053aa5c9e356c68997cbb59e') - self.assertEquals(utils.hash_path('a', 'c', 'o'), - '06fbf0b514e5199dfc4e00f42eb5ea83') - self.assertEquals(utils.hash_path('a', 'c', 'o', raw_digest=False), - '06fbf0b514e5199dfc4e00f42eb5ea83') - self.assertEquals(utils.hash_path('a', 'c', 'o', raw_digest=True), - '\x06\xfb\xf0\xb5\x14\xe5\x19\x9d\xfcN' - '\x00\xf4.\xb5\xea\x83') - self.assertRaises(ValueError, utils.hash_path, 'a', object='o') + try: + self.assertEquals(utils.hash_path('a'), + '1c84525acb02107ea475dcd3d09c2c58') + self.assertEquals(utils.hash_path('a', 'c'), + '33379ecb053aa5c9e356c68997cbb59e') + self.assertEquals(utils.hash_path('a', 'c', 'o'), + '06fbf0b514e5199dfc4e00f42eb5ea83') + self.assertEquals(utils.hash_path('a', 'c', 'o', raw_digest=False), + '06fbf0b514e5199dfc4e00f42eb5ea83') + self.assertEquals(utils.hash_path('a', 'c', 'o', raw_digest=True), + '\x06\xfb\xf0\xb5\x14\xe5\x19\x9d\xfcN' + '\x00\xf4.\xb5\xea\x83') + self.assertRaises(ValueError, utils.hash_path, 'a', object='o') + utils.HASH_PATH_PREFIX = 'abcdef' + self.assertEquals(utils.hash_path('a', 'c', 'o', raw_digest=False), + '363f9b535bfb7d17a43a46a358afca0e') + finally: + utils.HASH_PATH_PREFIX = _prefix def test_load_libc_function(self): self.assert_(callable( diff --git a/test/unit/container/test_sync.py b/test/unit/container/test_sync.py index 34d00c39c4..a3a36afecf 100644 --- a/test/unit/container/test_sync.py +++ b/test/unit/container/test_sync.py @@ -23,6 +23,7 @@ from swiftclient import ClientException utils.HASH_PATH_SUFFIX = 'endcap' +utils.HASH_PATH_PREFIX = 'endcap' class FakeRing(object): diff --git a/test/unit/container/test_updater.py b/test/unit/container/test_updater.py index 6e1fe32bec..d21e4ed830 100644 --- a/test/unit/container/test_updater.py +++ b/test/unit/container/test_updater.py @@ -35,6 +35,7 @@ class TestContainerUpdater(unittest.TestCase): def setUp(self): utils.HASH_PATH_SUFFIX = 'endcap' + utils.HASH_PATH_PREFIX = 'startcap' self.testdir = os.path.join(mkdtemp(), 'tmp_test_container_updater') rmtree(self.testdir, ignore_errors=1) os.mkdir(self.testdir) diff --git a/test/unit/obj/test_replicator.py b/test/unit/obj/test_replicator.py index 4924ad32a7..b5ca89e7c5 100644 --- a/test/unit/obj/test_replicator.py +++ b/test/unit/obj/test_replicator.py @@ -135,6 +135,7 @@ class TestObjectReplicator(unittest.TestCase): def setUp(self): utils.HASH_PATH_SUFFIX = 'endcap' + utils.HASH_PATH_PREFIX = '' # Setup a test ring (stolen from common/test_ring.py) self.testdir = tempfile.mkdtemp() self.devices = os.path.join(self.testdir, 'node') diff --git a/test/unit/obj/test_server.py b/test/unit/obj/test_server.py index 3f30991e2f..8ee266bf89 100755 --- a/test/unit/obj/test_server.py +++ b/test/unit/obj/test_server.py @@ -383,6 +383,7 @@ class TestObjectController(unittest.TestCase): def setUp(self): """ Set up for testing swift.object_server.ObjectController """ utils.HASH_PATH_SUFFIX = 'endcap' + utils.HASH_PATH_PREFIX = 'startcap' self.testdir = \ os.path.join(mkdtemp(), 'tmp_test_object_server_ObjectController') mkdirs(os.path.join(self.testdir, 'sda1', 'tmp')) @@ -1808,6 +1809,8 @@ class TestObjectController(unittest.TestCase): 'x-trans-id': '-'}}) def test_async_update_saves_on_exception(self): + _prefix = utils.HASH_PATH_PREFIX + utils.HASH_PATH_PREFIX = '' def fake_http_connect(*args): raise Exception('test') @@ -1820,6 +1823,7 @@ class TestObjectController(unittest.TestCase): {'x-timestamp': '1', 'x-out': 'set'}, 'sda1') finally: object_server.http_connect = orig_http_connect + utils.HASH_PATH_PREFIX = _prefix self.assertEquals( pickle.load(open(os.path.join(self.testdir, 'sda1', 'async_pending', 'a83', @@ -1828,6 +1832,8 @@ class TestObjectController(unittest.TestCase): 'container': 'c', 'obj': 'o', 'op': 'PUT'}) def test_async_update_saves_on_non_2xx(self): + _prefix = utils.HASH_PATH_PREFIX + utils.HASH_PATH_PREFIX = '' def fake_http_connect(status): @@ -1860,6 +1866,7 @@ class TestObjectController(unittest.TestCase): 'op': 'PUT'}) finally: object_server.http_connect = orig_http_connect + utils.HASH_PATH_PREFIX = _prefix def test_async_update_does_not_save_on_2xx(self): diff --git a/test/unit/obj/test_updater.py b/test/unit/obj/test_updater.py index 104325b6ac..27d9ef7d85 100644 --- a/test/unit/obj/test_updater.py +++ b/test/unit/obj/test_updater.py @@ -37,6 +37,7 @@ class TestObjectUpdater(unittest.TestCase): def setUp(self): utils.HASH_PATH_SUFFIX = 'endcap' + utils.HASH_PATH_PREFIX = '' self.testdir = os.path.join(os.path.dirname(__file__), 'object_updater') rmtree(self.testdir, ignore_errors=1)