Now, fix_fstab uses the same algorithm to decide what drive to use - it takes the first one found of /dev/xvda, /dev/vda, and /dev/sda.
Also, fix a docstring. Signed-off-by: Ben Lipton <[email protected]> --- instance-p2v-target/fixes/fixlib/__init__.py | 20 ++++++++++++++++ instance-p2v-target/fixes/fixlib/fix_fstab.py | 20 ++++++++-------- instance-p2v-target/test/fix_fstab_test.py | 30 +++++++++++++++++++++++++ p2v-transfer/p2v_transfer.py | 4 ++- 4 files changed, 63 insertions(+), 11 deletions(-) diff --git a/instance-p2v-target/fixes/fixlib/__init__.py b/instance-p2v-target/fixes/fixlib/__init__.py index b9e9ecc..1a2ca4d 100644 --- a/instance-p2v-target/fixes/fixlib/__init__.py +++ b/instance-p2v-target/fixes/fixlib/__init__.py @@ -25,5 +25,25 @@ can be unit tested but also run with run-parts. """ +import subprocess + + class FixError(Exception): pass + + +def FindTargetHardDrive(): + """Find the name of the first hard drive on the target machine. + + Tries, in order, /dev/{xvda,vda,sda} and returns the first one that exists on + the target machine. + + @rtype: str + @return: name of the hard drive device to install onto + + """ + for hd in ["/dev/xvda", "/dev/vda", "/dev/sda"]: + status = subprocess.call(["test", "-b", hd]) + if status == 0: + return hd + raise FixError("Could not locate a hard drive.") diff --git a/instance-p2v-target/fixes/fixlib/fix_fstab.py b/instance-p2v-target/fixes/fixlib/fix_fstab.py index 905531d..6856e3e 100644 --- a/instance-p2v-target/fixes/fixlib/fix_fstab.py +++ b/instance-p2v-target/fixes/fixlib/fix_fstab.py @@ -40,20 +40,20 @@ def FixFstab(fname_in="/target/etc/fstab", fname_out="/target/etc/fstab"): @param fname_out: Where to write the modified file. """ - # TODO(benlipton): This is totally xen-specific. Better would be to use the - # first that exists of /dev/{xvda,vda,sda}. - - # Note: This also assumes a particular partition layout (root partition on + # Note: This assumes a particular partition layout (root partition on # /dev/${device}1, swap partition on /dev/${device}2). This is only a problem # if we allow configurable partition layouts, so we'll let it stand for now, # but for the future, the bootstrap OS's /etc/mtab probably contains enough # information to reconstruct the whole partitioning scheme. uuids = {} fstypes = {} - disk_name = "xvda" + disk_name = fixlib.FindTargetHardDrive() + root_dev = "%s1" % disk_name + swap_dev = "%s2" % disk_name + p = subprocess.Popen(["blkid"], stdout=subprocess.PIPE) - devregex = re.compile("/dev/(%s[0-9]):" % disk_name) + devregex = re.compile("^(%s[0-9]):" % disk_name) uuidregex = re.compile("UUID=\"([-a-z0-9]+)\"") typeregex = re.compile("TYPE=\"(.+)\"") @@ -66,7 +66,7 @@ def FixFstab(fname_in="/target/etc/fstab", fname_out="/target/etc/fstab"): uuids[partname] = uuidmatch.group(1) fstypes[partname] = typematch.group(1) - if "xvda1" not in uuids or "xvda2" not in uuids: + if root_dev not in uuids or swap_dev not in uuids: raise fixlib.FixError("Could not determine UUID of root and swap" " filesystems. Found filesystems were: %s\n" "/etc/fstab may need to be edited by hand." % uuids) @@ -77,11 +77,11 @@ def FixFstab(fname_in="/target/etc/fstab", fname_out="/target/etc/fstab"): parts = line.split() if len(parts) >= 2 and parts[0][0] != "#": # Line containing a filesystem if parts[1] == "/": # root partition - parts[0] = "UUID=%s" % uuids["xvda1"] - parts[2] = fstypes["xvda1"] + parts[0] = "UUID=%s" % uuids[root_dev] + parts[2] = fstypes[root_dev] line = "\t".join(parts) + "\n" elif parts[2] == "swap": # swap partition - parts[0] = "UUID=%s" % uuids["xvda2"] + parts[0] = "UUID=%s" % uuids[swap_dev] line = "\t".join(parts) + "\n" elif IsAutomountedBlockDevice(parts): line = "# " + line diff --git a/instance-p2v-target/test/fix_fstab_test.py b/instance-p2v-target/test/fix_fstab_test.py index e9431ef..385b5ae 100755 --- a/instance-p2v-target/test/fix_fstab_test.py +++ b/instance-p2v-target/test/fix_fstab_test.py @@ -8,6 +8,7 @@ import mox import os import tempfile +import types import unittest from fixlib import fix_fstab @@ -19,17 +20,31 @@ class FixFstabTest(unittest.TestCase): def setUp(self): self.mox = mox.Mox() + self.module = fix_fstab def tearDown(self): self.mox.UnsetStubs() self.mox.ResetAll() + def _MockSubprocessCallSuccess(self, command_list): + if type(self.module.subprocess.call) == types.FunctionType: + self.mox.StubOutWithMock(self.module.subprocess, "call") + self.module.subprocess.call(command_list).AndReturn(0) + + def _MockSubprocessCallFailure(self, command_list): + if type(self.module.subprocess.call) == types.FunctionType: + self.mox.StubOutWithMock(self.module.subprocess, "call") + self.module.subprocess.call(command_list).AndReturn(1) + def testFixFstabReplacesRootLine(self): # stub out blkid call mock_popen = self.mox.CreateMock(fix_fstab.subprocess.Popen) + self.mox.StubOutWithMock(fix_fstab.fixlib, "FindTargetHardDrive") self.mox.StubOutWithMock(fix_fstab.subprocess, "Popen", use_mock_anything=True) + + fix_fstab.fixlib.FindTargetHardDrive().AndReturn("/dev/xvda") call = fix_fstab.subprocess.Popen(["blkid"], stdout=fix_fstab.subprocess.PIPE) call.AndReturn(mock_popen) @@ -62,8 +77,11 @@ class FixFstabTest(unittest.TestCase): # stub out blkid call mock_popen = self.mox.CreateMock(fix_fstab.subprocess.Popen) + self.mox.StubOutWithMock(fix_fstab.fixlib, "FindTargetHardDrive") self.mox.StubOutWithMock(fix_fstab.subprocess, "Popen", use_mock_anything=True) + + fix_fstab.fixlib.FindTargetHardDrive().AndReturn("/dev/xvda") call = fix_fstab.subprocess.Popen(["blkid"], stdout=fix_fstab.subprocess.PIPE) call.AndReturn(mock_popen) @@ -84,5 +102,17 @@ class FixFstabTest(unittest.TestCase): os.remove(fname_out) + def testFindTargetHardDriveReturnsFirstAvailableDrive(self): + self._MockSubprocessCallFailure(["test", "-b", "/dev/xvda"]) + self._MockSubprocessCallSuccess(["test", "-b", "/dev/vda"]) + + self.mox.ReplayAll() + + dev = fix_fstab.fixlib.FindTargetHardDrive() + self.assertEqual("/dev/vda", dev) + + self.mox.VerifyAll() + + if __name__ == '__main__': unittest.main() diff --git a/p2v-transfer/p2v_transfer.py b/p2v-transfer/p2v_transfer.py index 478d9b1..ef3aac4 100755 --- a/p2v-transfer/p2v_transfer.py +++ b/p2v-transfer/p2v_transfer.py @@ -566,7 +566,9 @@ def FindTargetHardDrive(client): the target machine. @type client: paramiko.SSHClient - @param client: SSH client object used to connect to the instance. + @param client: SSH client object used to connect to the instance + @rtype: str + @return: name of the hard drive device to install onto """ for hd in ["/dev/xvda", "/dev/vda", "/dev/sda"]: -- 1.7.3.1
