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 commit835ff1bf73
)
This commit is contained in:
parent
0871729c21
commit
474e7bb3f3
@ -96,7 +96,7 @@ class RbdTestCase(test.NoDBTestCase):
|
|||||||
'rbd://fsid/pool/image/',
|
'rbd://fsid/pool/image/',
|
||||||
'rbd://fsid/pool/image/snap/',
|
'rbd://fsid/pool/image/snap/',
|
||||||
'rbd://///', ]
|
'rbd://///', ]
|
||||||
image_meta = objects.ImageMeta.from_dict({'disk_format': 'raw'})
|
image_meta = {'disk_format': 'raw'}
|
||||||
|
|
||||||
for loc in locations:
|
for loc in locations:
|
||||||
self.assertRaises(exception.ImageUnacceptable,
|
self.assertRaises(exception.ImageUnacceptable,
|
||||||
@ -110,7 +110,7 @@ class RbdTestCase(test.NoDBTestCase):
|
|||||||
def test_cloneable(self, mock_rados, mock_rbd, mock_get_fsid):
|
def test_cloneable(self, mock_rados, mock_rbd, mock_get_fsid):
|
||||||
mock_get_fsid.return_value = 'abc'
|
mock_get_fsid.return_value = 'abc'
|
||||||
location = {'url': 'rbd://abc/pool/image/snap'}
|
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(self.driver.is_cloneable(location, image_meta))
|
||||||
self.assertTrue(mock_get_fsid.called)
|
self.assertTrue(mock_get_fsid.called)
|
||||||
|
|
||||||
@ -118,7 +118,7 @@ class RbdTestCase(test.NoDBTestCase):
|
|||||||
def test_uncloneable_different_fsid(self, mock_get_fsid):
|
def test_uncloneable_different_fsid(self, mock_get_fsid):
|
||||||
mock_get_fsid.return_value = 'abc'
|
mock_get_fsid.return_value = 'abc'
|
||||||
location = {'url': 'rbd://def/pool/image/snap'}
|
location = {'url': 'rbd://def/pool/image/snap'}
|
||||||
image_meta = objects.ImageMeta.from_dict({'disk_format': 'raw'})
|
image_meta = {'disk_format': 'raw'}
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
self.driver.is_cloneable(location, image_meta))
|
self.driver.is_cloneable(location, image_meta))
|
||||||
self.assertTrue(mock_get_fsid.called)
|
self.assertTrue(mock_get_fsid.called)
|
||||||
@ -133,7 +133,7 @@ class RbdTestCase(test.NoDBTestCase):
|
|||||||
location = {'url': 'rbd://abc/pool/image/snap'}
|
location = {'url': 'rbd://abc/pool/image/snap'}
|
||||||
|
|
||||||
mock_proxy.side_effect = mock_rbd.Error
|
mock_proxy.side_effect = mock_rbd.Error
|
||||||
image_meta = objects.ImageMeta.from_dict({'disk_format': 'raw'})
|
image_meta = {'disk_format': 'raw'}
|
||||||
|
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
self.driver.is_cloneable(location, image_meta))
|
self.driver.is_cloneable(location, image_meta))
|
||||||
@ -147,11 +147,20 @@ class RbdTestCase(test.NoDBTestCase):
|
|||||||
location = {'url': 'rbd://abc/pool/image/snap'}
|
location = {'url': 'rbd://abc/pool/image/snap'}
|
||||||
formats = ['qcow2', 'vmdk', 'vdi']
|
formats = ['qcow2', 'vmdk', 'vdi']
|
||||||
for f in formats:
|
for f in formats:
|
||||||
image_meta = objects.ImageMeta.from_dict({'disk_format': f})
|
image_meta = {'disk_format': f}
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
self.driver.is_cloneable(location, image_meta))
|
self.driver.is_cloneable(location, image_meta))
|
||||||
self.assertTrue(mock_get_fsid.called)
|
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')
|
@mock.patch.object(utils, 'execute')
|
||||||
def test_get_mon_addrs(self, mock_execute):
|
def test_get_mon_addrs(self, mock_execute):
|
||||||
mock_execute.return_value = (CEPH_MON_DUMP, '')
|
mock_execute.return_value = (CEPH_MON_DUMP, '')
|
||||||
|
@ -190,10 +190,10 @@ class RBDDriver(object):
|
|||||||
LOG.debug(reason)
|
LOG.debug(reason)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if image_meta.disk_format != 'raw':
|
if image_meta.get('disk_format') != 'raw':
|
||||||
reason = ("rbd image clone requires image format to be "
|
reason = ("rbd image clone requires image format to be "
|
||||||
"'raw' but image {0} is '{1}'").format(
|
"'raw' but image {0} is '{1}'").format(
|
||||||
url, image_meta.disk_format)
|
url, image_meta.get('disk_format'))
|
||||||
LOG.debug(reason)
|
LOG.debug(reason)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user