diff options
| author | Jenkins <jenkins@review.openstack.org> | 2011-09-30 15:40:04 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2011-09-30 15:40:04 +0000 |
| commit | 96b99e4d1f5f264e7f263ddbf50981abf5a3b04e (patch) | |
| tree | a20a6d10fce59da6232e30eedb8f5555aeb28383 | |
| parent | cb6250fa77d7724ba7e5dd15e8a3c9973756c1f5 (diff) | |
| parent | b9aac1181581b9036c98f5aa493731fdc74be7e1 (diff) | |
| download | nova-96b99e4d1f5f264e7f263ddbf50981abf5a3b04e.tar.gz nova-96b99e4d1f5f264e7f263ddbf50981abf5a3b04e.tar.xz nova-96b99e4d1f5f264e7f263ddbf50981abf5a3b04e.zip | |
Merge "Fixed bug lp850602. Adding backing file copy operation on kvm block migration."
| -rw-r--r-- | nova/tests/test_libvirt.py | 26 | ||||
| -rw-r--r-- | nova/virt/libvirt/connection.py | 33 |
2 files changed, 47 insertions, 12 deletions
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py index aefe26cc8..8b6f2080d 100644 --- a/nova/tests/test_libvirt.py +++ b/nova/tests/test_libvirt.py @@ -629,9 +629,12 @@ class LibvirtConnTestCase(test.TestCase): fake_timer = FakeTime() + # _fake_network_info must be called before create_fake_libvirt_mock(), + # as _fake_network_info calls utils.import_class() and + # create_fake_libvirt_mock() mocks utils.import_class(). + network_info = _fake_network_info(self.stubs, 1) self.create_fake_libvirt_mock() instance_ref = db.instance_create(self.context, self.test_instance) - network_info = _fake_network_info(self.stubs, 1) # Start test self.mox.ReplayAll() @@ -684,10 +687,7 @@ class LibvirtConnTestCase(test.TestCase): return vdmock self.create_fake_libvirt_mock(lookupByName=fake_lookup) -# self.mox.StubOutWithMock(self.compute, "recover_live_migration") self.mox.StubOutWithMock(self.compute, "rollback_live_migration") -# self.compute.recover_live_migration(self.context, instance_ref, -# dest='dest') self.compute.rollback_live_migration(self.context, instance_ref, 'dest', False) @@ -722,7 +722,8 @@ class LibvirtConnTestCase(test.TestCase): # Test data instance_ref = db.instance_create(self.context, self.test_instance) - dummyjson = '[{"path": "%s/disk", "local_gb": "10G", "type": "raw"}]' + dummyjson = ('[{"path": "%s/disk", "local_gb": "10G",' + ' "type": "raw", "backing_file": ""}]') # Preparing mocks # qemu-img should be mockd since test environment might not have @@ -763,7 +764,10 @@ class LibvirtConnTestCase(test.TestCase): "</devices></domain>") ret = ("image: /test/disk\nfile format: raw\n" - "virtual size: 20G (21474836480 bytes)\ndisk size: 3.1G\n") + "virtual size: 20G (21474836480 bytes)\ndisk size: 3.1G\n" + "disk size: 102M\n" + "cluster_size: 2097152\n" + "backing file: /test/dummy (actual path: /backing/file)\n") # Preparing mocks vdmock = self.mox.CreateMock(libvirt.virDomain) @@ -793,7 +797,9 @@ class LibvirtConnTestCase(test.TestCase): info[0]['path'] == '/test/disk' and info[1]['path'] == '/test/disk.local' and info[0]['local_gb'] == '10G' and - info[1]['local_gb'] == '20G') + info[1]['local_gb'] == '20G' and + info[0]['backing_file'] == "" and + info[1]['backing_file'] == "file") db.instance_destroy(self.context, instance_ref['id']) @@ -806,6 +812,10 @@ class LibvirtConnTestCase(test.TestCase): def fake_none(self, instance): return + # _fake_network_info must be called before create_fake_libvirt_mock(), + # as _fake_network_info calls utils.import_class() and + # create_fake_libvirt_mock() mocks utils.import_class(). + network_info = _fake_network_info(self.stubs, 1) self.create_fake_libvirt_mock() instance = db.instance_create(self.context, self.test_instance) @@ -815,8 +825,6 @@ class LibvirtConnTestCase(test.TestCase): conn.firewall_driver.setattr('setup_basic_filtering', fake_none) conn.firewall_driver.setattr('prepare_instance_filter', fake_none) - network_info = _fake_network_info(self.stubs, 1) - try: conn.spawn(self.context, instance, network_info) except Exception, e: diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py index 6afd41c1b..03b1a4ba4 100644 --- a/nova/virt/libvirt/connection.py +++ b/nova/virt/libvirt/connection.py @@ -1728,9 +1728,31 @@ class LibvirtConnection(driver.ComputeDriver): for info in disk_info: base = os.path.basename(info['path']) - # Get image type and create empty disk image. + # Get image type and create empty disk image, and + # create backing file in case of qcow2. instance_disk = os.path.join(instance_dir, base) - utils.execute('qemu-img', 'create', '-f', info['type'], + if not info['backing_file']: + utils.execute('qemu-img', 'create', '-f', info['type'], + instance_disk, info['local_gb']) + + else: + # Creating backing file follows same way as spawning instances. + backing_file = os.path.join(FLAGS.instances_path, + '_base', info['backing_file']) + + if not os.path.exists(backing_file): + self._cache_image(fn=self._fetch_image, + context=ctxt, + target=info['path'], + fname=info['backing_file'], + cow=FLAGS.use_cow_images, + image_id=instance_ref['image_ref'], + user_id=instance_ref['user_id'], + project_id=instance_ref['project_id'], + size=instance_ref['local_gb']) + + utils.execute('qemu-img', 'create', '-f', info['type'], + '-o', 'backing_file=%s' % backing_file, instance_disk, info['local_gb']) # if image has kernel and ramdisk, just download @@ -1821,12 +1843,17 @@ class LibvirtConnection(driver.ComputeDriver): driver_nodes[cnt].get_properties().get_next().getContent() if disk_type == 'raw': size = int(os.path.getsize(path)) + backing_file = "" else: out, err = utils.execute('qemu-img', 'info', path) size = [i.split('(')[1].split()[0] for i in out.split('\n') if i.strip().find('virtual size') >= 0] size = int(size[0]) + backing_file = [i.split('actual path:')[1].strip()[:-1] + for i in out.split('\n') if 0 <= i.find('backing file')] + backing_file = os.path.basename(backing_file[0]) + # block migration needs same/larger size of empty image on the # destination host. since qemu-img creates bit smaller size image # depending on original image size, fixed value is necessary. @@ -1842,7 +1869,7 @@ class LibvirtConnection(driver.ComputeDriver): break disk_info.append({'type': disk_type, 'path': path, - 'local_gb': size}) + 'local_gb': size, 'backing_file': backing_file}) return utils.dumps(disk_info) |
