Specify image when do rebuilding

Implements: bp specify-image-during-rebuilding
APIImpact

Change-Id: I83104f4209eb4f67699ea9a721509f704d232af9
This commit is contained in:
Xinran 2017-08-03 10:57:40 +08:00
parent dd5f08210b
commit 108348ad41
9 changed files with 50 additions and 14 deletions

View File

@ -309,6 +309,12 @@ flavors:
in: body
required: true
type: array
image_ident:
description: |
The UUID of the image to apply to rebuild your server.
in: body
required: false
type: string
imageRef:
description: |
The UUID of the image to use for your server.

View File

@ -1,3 +1,4 @@
{
"target": "rebuild"
"target": "rebuild",
"image_uuid":"9145be5b-38d0-4a05-8dd6-837a8ec15281"
}

View File

@ -129,6 +129,7 @@ Request
- server_uuid: server_ident
- target: provision_state
- image_uuid: image_ident
**Example request to rebuild a Server:**

View File

@ -158,9 +158,9 @@ class ServerStatesController(ServerControllerBase):
pecan.request.engine_api.unlock(context, db_server)
@policy.authorize_wsgi("mogan:server", "set_provision_state")
@expose.expose(None, types.uuid, wtypes.text,
@expose.expose(None, types.uuid, wtypes.text, types.uuid,
status_code=http_client.ACCEPTED)
def provision(self, server_uuid, target):
def provision(self, server_uuid, target, image_uuid=None):
"""Asynchronous trigger the provisioning of the server.
This will set the target provision state of the server, and
@ -179,10 +179,10 @@ class ServerStatesController(ServerControllerBase):
raise exception.InvalidActionParameterValue(
value=target, action="provision",
server=server_uuid)
db_server = self._resource or self._get_resource(server_uuid)
if target == states.REBUILD:
pecan.request.engine_api.rebuild(pecan.request.context, db_server)
pecan.request.engine_api.rebuild(pecan.request.context, db_server,
image_uuid)
# Set the HTTP Location Header
url_args = '/'.join([server_uuid, 'states'])
@ -675,7 +675,6 @@ class ServerController(ServerControllerBase):
:param server: a server within the request body.
"""
validation.check_schema(server, server_schemas.create_server)
min_count = server.get('min_count', 1)
max_count = server.get('max_count', min_count)

View File

@ -100,7 +100,7 @@ class BaseEngineDriver(object):
"""
raise NotImplementedError()
def rebuild(self, context, server):
def rebuild(self, context, server, image_uuid):
"""Trigger node deploy process.
:param server: server to rebuild.

View File

@ -100,7 +100,6 @@ class IronicDriver(base_driver.BaseEngineDriver):
raise exception.ServerNotFound(server=server.uuid)
def _add_server_info_to_node(self, node, server):
patch = list()
# Associate the node with a server
patch.append({'path': '/instance_uuid', 'op': 'add',
@ -437,10 +436,14 @@ class IronicDriver(base_driver.BaseEngineDriver):
"""
LOG.debug('Rebuild called for server', server=server)
node_uuid = server.node_uuid
node = self._get_node(node_uuid)
self._add_server_info_to_node(node, server)
# trigger the node rebuild
try:
self.ironicclient.call("node.set_provision_state",
server.node_uuid,
node_uuid,
ironic_states.REBUILD)
except (ironic_exc.InternalServerError,
ironic_exc.BadRequest) as e:

View File

@ -386,8 +386,17 @@ class API(object):
@check_server_lock
@check_server_maintenance
def rebuild(self, context, server):
def rebuild(self, context, server, image_uuid=None):
"""Rebuild a server."""
if not image_uuid:
image_uuid = server.image_uuid
# check if the image exists
self._get_image(context, image_uuid)
if image_uuid != server.image_uuid:
# replace original image with the new one
server.image_uuid = image_uuid
server.save()
fsm = utils.get_state_machine(start_state=server.status)
try:
utils.process_event(fsm, server, event='rebuild')

View File

@ -503,7 +503,6 @@ class EngineManager(base_manager.BaseEngineManager):
:param context: mogan request context
:param server: server object
"""
LOG.debug('Rebuilding server', server=server)
fsm = utils.get_state_machine(start_state=server.status)
@ -517,7 +516,6 @@ class EngineManager(base_manager.BaseEngineManager):
"Exception: %(exception)s",
{"uuid": server.uuid,
"exception": e})
utils.process_event(fsm, server, event='done')
LOG.info('Server was successfully rebuilt', server=server)

View File

@ -340,21 +340,40 @@ class ComputeAPIUnitTest(base.DbTestCase):
mock_rebuild.assert_not_called()
@mock.patch.object(engine_rpcapi.EngineAPI, 'rebuild_server')
def test_rebuild_locked_server_with_admin(self, mock_rebuild):
@mock.patch('mogan.engine.api.API._get_image')
def test_rebuild_locked_server_with_admin(self, mock_rebuild,
mock_get_image):
fake_server = db_utils.get_test_server(
user_id=self.user_id, project_id=self.project_id,
locked=True, locked_by='owner')
fake_server_obj = self._create_fake_server_obj(fake_server)
admin_context = context.get_admin_context()
mock_get_image.side_effect = None
self.engine_api.rebuild(admin_context, fake_server_obj)
self.assertTrue(mock_rebuild.called)
@mock.patch.object(engine_rpcapi.EngineAPI, 'rebuild_server')
def test_rebuild_server(self, mock_rebuild):
@mock.patch('mogan.engine.api.API._get_image')
def test_rebuild_server(self, mock_rebuild, mock_get_image):
fake_server = db_utils.get_test_server(
user_id=self.user_id, project_id=self.project_id)
fake_server_obj = self._create_fake_server_obj(fake_server)
mock_get_image.side_effect = None
self.engine_api.rebuild(self.context, fake_server_obj)
self.assertTrue(mock_get_image.called)
self.assertTrue(mock_rebuild.called)
@mock.patch.object(engine_rpcapi.EngineAPI, 'rebuild_server')
@mock.patch('mogan.engine.api.API._get_image')
def test_rebuild_server_with_new_image(self, mock_rebuild, mock_get_image):
fake_server = db_utils.get_test_server(
user_id=self.user_id, project_id=self.project_id)
fake_server_obj = self._create_fake_server_obj(fake_server)
mock_get_image.side_effect = None
image_uuid = 'fake-uuid'
self.engine_api.rebuild(self.context, fake_server_obj, image_uuid)
self.assertTrue(mock_get_image.called)
self.assertTrue(mock_rebuild.called)
@mock.patch.object(engine_rpcapi.EngineAPI, 'detach_interface')