diff options
| author | Chang Bo Guo <guochbo@cn.ibm.com> | 2013-04-25 23:40:12 -0700 |
|---|---|---|
| committer | Chang Bo Guo <guochbo@cn.ibm.com> | 2013-05-29 02:07:46 -0700 |
| commit | 68cc1cd511298208dde59878bfbef474a3625c9f (patch) | |
| tree | a7fd346ecc1b4e719496e70a93ab1db4ea914ca9 | |
| parent | 64b234d5cb69fbfd183d74f20d7b243569f6c6f6 (diff) | |
Clean up failed image transfers in instance spawn
Boot one instance with powervm driver, will transfer the image
file to host. Need clean up failed image transfers that may occur
during instance spawn.
Fixes bug #1173017
Change-Id: Iff5ecd32e201333567a6a4de1d3796e78ea5dc0c
| -rw-r--r-- | nova/tests/virt/powervm/test_powervm.py | 67 | ||||
| -rw-r--r-- | nova/virt/powervm/blockdev.py | 49 |
2 files changed, 97 insertions, 19 deletions
diff --git a/nova/tests/virt/powervm/test_powervm.py b/nova/tests/virt/powervm/test_powervm.py index ef4ea4a43..a923d52ff 100644 --- a/nova/tests/virt/powervm/test_powervm.py +++ b/nova/tests/virt/powervm/test_powervm.py @@ -19,6 +19,7 @@ Test suite for PowerVMDriver. """ import contextlib +import os import paramiko from nova import context @@ -744,3 +745,69 @@ class PowerVMLocalVolumeAdapterTestCase(test.TestCase): self.powervm_adapter.create_volume_from_image, self.context, self.instance, self.image_id) self.assertTrue(self.delete_volume_called) + + def test_copy_image_file_wrong_checksum(self): + file_path = os.tempnam('/tmp', 'image') + remote_path = '/mnt/openstack/images' + exp_remote_path = os.path.join(remote_path, + os.path.basename(file_path)) + exp_cmd = ' '.join(['/usr/bin/rm -f', exp_remote_path]) + + def fake_md5sum_remote_file(remote_path): + return '3202937169' + + def fake_checksum_local_file(source_path): + return '3229026618' + + fake_noop = lambda *args, **kwargs: None + fake_op = self.powervm_adapter + self.stubs.Set(fake_op, 'run_vios_command', fake_noop) + self.stubs.Set(fake_op, '_md5sum_remote_file', + fake_md5sum_remote_file) + self.stubs.Set(fake_op, '_checksum_local_file', + fake_checksum_local_file) + self.stubs.Set(common, 'ftp_put_command', fake_noop) + + self.mox.StubOutWithMock(self.powervm_adapter, + 'run_vios_command_as_root') + self.powervm_adapter.run_vios_command_as_root(exp_cmd).AndReturn([]) + + self.mox.ReplayAll() + + self.assertRaises(exception.PowerVMFileTransferFailed, + self.powervm_adapter._copy_image_file, + file_path, remote_path) + + def test_checksum_local_file(self): + file_path = os.tempnam('/tmp', 'image') + img_file = file(file_path, 'w') + img_file.write('This is a test') + img_file.close() + exp_md5sum = 'ce114e4501d2f4e2dcea3e17b546f339' + + self.assertEqual(self.powervm_adapter._checksum_local_file(file_path), + exp_md5sum) + os.remove(file_path) + + def test_copy_image_file_from_host_with_wrong_checksum(self): + local_path = 'some/tmp' + remote_path = os.tempnam('/mnt/openstack/images', 'image') + + def fake_md5sum_remote_file(remote_path): + return '3202937169' + + def fake_checksum_local_file(source_path): + return '3229026618' + + fake_noop = lambda *args, **kwargs: None + fake_op = self.powervm_adapter + self.stubs.Set(fake_op, 'run_vios_command_as_root', fake_noop) + self.stubs.Set(fake_op, '_md5sum_remote_file', + fake_md5sum_remote_file) + self.stubs.Set(fake_op, '_checksum_local_file', + fake_checksum_local_file) + self.stubs.Set(common, 'ftp_get_command', fake_noop) + + self.assertRaises(exception.PowerVMFileTransferFailed, + self.powervm_adapter._copy_image_file_from_host, + remote_path, local_path) diff --git a/nova/virt/powervm/blockdev.py b/nova/virt/powervm/blockdev.py index 5e207e1f2..73099b148 100644 --- a/nova/virt/powervm/blockdev.py +++ b/nova/virt/powervm/blockdev.py @@ -384,6 +384,22 @@ class PowerVMLocalVolumeAdapter(PowerVMDiskAdapter): output = self.run_vios_command_as_root(cmd) return output[0] + def _checksum_local_file(self, source_path): + """Calculate local file checksum. + + :param source_path: source file path + :returns: string -- the md5sum of local file + """ + with open(source_path, 'r') as img_file: + hasher = hashlib.md5() + block_size = 0x10000 + buf = img_file.read(block_size) + while len(buf) > 0: + hasher.update(buf) + buf = img_file.read(block_size) + source_cksum = hasher.hexdigest() + return source_cksum + def _copy_image_file(self, source_path, remote_path, decompress=False): """Copy file to VIOS, decompress it, and return its new size and name. @@ -393,14 +409,7 @@ class PowerVMLocalVolumeAdapter(PowerVMDiskAdapter): if False (default), just copies the file """ # Calculate source image checksum - hasher = hashlib.md5() - block_size = 0x10000 - img_file = file(source_path, 'r') - buf = img_file.read(block_size) - while len(buf) > 0: - hasher.update(buf) - buf = img_file.read(block_size) - source_cksum = hasher.hexdigest() + source_cksum = self._checksum_local_file(source_path) comp_path = os.path.join(remote_path, os.path.basename(source_path)) if comp_path.endswith(".gz"): @@ -426,10 +435,18 @@ class PowerVMLocalVolumeAdapter(PowerVMDiskAdapter): output = self._md5sum_remote_file(final_path) if not output: LOG.error(_("Unable to get checksum")) - raise exception.PowerVMFileTransferFailed() + # Cleanup inconsistent remote file + cmd = "/usr/bin/rm -f %s" % final_path + self.run_vios_command_as_root(cmd) + + raise exception.PowerVMFileTransferFailed(file_path=final_path) if source_cksum != output.split(' ')[0]: LOG.error(_("Image checksums do not match")) - raise exception.PowerVMFileTransferFailed() + # Cleanup inconsistent remote file + cmd = "/usr/bin/rm -f %s" % final_path + self.run_vios_command_as_root(cmd) + + raise exception.PowerVMFileTransferFailed(file_path=final_path) if decompress: # Unzip the image @@ -509,19 +526,13 @@ class PowerVMLocalVolumeAdapter(PowerVMDiskAdapter): local_file_path) # Calculate copied image checksum - with open(local_file_path, 'r') as image_file: - hasher = hashlib.md5() - block_size = 0x10000 - buf = image_file.read(block_size) - while len(buf) > 0: - hasher.update(buf) - buf = image_file.read(block_size) - dest_chksum = hasher.hexdigest() + dest_chksum = self._checksum_local_file(local_file_path) # do comparison if source_chksum and dest_chksum != source_chksum: LOG.error(_("Image checksums do not match")) - raise exception.PowerVMFileTransferFailed() + raise exception.PowerVMFileTransferFailed( + file_path=local_file_path) # Cleanup transferred remote file cmd = "/usr/bin/rm -f %s" % copy_from_path |
