Use uuid instead of name for lvm backend
Because libvirt lvm volumes are based on instance['name'], it means that the actual names used in lvm storage are based on an operator configuration variable: instance_name_template (default is 'instance-%08x'). However this is site changeable, and changeable at any time. This creates 2 failure modes. 1. Operator changes this, the result is all volumes created before the change are no longer able to be cleaned up by nova 2. Operator has changed this to something that includes end user input, like %(display_name), which would allow one user to impact another (user A has display name "bob", user B has display name "bob_joe") This changes the lvm backend to use instance['uuid'] as it's identifier which we know is unique, non overlapping, and not changeable based on whims of site policy. It also provides limited backwards compatibility for cleaning up old disks if the installation was using the default template (which is safe), otherwise it logs a warning about possibly leaking a disk which will need to be manually cleaned up. That should be removed once we open the Juno tree. UpgradeImpact - while there is no operator action required to upgrade over this change, if the nova install included a non default value for instance_name_template then old lvm volumes will need to be cleaned up manually after old guests are destroyed. Change-Id: Ib36b962971fd1f66ea9a0818e91fec59e118e686 Closes-Bug: #1285735
This commit is contained in:
parent
126e1c5ae1
commit
d9a5a80bc0
|
@ -362,7 +362,7 @@ class LvmTestCase(_ImageTestCase, test.NoDBTestCase):
|
|||
self.image_class = imagebackend.Lvm
|
||||
super(LvmTestCase, self).setUp()
|
||||
self.flags(images_volume_group=self.VG, group='libvirt')
|
||||
self.LV = '%s_%s' % (self.INSTANCE['name'], self.NAME)
|
||||
self.LV = '%s_%s' % (self.INSTANCE['uuid'], self.NAME)
|
||||
self.OLD_STYLE_INSTANCE_PATH = None
|
||||
self.PATH = os.path.join('/dev', self.VG, self.LV)
|
||||
|
||||
|
|
|
@ -8093,6 +8093,21 @@ class LibvirtDriverTestCase(test.TestCase):
|
|||
self.libvirtconnection.get_instance_disk_info,
|
||||
instance_name)
|
||||
|
||||
@mock.patch('os.path.exists')
|
||||
@mock.patch('nova.virt.libvirt.utils.list_logical_volumes')
|
||||
def test_lvm_disks(self, listlvs, exists):
|
||||
instance = instance_obj.Instance(uuid='fake-uuid',
|
||||
id=1)
|
||||
self.flags(images_volume_group='vols', group='libvirt')
|
||||
exists.return_value = True
|
||||
listlvs.return_value = ['fake-uuid_foo',
|
||||
'instance-00000001_bar',
|
||||
'other-uuid_foo',
|
||||
'instance-00000002_bar']
|
||||
disks = self.libvirtconnection._lvm_disks(instance)
|
||||
self.assertEqual(['/dev/vols/fake-uuid_foo',
|
||||
'/dev/vols/instance-00000001_bar'], disks)
|
||||
|
||||
|
||||
class LibvirtVolumeUsageTestCase(test.TestCase):
|
||||
"""Test for LibvirtDriver.get_all_volume_usage."""
|
||||
|
|
|
@ -1077,7 +1077,22 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
vg = os.path.join('/dev', CONF.libvirt.images_volume_group)
|
||||
if not os.path.exists(vg):
|
||||
return []
|
||||
pattern = '%s_' % instance['name']
|
||||
pattern = '%s_' % instance['uuid']
|
||||
|
||||
# TODO(sdague): remove in Juno
|
||||
def belongs_to_instance_legacy(disk):
|
||||
# We don't want to leak old disks, but at the same time, we
|
||||
# don't want to do an unsafe thing. So we will only handle
|
||||
# the old filter if it's the system default still.
|
||||
pattern = '%s_' % instance['name']
|
||||
if disk.startswith(pattern):
|
||||
if CONF.instance_name_template == 'instance-%08x':
|
||||
return True
|
||||
else:
|
||||
LOG.warning(_('Volume %(disk)s possibly unsafe to '
|
||||
'remove, please clean up manually'),
|
||||
{'disk': disk})
|
||||
return False
|
||||
|
||||
def belongs_to_instance(disk):
|
||||
return disk.startswith(pattern)
|
||||
|
@ -1088,6 +1103,10 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
logical_volumes = libvirt_utils.list_logical_volumes(vg)
|
||||
|
||||
disk_names = filter(belongs_to_instance, logical_volumes)
|
||||
# TODO(sdague): remove in Juno
|
||||
disk_names.extend(
|
||||
filter(belongs_to_instance_legacy, logical_volumes)
|
||||
)
|
||||
disks = map(fullpath, disk_names)
|
||||
return disks
|
||||
return []
|
||||
|
|
|
@ -361,7 +361,7 @@ class Lvm(Image):
|
|||
' images_volume_group'
|
||||
' flag to use LVM images.'))
|
||||
self.vg = CONF.libvirt.images_volume_group
|
||||
self.lv = '%s_%s' % (self.escape(instance['name']),
|
||||
self.lv = '%s_%s' % (instance['uuid'],
|
||||
self.escape(disk_name))
|
||||
self.path = os.path.join('/dev', self.vg, self.lv)
|
||||
|
||||
|
|
Loading…
Reference in New Issue