Fix nova rebuild not support vm use boot volume

Change-Id: Ic7b9b9b96db79e0b6e0c8ec3412d3eef172c5652
Closes-Bug: 1740977
This commit is contained in:
Yuanbin.Chen 2017-12-05 00:44:04 +08:00
parent ca12b67688
commit 33231f869f
2 changed files with 73 additions and 13 deletions

View File

@ -1491,30 +1491,51 @@ class ServerProfile(base.Profile):
return None
server_id = obj.physical_id
driver = self.compute(obj)
nova_driver = self.compute(obj)
try:
server = driver.server_get(server_id)
server = nova_driver.server_get(server_id)
except exc.InternalError as ex:
raise exc.EResourceOperation(op='rebuilding', type='server',
id=server_id,
message=six.text_type(ex))
if server is None or server.image is None:
if server is None:
return None
# when booting a nova server from volume, the image property
# can be ignored.
# we try find a volume which is bootable and use its image_id
# for the server.
if server.image:
image_id = server.image
elif server.attached_volumes:
cinder_driver = self.block_storage(obj)
for volume_ids in server.attached_volumes:
try:
vs = cinder_driver.volume_get(volume_ids['id'])
if vs.is_bootable:
image_id = vs.volume_image_metadata['image_id']
except exc.InternalError as ex:
raise exc.EResourceOperation(op='rebuild', type='server',
id=obj.physical_id,
message=six.text_type(ex))
else:
msg = _("server doesn't have an image and it has no "
"bootable volume")
raise exc.EResourceOperation(op="rebuild", type="server",
id=obj.physical_id,
message=msg)
image_id = server.image['id']
admin_pass = self.properties.get(self.ADMIN_PASS)
name = self.properties[self.NAME] or obj.name
try:
driver.server_rebuild(server_id, image_id,
name, admin_pass)
driver.wait_for_server(server_id, 'ACTIVE')
nova_driver.server_rebuild(server_id, image_id,
name, admin_pass)
nova_driver.wait_for_server(server_id, 'ACTIVE')
return server_id
except exc.InternalError as ex:
raise exc.EResourceOperation(op='rebuilding', type='server',
id=server_id,
message=six.text_type(ex))
return None
def handle_change_password(self, obj, **options):
"""Handler for the change_password operation."""

View File

@ -1237,9 +1237,48 @@ class TestNovaServerBasic(base.SenlinTestCase):
res = profile.handle_reboot(obj, type='foo')
self.assertFalse(res)
def test_handle_rebuild(self):
def test_handle_rebuild_with_image(self):
profile = server.ServerProfile('t', self.spec)
x_image = {'id': '123'}
x_image = '123'
x_server = mock.Mock(image=x_image)
cc = mock.Mock()
cc.server_get.return_value = x_server
cc.server_rebuild.return_value = True
profile._computeclient = cc
node_obj = mock.Mock(physical_id='FAKE_ID')
res = profile.handle_rebuild(node_obj)
self.assertEqual('FAKE_ID', res)
cc.server_get.assert_called_with('FAKE_ID')
cc.server_rebuild.assert_called_once_with('FAKE_ID', '123',
'FAKE_SERVER_NAME',
'adminpass')
cc.wait_for_server.assert_called_once_with('FAKE_ID', 'ACTIVE')
def test_handle_rebuild_with_bdm(self):
bdm_v2 = [
{
'volume_size': 1,
'uuid': '123',
'source_type': 'image',
'destination_type': 'volume',
'boot_index': 0,
}
]
spec = {
'type': 'os.nova.server',
'version': '1.0',
'properties': {
'flavor': 'FLAV',
'admin_pass': 'adminpass',
'name': 'FAKE_SERVER_NAME',
'security_groups': ['HIGH_SECURITY_GROUP'],
'block_device_mapping_v2': bdm_v2,
}
}
profile = server.ServerProfile('t', spec)
x_image = '123'
x_server = mock.Mock(image=x_image)
cc = mock.Mock()
cc.server_get.return_value = x_server
@ -1275,7 +1314,7 @@ class TestNovaServerBasic(base.SenlinTestCase):
def test_handle_rebuild_failed_rebuild(self):
profile = server.ServerProfile('t', self.spec)
x_image = {'id': '123'}
x_image = '123'
x_server = mock.Mock(image=x_image)
cc = mock.Mock()
cc.server_get.return_value = x_server
@ -1299,7 +1338,7 @@ class TestNovaServerBasic(base.SenlinTestCase):
def test_handle_rebuild_failed_waiting(self):
profile = server.ServerProfile('t', self.spec)
x_image = {'id': '123'}
x_image = '123'
x_server = mock.Mock(image=x_image)
cc = mock.Mock()
cc.server_get.return_value = x_server
@ -1348,7 +1387,7 @@ class TestNovaServerBasic(base.SenlinTestCase):
def test_handle_rebuild_failed_with_name(self):
self.spec['properties']['name'] = None
profile = server.ServerProfile('t', self.spec)
x_image = {'id': '123'}
x_image = '123'
x_server = mock.Mock(image=x_image)
cc = mock.Mock()
cc.server_get.return_value = x_server