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
