diff --git a/swift/common/utils.py b/swift/common/utils.py index 00cf119f07..c2499821f4 100644 --- a/swift/common/utils.py +++ b/swift/common/utils.py @@ -233,25 +233,26 @@ def validate_hash_conf(): if six.PY3: # Use Latin1 to accept arbitrary bytes in the hash prefix/suffix - confs_read = hash_conf.read(SWIFT_CONF_FILE, encoding='latin1') + with open(SWIFT_CONF_FILE, encoding='latin1') as swift_conf_file: + hash_conf.readfp(swift_conf_file) else: - confs_read = hash_conf.read(SWIFT_CONF_FILE) + with open(SWIFT_CONF_FILE) as swift_conf_file: + hash_conf.readfp(swift_conf_file) - if confs_read: - try: - HASH_PATH_SUFFIX = hash_conf.get('swift-hash', - 'swift_hash_path_suffix') - if six.PY3: - HASH_PATH_SUFFIX = HASH_PATH_SUFFIX.encode('latin1') - except (NoSectionError, NoOptionError): - pass - try: - HASH_PATH_PREFIX = hash_conf.get('swift-hash', - 'swift_hash_path_prefix') - if six.PY3: - HASH_PATH_PREFIX = HASH_PATH_PREFIX.encode('latin1') - except (NoSectionError, NoOptionError): - pass + try: + HASH_PATH_SUFFIX = hash_conf.get('swift-hash', + 'swift_hash_path_suffix') + if six.PY3: + HASH_PATH_SUFFIX = HASH_PATH_SUFFIX.encode('latin1') + except (NoSectionError, NoOptionError): + pass + try: + HASH_PATH_PREFIX = hash_conf.get('swift-hash', + 'swift_hash_path_prefix') + if six.PY3: + HASH_PATH_PREFIX = HASH_PATH_PREFIX.encode('latin1') + except (NoSectionError, NoOptionError): + pass if not HASH_PATH_SUFFIX and not HASH_PATH_PREFIX: raise InvalidHashPathConfigError() @@ -259,7 +260,7 @@ def validate_hash_conf(): try: validate_hash_conf() -except InvalidHashPathConfigError: +except (InvalidHashPathConfigError, IOError): # could get monkey patched or lazy loaded pass diff --git a/test/unit/common/ring/test_ring.py b/test/unit/common/ring/test_ring.py index 863c713280..3b4b1467a3 100644 --- a/test/unit/common/ring/test_ring.py +++ b/test/unit/common/ring/test_ring.py @@ -248,7 +248,7 @@ class TestRing(TestRingBase): with mock.patch.object(utils, 'HASH_PATH_SUFFIX', b''), \ mock.patch.object(utils, 'HASH_PATH_PREFIX', b''), \ mock.patch.object(utils, 'SWIFT_CONF_FILE', ''): - self.assertRaises(SystemExit, ring.Ring, self.testdir, 'whatever') + self.assertRaises(IOError, ring.Ring, self.testdir, 'whatever') def test_replica_count(self): self.assertEqual(self.ring.replica_count, 3) diff --git a/test/unit/common/test_utils.py b/test/unit/common/test_utils.py index 40afc6351e..06e54d5e3e 100644 --- a/test/unit/common/test_utils.py +++ b/test/unit/common/test_utils.py @@ -2085,11 +2085,21 @@ class TestUtils(unittest.TestCase): ['swift-hash-xxx'], ['swift_hash_path_suffix', 'swift_hash_path_prefix'], True) + # Unreadable/missing swift.conf causes IOError + # We mock in case the unit tests are run on a laptop with SAIO, + # which does have a natural /etc/swift/swift.conf. + with mock.patch('swift.common.utils.HASH_PATH_PREFIX', b''), \ + mock.patch('swift.common.utils.HASH_PATH_SUFFIX', b''), \ + mock.patch('swift.common.utils.SWIFT_CONF_FILE', + '/nosuchfile'), \ + self.assertRaises(IOError): + utils.validate_hash_conf() + def _test_validate_hash_conf(self, sections, options, should_raise_error): class FakeConfigParser(object): - def read(self, conf_path, encoding=None): - return [conf_path] + def readfp(self, fp): + pass def get(self, section, option): if section not in sections: @@ -2101,6 +2111,8 @@ class TestUtils(unittest.TestCase): with mock.patch('swift.common.utils.HASH_PATH_PREFIX', b''), \ mock.patch('swift.common.utils.HASH_PATH_SUFFIX', b''), \ + mock.patch('swift.common.utils.SWIFT_CONF_FILE', + '/dev/null'), \ mock.patch('swift.common.utils.ConfigParser', FakeConfigParser): try: