From f5c9ebd56075f8eb04f9f0e683f85bacdcd68c38 Mon Sep 17 00:00:00 2001 From: melanie witt Date: Wed, 18 May 2016 00:09:18 +0000 Subject: [PATCH] Fall back to flat config drive if not found in rbd Commit adecf780d3ed4315e4ce305cb1821d493650494b added support for storing config drives in rbd. Existing instances however still have config drives in the instance directory. If an existing instance is stopped, an attempt to start it again fails because the guest config is generated assuming a config drive location in rbd. This adds a fall back to the instance directory in the case of config drive and rbd if the image is not found in rbd. Closes-Bug: #1582684 Change-Id: I21107ea0a148b66bee81e57cdce08e3006a60aee --- nova/tests/unit/virt/libvirt/test_driver.py | 30 +++++++++++++++++++++ nova/virt/libvirt/driver.py | 9 +++++++ 2 files changed, 39 insertions(+) diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index bfbe32d04923..60c16c3d1177 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -13765,6 +13765,36 @@ class LibvirtConnTestCase(test.NoDBTestCase): self._test_get_guest_config_parallels_volume(vm_mode.EXE, 4) self._test_get_guest_config_parallels_volume(vm_mode.HVM, 6) + def test_get_guest_disk_config_rbd_older_config_drive_fall_back(self): + # New config drives are stored in rbd but existing instances have + # config drives in the old location under the instances path. + # Test that the driver falls back to 'flat' for config drive if it + # doesn't exist in rbd. + self.flags(images_type='rbd', group='libvirt') + drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) + drvr.image_backend = mock.Mock() + mock_rbd_image = mock.Mock() + mock_flat_image = mock.Mock() + mock_flat_image.libvirt_info.return_value = mock.sentinel.diskconfig + drvr.image_backend.image.side_effect = [mock_rbd_image, + mock_flat_image] + mock_rbd_image.exists.return_value = False + instance = objects.Instance() + disk_mapping = {'disk.config': {'bus': 'ide', + 'dev': 'hdd', + 'type': 'file'}} + flavor = objects.Flavor(extra_specs={}) + + diskconfig = drvr._get_guest_disk_config( + instance, 'disk.config', disk_mapping, flavor, + drvr._get_disk_config_image_type()) + + self.assertEqual(2, drvr.image_backend.image.call_count) + call1 = mock.call(instance, 'disk.config', 'rbd') + call2 = mock.call(instance, 'disk.config', 'flat') + drvr.image_backend.image.assert_has_calls([call1, call2]) + self.assertEqual(mock.sentinel.diskconfig, diskconfig) + def _test_prepare_domain_for_snapshot(self, live_snapshot, state): drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False) instance_ref = objects.Instance(**self.test_instance) diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index fae159b325bf..e82206c4b0ba 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -3327,6 +3327,15 @@ class LibvirtDriver(driver.ComputeDriver): image = self.image_backend.image(instance, name, image_type) + if (name == 'disk.config' and image_type == 'rbd' and + not image.exists()): + # This is likely an older config drive that has not been migrated + # to rbd yet. Try to fall back on 'flat' image type. + # TODO(melwitt): Add online migration of some sort so we can + # remove this fall back once we know all config drives are in rbd. + image = self.image_backend.image(instance, name, 'flat') + LOG.debug('Config drive not found in RBD, falling back to the ' + 'instance directory', instance=instance) disk_info = disk_mapping[name] return image.libvirt_info(disk_info['bus'], disk_info['dev'],