Fix attibute error when cloning raw images in Ceph

A regression introduced in If03b166d3ecc3e7fa6b7f1a0c69f8ab1cc7b1972
causes a glance image with the type 'raw' in ceph to fail to CoW
clone which prevents launching at all in this case.

The original patch did not update imagebackend.py [1] to use the new
nova.objects.ImageMeta object so the clone() function passes a normal
dict to the is_cloneable() function.

Additionally add another test to ensure that not passing disk_format
will fail, but not result in an exception. It will simply mean that
the function returns that it cannot take advantage of the CoW cloning
ceph provides.

[1] f2e2a5891d/nova/virt/libvirt/imagebackend.py (L824)

Change-Id: I7ae107bfccab7ff66c09d96856722dd6e60fdd96
Closes-Bug: #1508230
(cherry picked from commit 835ff1bf73)
This commit is contained in:
Sam Yaple 2015-10-20 22:42:36 +00:00
parent 0871729c21
commit 474e7bb3f3
2 changed files with 16 additions and 7 deletions

View File

@ -96,7 +96,7 @@ class RbdTestCase(test.NoDBTestCase):
'rbd://fsid/pool/image/',
'rbd://fsid/pool/image/snap/',
'rbd://///', ]
image_meta = objects.ImageMeta.from_dict({'disk_format': 'raw'})
image_meta = {'disk_format': 'raw'}
for loc in locations:
self.assertRaises(exception.ImageUnacceptable,
@ -110,7 +110,7 @@ class RbdTestCase(test.NoDBTestCase):
def test_cloneable(self, mock_rados, mock_rbd, mock_get_fsid):
mock_get_fsid.return_value = 'abc'
location = {'url': 'rbd://abc/pool/image/snap'}
image_meta = objects.ImageMeta.from_dict({'disk_format': 'raw'})
image_meta = {'disk_format': 'raw'}
self.assertTrue(self.driver.is_cloneable(location, image_meta))
self.assertTrue(mock_get_fsid.called)
@ -118,7 +118,7 @@ class RbdTestCase(test.NoDBTestCase):
def test_uncloneable_different_fsid(self, mock_get_fsid):
mock_get_fsid.return_value = 'abc'
location = {'url': 'rbd://def/pool/image/snap'}
image_meta = objects.ImageMeta.from_dict({'disk_format': 'raw'})
image_meta = {'disk_format': 'raw'}
self.assertFalse(
self.driver.is_cloneable(location, image_meta))
self.assertTrue(mock_get_fsid.called)
@ -133,7 +133,7 @@ class RbdTestCase(test.NoDBTestCase):
location = {'url': 'rbd://abc/pool/image/snap'}
mock_proxy.side_effect = mock_rbd.Error
image_meta = objects.ImageMeta.from_dict({'disk_format': 'raw'})
image_meta = {'disk_format': 'raw'}
self.assertFalse(
self.driver.is_cloneable(location, image_meta))
@ -147,11 +147,20 @@ class RbdTestCase(test.NoDBTestCase):
location = {'url': 'rbd://abc/pool/image/snap'}
formats = ['qcow2', 'vmdk', 'vdi']
for f in formats:
image_meta = objects.ImageMeta.from_dict({'disk_format': f})
image_meta = {'disk_format': f}
self.assertFalse(
self.driver.is_cloneable(location, image_meta))
self.assertTrue(mock_get_fsid.called)
@mock.patch.object(rbd_utils.RBDDriver, '_get_fsid')
def test_uncloneable_missing_format(self, mock_get_fsid):
mock_get_fsid.return_value = 'abc'
location = {'url': 'rbd://abc/pool/image/snap'}
image_meta = {}
self.assertFalse(
self.driver.is_cloneable(location, image_meta))
self.assertTrue(mock_get_fsid.called)
@mock.patch.object(utils, 'execute')
def test_get_mon_addrs(self, mock_execute):
mock_execute.return_value = (CEPH_MON_DUMP, '')

View File

@ -190,10 +190,10 @@ class RBDDriver(object):
LOG.debug(reason)
return False
if image_meta.disk_format != 'raw':
if image_meta.get('disk_format') != 'raw':
reason = ("rbd image clone requires image format to be "
"'raw' but image {0} is '{1}'").format(
url, image_meta.disk_format)
url, image_meta.get('disk_format'))
LOG.debug(reason)
return False