diff options
| author | Jenkins <jenkins@review.openstack.org> | 2013-06-06 15:07:43 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2013-06-06 15:07:43 +0000 |
| commit | 5231a786f2b0be11a1abda2f0a7f595586837b3c (patch) | |
| tree | 9cf2ac4b8de982626b2aa1efd74c32320506c0f6 | |
| parent | 35f90d719f2941fb6f2b660c18980bc9a93d2754 (diff) | |
| parent | 21ee25f07ad06c12150b2321d494eab641ef9ac2 (diff) | |
| download | oslo-5231a786f2b0be11a1abda2f0a7f595586837b3c.tar.gz oslo-5231a786f2b0be11a1abda2f0a7f595586837b3c.tar.xz oslo-5231a786f2b0be11a1abda2f0a7f595586837b3c.zip | |
Merge "Add common code for fileutils."
| -rw-r--r-- | openstack/common/fileutils.py | 31 | ||||
| -rw-r--r-- | tests/unit/test_fileutils.py | 50 |
2 files changed, 81 insertions, 0 deletions
diff --git a/openstack/common/fileutils.py b/openstack/common/fileutils.py index bb2ef61..0c967da 100644 --- a/openstack/common/fileutils.py +++ b/openstack/common/fileutils.py @@ -16,9 +16,11 @@ # under the License. +import contextlib import errno import os +from openstack.common import excutils from openstack.common.gettextutils import _ from openstack.common import log as logging @@ -65,3 +67,32 @@ def read_cached_file(filename, force_reload=False): cache_info['mtime'] = mtime reloaded = True return (reloaded, cache_info['data']) + + +def delete_if_exists(path): + """Delete a file, but ignore file not found error. + + :param path: File to delete + """ + + try: + os.unlink(path) + except OSError as e: + if e.errno == errno.ENOENT: + return + else: + raise + + +@contextlib.contextmanager +def remove_path_on_error(path): + """Protect code that wants to operate on PATH atomically. + Any exception will cause PATH to be removed. + + :param path: File to work with + """ + try: + yield + except Exception: + with excutils.save_and_reraise_exception(): + delete_if_exists(path) diff --git a/tests/unit/test_fileutils.py b/tests/unit/test_fileutils.py index 7cd067c..030f5f0 100644 --- a/tests/unit/test_fileutils.py +++ b/tests/unit/test_fileutils.py @@ -16,10 +16,12 @@ # under the License. import __builtin__ +import errno import os import shutil import tempfile +import mock import mox from openstack.common import fileutils @@ -82,3 +84,51 @@ class TestCachedFile(utils.BaseTestCase): fresh, data = fileutils.read_cached_file("/this/is/a/fake") self.assertEqual(data, fake_contents) self.assertTrue(fresh) + + +class DeleteIfExists(utils.BaseTestCase): + def test_file_present(self): + tmpfile = tempfile.mktemp() + + open(tmpfile, 'w') + fileutils.delete_if_exists(tmpfile) + self.assertFalse(os.path.exists(tmpfile)) + + def test_file_absent(self): + tmpfile = tempfile.mktemp() + + fileutils.delete_if_exists(tmpfile) + self.assertFalse(os.path.exists(tmpfile)) + + @mock.patch('os.unlink') + def test_file_error(self, osunlink): + tmpfile = tempfile.mktemp() + + open(tmpfile, 'w') + + error = OSError() + error.errno = errno.EINVAL + osunlink.side_effect = error + + self.assertRaises(OSError, fileutils.delete_if_exists, tmpfile) + + +class RemovePathOnError(utils.BaseTestCase): + def test_error(self): + tmpfile = tempfile.mktemp() + open(tmpfile, 'w') + + try: + with fileutils.remove_path_on_error(tmpfile): + raise Exception + except Exception: + self.assertFalse(os.path.exists(tmpfile)) + + def test_no_error(self): + tmpfile = tempfile.mktemp() + open(tmpfile, 'w') + + with fileutils.remove_path_on_error(tmpfile): + pass + self.assertTrue(os.path.exists(tmpfile)) + os.unlink(tmpfile) |
