Checks for presence of xvda, vda, and sda, and creates the partitions on
the first one found.

Signed-off-by: Ben Lipton <[email protected]>
---
 p2v-transfer/p2v_transfer.py           |   47 ++++++++++++++++++++++-------
 p2v-transfer/test/p2v_transfer_test.py |   51 +++++++++++++++++++++++++------
 2 files changed, 77 insertions(+), 21 deletions(-)

diff --git a/p2v-transfer/p2v_transfer.py b/p2v-transfer/p2v_transfer.py
index e98dc00..478d9b1 100755
--- a/p2v-transfer/p2v_transfer.py
+++ b/p2v-transfer/p2v_transfer.py
@@ -325,7 +325,8 @@ def _GetDeviceFile(dev):
   else:
     return dev
 
-def GetDiskSize(client, swap_devs):
+
+def GetDiskSize(client, swap_devs, target_hd):
   """Determine how much disk is available, how much swap space to include.
 
   For swap size, returns the minimum of:
@@ -336,6 +337,8 @@ def GetDiskSize(client, swap_devs):
   @param client: SSH client object used to connect to the instance.
   @type swap_devs: list
   @param swap_devs: List of swap partitions on the source machine.
+  @type target_hd: str
+  @param target_hd: Device file for the instance hard drive.
   @rtype: (int, int)
   @return: Total size in megabytes, swap size in megabytes
 
@@ -343,7 +346,8 @@ def GetDiskSize(client, swap_devs):
   DisplayCommandStart("Determining partition sizes...")
 
    # Find out how many MB are available on target
-  stdin, stdout, stderr = client.exec_command("blockdev --getsize64 /dev/xvda")
+  stdin, stdout, stderr = client.exec_command("blockdev --getsize64 %s" %
+                                              target_hd)
   for line in stdout:
     if line.strip():
       total_megs = int(line.strip()) / (1024 * 1024)
@@ -408,7 +412,7 @@ def ParseFstab(fstab_data):
   return fs_devs, swap_devs
 
 
-def PartitionTargetDisks(client, total_megs, swap_megs):
+def PartitionTargetDisks(client, total_megs, swap_megs, target_hd):
   """Partition and format the disks on the target machine.
 
   Sends commands over the SSH connection to partition and format the
@@ -420,22 +424,24 @@ def PartitionTargetDisks(client, total_megs, swap_megs):
   @param total_megs: Total size of disk, in megabytes
   @type swap_megs: int
   @param swap_megs: Desired size of swap space, in megabytes
+  @type target_hd: str
+  @param target_hd: Device file for the instance hard drive.
 
   """
   DisplayCommandStart("Partitioning disks...")
 
   nonswap_megs = total_megs - swap_megs
-  sfdisk_command = """sfdisk -uM /dev/xvda <<EOF
+  sfdisk_command = """sfdisk -uM %s <<EOF
 0,%d,83
 ,,82
 EOF
-""" % nonswap_megs
+""" % (target_hd, nonswap_megs)
 
   other_commands = [
-    "mkfs.ext3 /dev/xvda1",
-    "mkswap /dev/xvda2",
+    "mkfs.ext3 %s1" % target_hd,
+    "mkswap %s2" % target_hd,
     "mkdir -p %s" % TARGET_MOUNT,
-    "mount /dev/xvda1 %s" % TARGET_MOUNT,
+    "mount %s1 %s" % (target_hd, TARGET_MOUNT),
     ]
 
   try:
@@ -553,6 +559,24 @@ def DisplayCommandEnd(message):
   print message
 
 
+def FindTargetHardDrive(client):
+  """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.
+
+  @type client: paramiko.SSHClient
+  @param client: SSH client object used to connect to the instance.
+
+  """
+  for hd in ["/dev/xvda", "/dev/vda", "/dev/sda"]:
+    stdin, stdout, stderr = client.exec_command("test -b %s" % hd)
+    _WaitForCompletion(stdout.channel)
+    if stdout.channel.recv_exit_status() == 0:
+      return hd
+  raise P2VError("Could not locate a hard drive on the target.")
+
+
 def main(argv):
   client = None
   uid = None
@@ -571,9 +595,10 @@ def main(argv):
       key = LoadSSHKey(keyfile)
       client = EstablishConnection(user, host, key)
       fs_devs, swap_devs = MountSourceFilesystems(root_dev)
+      target_hd = FindTargetHardDrive(client)
       if options.skip_kernel_check or VerifyKernelMatches(client):
-        total_megs, swap_megs = GetDiskSize(client, swap_devs)
-        PartitionTargetDisks(client, total_megs, swap_megs)
+        total_megs, swap_megs = GetDiskSize(client, swap_devs, target_hd)
+        PartitionTargetDisks(client, total_megs, swap_megs, target_hd)
         TransferFiles(user, host, keyfile)
         RunFixScripts(client)
         ShutDownTarget(client)
@@ -581,7 +606,7 @@ def main(argv):
         raise P2VError("Modules matching instance kernel not present on source"
                        " OS. If your kernel does not use modules, you may want"
                        " the --skip-kernel-check option.")
-    except Exception, e:  # Make sure any error gets printed out
+    except P2VError, e:  # Print error message
       print e
       sys.exit(1)
   finally:
diff --git a/p2v-transfer/test/p2v_transfer_test.py 
b/p2v-transfer/test/p2v_transfer_test.py
index a224b9b..13efd74 100755
--- a/p2v-transfer/test/p2v_transfer_test.py
+++ b/p2v-transfer/test/p2v_transfer_test.py
@@ -57,6 +57,7 @@ class P2vtransferTest(unittest.TestCase):
     self.module = p2v_transfer
 
     self.root_dev = "/dev/sda1"
+    self.target_hd = "/dev/xvda"
     self.host = "testmachine"
     self.pkeyfile = "/home/testuser/.ssh/id_dsa"
     self.pkey = "thepkey"
@@ -122,6 +123,7 @@ UUID=55555555-5555-5555-5555-555555555555 /usr ext3 
defaults 0 2
       "LoadSSHKey",
       "CleanUpTarget",
       "ParseFstab",
+      "FindTargetHardDrive",
       ]
     for func in self.module_functions:
       self.mox.StubOutWithMock(self.module, func)
@@ -162,7 +164,8 @@ UUID=55555555-5555-5555-5555-555555555555 /usr ext3 
defaults 0 2
     popen.communicate().AndReturn((str(swap_bytes), None))
 
     self.mox.ReplayAll()
-    total, swap = self.module.GetDiskSize(self.client, self.swap_devs)
+    total, swap = self.module.GetDiskSize(self.client, self.swap_devs,
+                                          self.target_hd)
     self.assertEqual(total, self.totsize)
     # Should return same swap size as source machine
     self.assertEqual(swap, self.swapsize)
@@ -196,7 +199,8 @@ UUID=55555555-5555-5555-5555-555555555555 /usr ext3 
defaults 0 2
     popen.communicate().AndReturn((str(swap_bytes), None))
 
     self.mox.ReplayAll()
-    total, swap = self.module.GetDiskSize(self.client, self.swap_devs)
+    total, swap = self.module.GetDiskSize(self.client, self.swap_devs,
+                                          self.target_hd)
     self.assertEqual(total, self.totsize)
     # swap size should be about 10% of the total
     self.assertEqual(swap, self.totsize/10)
@@ -220,7 +224,30 @@ EOF
     self._MockRunCommandAndWait(commands)
 
     self.mox.ReplayAll()
-    self.module.PartitionTargetDisks(self.client, self.totsize, self.swapsize)
+    self.module.PartitionTargetDisks(self.client, self.totsize, self.swapsize,
+                                     self.target_hd)
+    self.mox.VerifyAll()
+
+  def testPartitionTargetDisksUsesKVMDevice(self):
+    self.target_hd = "/dev/vda"
+    sfdisk_command = """sfdisk -uM /dev/vda <<EOF
+0,%d,83
+,,82
+EOF
+""" % (self.totsize - self.swapsize)
+
+    self._MockRunCommandAndWait(sfdisk_command)
+
+    commands = ("mkfs.ext3 /dev/vda1"
+                " && mkswap /dev/vda2"
+                " && mkdir -p %s"
+                " && mount /dev/vda1 %s") % (self.module.TARGET_MOUNT,
+                                              self.module.TARGET_MOUNT)
+    self._MockRunCommandAndWait(commands)
+
+    self.mox.ReplayAll()
+    self.module.PartitionTargetDisks(self.client, self.totsize, self.swapsize,
+                                     self.target_hd)
     self.mox.VerifyAll()
 
   def testPartitionTargetDisksRetriesFormatOnError(self):
@@ -245,7 +272,8 @@ EOF
     self._MockRunCommandAndWait(commands)  # and try both commands again
 
     self.mox.ReplayAll()
-    self.module.PartitionTargetDisks(self.client, self.totsize, self.swapsize)
+    self.module.PartitionTargetDisks(self.client, self.totsize, self.swapsize,
+                                     self.target_hd)
     self.mox.VerifyAll()
 
   def testTransferFilesExitsOnError(self):
@@ -315,11 +343,13 @@ EOF
                                     self.pkey).AndReturn(self.client)
     call = self.module.MountSourceFilesystems(self.root_dev)
     call.AndReturn((self.fs_devs, self.swap_devs))
+    self.module.FindTargetHardDrive(self.client).AndReturn(self.target_hd)
     self.module.VerifyKernelMatches(self.client).AndReturn(True)
-    self.module.GetDiskSize(self.client,
-                            self.swap_devs).AndReturn((self.totsize,
+    self.module.GetDiskSize(self.client, self.swap_devs,
+                            self.target_hd).AndReturn((self.totsize,
                                                        self.swapsize))
-    self.module.PartitionTargetDisks(self.client, self.totsize, self.swapsize)
+    self.module.PartitionTargetDisks(self.client, self.totsize, self.swapsize,
+                                     self.target_hd)
     self.module.TransferFiles("root", self.host, self.pkeyfile)
     self.module.RunFixScripts(self.client)
     self.module.ShutDownTarget(self.client)
@@ -365,12 +395,13 @@ EOF
                                     self.pkey).AndReturn(self.client)
     call = self.module.MountSourceFilesystems(self.root_dev)
     call.AndReturn((self.fs_devs, self.swap_devs))
+    self.module.FindTargetHardDrive(self.client).AndReturn(self.target_hd)
     self.module.VerifyKernelMatches(self.client).AndReturn(True)
-    self.module.GetDiskSize(self.client,
-                            self.swap_devs).AndReturn((self.totsize,
+    self.module.GetDiskSize(self.client, self.swap_devs,
+                            self.target_hd).AndReturn((self.totsize,
                                                        self.swapsize))
     call = self.module.PartitionTargetDisks(self.client, self.totsize,
-                                            self.swapsize)
+                                            self.swapsize, self.target_hd)
     call.AndRaise(self.module.P2VError("meep"))
     # Transfer is cancelled because of the error, but still we have:
     self.module.UnmountSourceFilesystems(self.fs_devs)
-- 
1.7.3.1

Reply via email to