Snap for 4640417 from b85743da03e772138a909471eefd93b52abd30a7 to oreo-mr1-vts-release
Change-Id: Id8d7682233f339ac811df56b96643036899ae692
diff --git a/internal/lib/utils.py b/internal/lib/utils.py
index 54524da..875e183 100755
--- a/internal/lib/utils.py
+++ b/internal/lib/utils.py
@@ -14,12 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-"""Common Utilities.
-
-The following code is copied from chromite with modifications.
- - class TempDir: chromite/lib/osutils.py
-
-"""
+"""Common Utilities."""
import base64
import binascii
@@ -46,70 +41,53 @@
class TempDir(object):
- """Object that creates a temporary directory.
+ """A context manager that ceates a temporary directory.
- This object can either be used as a context manager or just as a simple
- object. The temporary directory is stored as self.tempdir in the object, and
- is returned as a string by a 'with' statement.
+ Attributes:
+ path: The path of the temporary directory.
"""
- def __init__(self, prefix='tmp', base_dir=None, delete=True):
- """Constructor. Creates the temporary directory.
-
- Args:
- prefix: See tempfile.mkdtemp documentation.
- base_dir: The directory to place the temporary directory.
- If None, will choose from system default tmp dir.
- delete: Whether the temporary dir should be deleted as part of cleanup.
- """
- self.delete = delete
- self.tempdir = tempfile.mkdtemp(prefix=prefix, dir=base_dir)
- os.chmod(self.tempdir, 0o700)
-
- def Cleanup(self):
- """Clean up the temporary directory."""
- # Note that _TempDirSetup may have failed, resulting in these attributes
- # not being set; this is why we use getattr here (and must).
- tempdir = getattr(self, 'tempdir', None)
- if tempdir is not None and self.delete:
- try:
- shutil.rmtree(tempdir)
- except EnvironmentError as e:
- # Ignore error if directory or file does not exist.
- if e.errno != errno.ENOENT:
- raise
- finally:
- self.tempdir = None
+ def __init__(self):
+ self.path = tempfile.mkdtemp()
+ os.chmod(self.path, 0o700)
+ logger.debug("Created temporary dir %s", self.path)
def __enter__(self):
- """Return the temporary directory."""
- return self.tempdir
+ """Enter."""
+ return self.path
- def __exit__(self, exc_type, exc_value, exc_traceback):
- """Exit the context manager."""
+ def __exit__(self, exc_type, exc_value, traceback):
+ """Exit.
+
+ Args:
+ exc_type: Exception type raised within the context manager.
+ None if no execption is raised.
+ exc_value: Exception instance raised within the context manager.
+ None if no execption is raised.
+ traceback: Traceback for exeception that is raised within
+ the context manager.
+ None if no execption is raised.
+ Raises:
+ EnvironmentError or OSError when failed to delete temp directory.
+ """
try:
- self.Cleanup()
- except Exception: # pylint: disable=W0703
+ if self.path:
+ shutil.rmtree(self.path)
+ logger.debug("Deleted temporary dir %s", self.path)
+ except EnvironmentError as e:
+ # Ignore error if there is no exception raised
+ # within the with-clause and the EnvironementError is
+ # about problem that directory or file does not exist.
+ if not exc_type and e.errno != errno.ENOENT:
+ raise
+ except Exception as e: # pylint: disable=W0703
if exc_type:
- # If an exception from inside the context was already in progress,
- # log our cleanup exception, then allow the original to resume.
- logger.error('While exiting %s:', self, exc_info=True)
-
- if self.tempdir:
- # Log all files in tempdir at the time of the failure.
- try:
- logger.error('Directory contents were:')
- for name in os.listdir(self.tempdir):
- logger.error(' %s', name)
- except OSError:
- logger.error(' Directory did not exist.')
+ logger.error(
+ "Encountered error while deleting %s: %s",
+ self.path, str(e), exc_info=True)
else:
- # If there was not an exception from the context, raise ours.
raise
- def __del__(self):
- """Delete the object."""
- self.Cleanup()
def RetryOnException(retry_checker, max_retries, sleep_multiplier=0,
retry_backoff_factor=1):
diff --git a/internal/lib/utils_test.py b/internal/lib/utils_test.py
index bb1200e..a450933 100644
--- a/internal/lib/utils_test.py
+++ b/internal/lib/utils_test.py
@@ -16,9 +16,12 @@
"""Tests for acloud.internal.lib.utils."""
+import errno
import getpass
import os
+import shutil
import subprocess
+import tempfile
import time
import mock
@@ -30,6 +33,87 @@
class UtilsTest(driver_test_lib.BaseDriverTest):
+ def testTempDir_Success(self):
+ """Test create a temp dir."""
+ self.Patch(os, "chmod")
+ self.Patch(tempfile, "mkdtemp", return_value="/tmp/tempdir")
+ self.Patch(shutil, "rmtree")
+ with utils.TempDir():
+ pass
+ # Verify.
+ tempfile.mkdtemp.assert_called_once()
+ shutil.rmtree.assert_called_with("/tmp/tempdir")
+
+ def testTempDir_ExceptionRaised(self):
+ """Test create a temp dir and exception is raised within with-clause."""
+ self.Patch(os, "chmod")
+ self.Patch(tempfile, "mkdtemp", return_value="/tmp/tempdir")
+ self.Patch(shutil, "rmtree")
+
+ class ExpectedException(Exception):
+ pass
+
+ def _Call():
+ with utils.TempDir():
+ raise ExpectedException("Expected exception.")
+ # Verify. ExpectedException should be raised.
+ self.assertRaises(ExpectedException, _Call)
+ tempfile.mkdtemp.assert_called_once()
+ shutil.rmtree.assert_called_with("/tmp/tempdir")
+
+ def testTempDir_WhenDeleteTempDirNoLongerExist(self):
+ """Test create a temp dir and dir no longer exists during deletion."""
+ self.Patch(os, "chmod")
+ self.Patch(tempfile, "mkdtemp", return_value="/tmp/tempdir")
+ expected_error = EnvironmentError()
+ expected_error.errno = errno.ENOENT
+ self.Patch(shutil, "rmtree", side_effect=expected_error)
+ def _Call():
+ with utils.TempDir():
+ pass
+ # Verify no exception should be raised when rmtree raises
+ # EnvironmentError with errno.ENOENT, i.e.
+ # directory no longer exists.
+ _Call()
+ tempfile.mkdtemp.assert_called_once()
+ shutil.rmtree.assert_called_with("/tmp/tempdir")
+
+ def testTempDir_WhenDeleteEncounterError(self):
+ """Test create a temp dir and encoutered error during deletion."""
+ self.Patch(os, "chmod")
+ self.Patch(tempfile, "mkdtemp", return_value="/tmp/tempdir")
+ expected_error = OSError("Expected OS Error")
+ self.Patch(shutil, "rmtree", side_effect=expected_error)
+ def _Call():
+ with utils.TempDir():
+ pass
+
+ # Verify OSError should be raised.
+ self.assertRaises(OSError, _Call)
+ tempfile.mkdtemp.assert_called_once()
+ shutil.rmtree.assert_called_with("/tmp/tempdir")
+
+ def testTempDir_OrininalErrorRaised(self):
+ """Test original error is raised even if tmp dir deletion failed."""
+ self.Patch(os, "chmod")
+ self.Patch(tempfile, "mkdtemp", return_value="/tmp/tempdir")
+ expected_error = OSError("Expected OS Error")
+ self.Patch(shutil, "rmtree", side_effect=expected_error)
+
+ class ExpectedException(Exception):
+ pass
+
+ def _Call():
+ with utils.TempDir():
+ raise ExpectedException("Expected Exception")
+
+ # Verify.
+ # ExpectedException should be raised, and OSError
+ # should not be raised.
+ self.assertRaises(ExpectedException, _Call)
+ tempfile.mkdtemp.assert_called_once()
+ shutil.rmtree.assert_called_with("/tmp/tempdir")
+
def testCreateSshKeyPair_KeyAlreadyExists(self):
"""Test when the key pair already exists."""
public_key = "/fake/public_key"