[master 2/4] Manage backing store more independently in loop backed test cases.
mulkieran
installerbot-noreply at redhat.com
Fri May 22 13:59:33 UTC 2015
From: mulhern <amulhern at redhat.com>
* Make the backing store before starting to use the loop devices so there
is less elapsed time between finding a free loop device and actually using
it. Get rid of it if there is a failure in locating a free loop device
or using it.
* Make self._loopMap a list of pairs, since we never do random access
anyway.
* Make the names of our temp files that back the loop devices less likely
to be reused by adding a random string to their names.
* Don't give up on deleting all loop devices the first time one loop
device is not succesfully removed.
* Give every loop device a minimum of three deletion attempts
before teardown gives up. This is apallingly ad-hoc, but almost works.
As many deletion attempts as needed is sometimes infinitely too many.
Signed-off-by: mulhern <amulhern at redhat.com>
---
tests/loopbackedtestcase.py | 50 ++++++++++++++++++++++++++++++++-------------
1 file changed, 36 insertions(+), 14 deletions(-)
diff --git a/tests/loopbackedtestcase.py b/tests/loopbackedtestcase.py
index 9451ed1..d60ba01 100644
--- a/tests/loopbackedtestcase.py
+++ b/tests/loopbackedtestcase.py
@@ -1,13 +1,13 @@
import unittest
import os
+import random
import subprocess
from blivet.size import Size
-def makeLoopDev(device_name, file_name, num_blocks=102400, block_size=1024):
- """ Set up a loop device with a backing store.
+def makeStore(file_name, num_blocks=102400, block_size=1024):
+ """ Set up the backing store for a loop device.
- :param str device_name: the path of the loop device
:param str file_name: the path of the backing file
:param int num_blocks: the size of file_name in number of blocks
:param int block_size: the number of bytes in a block
@@ -23,6 +23,13 @@ def makeLoopDev(device_name, file_name, num_blocks=102400, block_size=1024):
if rc:
raise OSError("dd failed creating the file %s" % file_name)
+def makeLoopDev(device_name, file_name):
+ """ Set up a loop device with a backing store.
+
+ :param str device_name: the path of the loop device
+ :param str file_name: the path of the backing file
+ """
+
proc = subprocess.Popen(["losetup", device_name, file_name],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
while True:
@@ -33,7 +40,7 @@ def makeLoopDev(device_name, file_name, num_blocks=102400, block_size=1024):
if rc:
raise OSError("losetup failed setting up the loop device %s" % device_name)
-def removeLoopDev(device_name, file_name):
+def removeLoopDev(device_name):
proc = subprocess.Popen(["losetup", "-d", device_name],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
while True:
@@ -44,8 +51,6 @@ def removeLoopDev(device_name, file_name):
if rc:
raise OSError("losetup failed removing the loop device %s" % device_name)
- os.unlink(file_name)
-
def getFreeLoopDev():
# There's a race condition here where another process could grab the loop
# device losetup gives us before we have time to set it up, but that's just
@@ -72,7 +77,7 @@ class LoopBackedTestCase(unittest.TestCase):
DEFAULT_BLOCK_SIZE = Size("1 KiB")
DEFAULT_STORE_SIZE = Size("100 MiB")
_DEFAULT_DEVICE_SPEC = [DEFAULT_STORE_SIZE, DEFAULT_STORE_SIZE]
- _STORE_FILE_TEMPLATE = 'test-virtdev%d'
+ _STORE_FILE_TEMPLATE = 'test-virtdev%d-%s'
_STORE_FILE_PATH = '/var/tmp'
def __init__(self, methodName='runTest', deviceSpec=None, block_size=None):
@@ -88,7 +93,7 @@ def __init__(self, methodName='runTest', deviceSpec=None, block_size=None):
"""
unittest.TestCase.__init__(self, methodName=methodName)
self._deviceSpec = deviceSpec or self._DEFAULT_DEVICE_SPEC
- self._loopMap = {}
+ self._loopMap = []
self.loopDevices = []
self.block_size = block_size or self.DEFAULT_BLOCK_SIZE
@@ -96,14 +101,31 @@ def __init__(self, methodName='runTest', deviceSpec=None, block_size=None):
raise ValueError("Every device size must be a multiple of the block size.")
def setUp(self):
+ random_str = '%06x' % random.randrange(16**6)
for index, size in enumerate(self._deviceSpec):
- store = os.path.join(self._STORE_FILE_PATH, self._STORE_FILE_TEMPLATE % index)
- dev = getFreeLoopDev()
+ store = os.path.join(self._STORE_FILE_PATH, self._STORE_FILE_TEMPLATE % (index, random_str))
num_blocks = int(size / self.block_size)
- makeLoopDev(dev, store, num_blocks=num_blocks, block_size=int(self.block_size))
- self._loopMap[dev] = store
+ makeStore(store, num_blocks, int(self.block_size))
+
+ dev = None
+ try:
+ dev = getFreeLoopDev()
+ makeLoopDev(dev, store)
+ except OSError:
+ os.unlink(store)
+ raise
+
+ self._loopMap.append((dev, store))
self.loopDevices.append(dev)
def tearDown(self):
- for (dev, store) in iter(self._loopMap.items()):
- removeLoopDev(dev, store)
+ l = len(self._loopMap)
+ for _ in range(3 * l):
+ if not self._loopMap:
+ break
+ dev, store = self._loopMap.pop(0)
+ try:
+ removeLoopDev(dev)
+ os.unlink(store)
+ except OSError:
+ self._loopMap.append((dev, store))
--
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/4f1671e812b8d0b8113520d55b89807fbf8686c7
More information about the anaconda-patches
mailing list