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

Reply via email to