Specify image when do rebuilding
Implements: bp specify-image-during-rebuilding APIImpact Change-Id: I83104f4209eb4f67699ea9a721509f704d232af9
This commit is contained in:
parent
dd5f08210b
commit
108348ad41
|
@ -309,6 +309,12 @@ flavors:
|
||||||
in: body
|
in: body
|
||||||
required: true
|
required: true
|
||||||
type: array
|
type: array
|
||||||
|
image_ident:
|
||||||
|
description: |
|
||||||
|
The UUID of the image to apply to rebuild your server.
|
||||||
|
in: body
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
imageRef:
|
imageRef:
|
||||||
description: |
|
description: |
|
||||||
The UUID of the image to use for your server.
|
The UUID of the image to use for your server.
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
{
|
{
|
||||||
"target": "rebuild"
|
"target": "rebuild",
|
||||||
|
"image_uuid":"9145be5b-38d0-4a05-8dd6-837a8ec15281"
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,6 +129,7 @@ Request
|
||||||
|
|
||||||
- server_uuid: server_ident
|
- server_uuid: server_ident
|
||||||
- target: provision_state
|
- target: provision_state
|
||||||
|
- image_uuid: image_ident
|
||||||
|
|
||||||
**Example request to rebuild a Server:**
|
**Example request to rebuild a Server:**
|
||||||
|
|
||||||
|
|
|
@ -158,9 +158,9 @@ class ServerStatesController(ServerControllerBase):
|
||||||
pecan.request.engine_api.unlock(context, db_server)
|
pecan.request.engine_api.unlock(context, db_server)
|
||||||
|
|
||||||
@policy.authorize_wsgi("mogan:server", "set_provision_state")
|
@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)
|
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.
|
"""Asynchronous trigger the provisioning of the server.
|
||||||
|
|
||||||
This will set the target provision state of the server, and
|
This will set the target provision state of the server, and
|
||||||
|
@ -179,10 +179,10 @@ class ServerStatesController(ServerControllerBase):
|
||||||
raise exception.InvalidActionParameterValue(
|
raise exception.InvalidActionParameterValue(
|
||||||
value=target, action="provision",
|
value=target, action="provision",
|
||||||
server=server_uuid)
|
server=server_uuid)
|
||||||
|
|
||||||
db_server = self._resource or self._get_resource(server_uuid)
|
db_server = self._resource or self._get_resource(server_uuid)
|
||||||
if target == states.REBUILD:
|
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
|
# Set the HTTP Location Header
|
||||||
url_args = '/'.join([server_uuid, 'states'])
|
url_args = '/'.join([server_uuid, 'states'])
|
||||||
|
@ -675,7 +675,6 @@ class ServerController(ServerControllerBase):
|
||||||
:param server: a server within the request body.
|
:param server: a server within the request body.
|
||||||
"""
|
"""
|
||||||
validation.check_schema(server, server_schemas.create_server)
|
validation.check_schema(server, server_schemas.create_server)
|
||||||
|
|
||||||
min_count = server.get('min_count', 1)
|
min_count = server.get('min_count', 1)
|
||||||
max_count = server.get('max_count', min_count)
|
max_count = server.get('max_count', min_count)
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ class BaseEngineDriver(object):
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def rebuild(self, context, server):
|
def rebuild(self, context, server, image_uuid):
|
||||||
"""Trigger node deploy process.
|
"""Trigger node deploy process.
|
||||||
|
|
||||||
:param server: server to rebuild.
|
:param server: server to rebuild.
|
||||||
|
|
|
@ -100,7 +100,6 @@ class IronicDriver(base_driver.BaseEngineDriver):
|
||||||
raise exception.ServerNotFound(server=server.uuid)
|
raise exception.ServerNotFound(server=server.uuid)
|
||||||
|
|
||||||
def _add_server_info_to_node(self, node, server):
|
def _add_server_info_to_node(self, node, server):
|
||||||
|
|
||||||
patch = list()
|
patch = list()
|
||||||
# Associate the node with a server
|
# Associate the node with a server
|
||||||
patch.append({'path': '/instance_uuid', 'op': 'add',
|
patch.append({'path': '/instance_uuid', 'op': 'add',
|
||||||
|
@ -437,10 +436,14 @@ class IronicDriver(base_driver.BaseEngineDriver):
|
||||||
"""
|
"""
|
||||||
LOG.debug('Rebuild called for server', server=server)
|
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
|
# trigger the node rebuild
|
||||||
try:
|
try:
|
||||||
self.ironicclient.call("node.set_provision_state",
|
self.ironicclient.call("node.set_provision_state",
|
||||||
server.node_uuid,
|
node_uuid,
|
||||||
ironic_states.REBUILD)
|
ironic_states.REBUILD)
|
||||||
except (ironic_exc.InternalServerError,
|
except (ironic_exc.InternalServerError,
|
||||||
ironic_exc.BadRequest) as e:
|
ironic_exc.BadRequest) as e:
|
||||||
|
|
|
@ -386,8 +386,17 @@ class API(object):
|
||||||
|
|
||||||
@check_server_lock
|
@check_server_lock
|
||||||
@check_server_maintenance
|
@check_server_maintenance
|
||||||
def rebuild(self, context, server):
|
def rebuild(self, context, server, image_uuid=None):
|
||||||
"""Rebuild a server."""
|
"""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)
|
fsm = utils.get_state_machine(start_state=server.status)
|
||||||
try:
|
try:
|
||||||
utils.process_event(fsm, server, event='rebuild')
|
utils.process_event(fsm, server, event='rebuild')
|
||||||
|
|
|
@ -503,7 +503,6 @@ class EngineManager(base_manager.BaseEngineManager):
|
||||||
:param context: mogan request context
|
:param context: mogan request context
|
||||||
:param server: server object
|
:param server: server object
|
||||||
"""
|
"""
|
||||||
|
|
||||||
LOG.debug('Rebuilding server', server=server)
|
LOG.debug('Rebuilding server', server=server)
|
||||||
|
|
||||||
fsm = utils.get_state_machine(start_state=server.status)
|
fsm = utils.get_state_machine(start_state=server.status)
|
||||||
|
@ -517,7 +516,6 @@ class EngineManager(base_manager.BaseEngineManager):
|
||||||
"Exception: %(exception)s",
|
"Exception: %(exception)s",
|
||||||
{"uuid": server.uuid,
|
{"uuid": server.uuid,
|
||||||
"exception": e})
|
"exception": e})
|
||||||
|
|
||||||
utils.process_event(fsm, server, event='done')
|
utils.process_event(fsm, server, event='done')
|
||||||
LOG.info('Server was successfully rebuilt', server=server)
|
LOG.info('Server was successfully rebuilt', server=server)
|
||||||
|
|
||||||
|
|
|
@ -340,21 +340,40 @@ class ComputeAPIUnitTest(base.DbTestCase):
|
||||||
mock_rebuild.assert_not_called()
|
mock_rebuild.assert_not_called()
|
||||||
|
|
||||||
@mock.patch.object(engine_rpcapi.EngineAPI, 'rebuild_server')
|
@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(
|
fake_server = db_utils.get_test_server(
|
||||||
user_id=self.user_id, project_id=self.project_id,
|
user_id=self.user_id, project_id=self.project_id,
|
||||||
locked=True, locked_by='owner')
|
locked=True, locked_by='owner')
|
||||||
fake_server_obj = self._create_fake_server_obj(fake_server)
|
fake_server_obj = self._create_fake_server_obj(fake_server)
|
||||||
admin_context = context.get_admin_context()
|
admin_context = context.get_admin_context()
|
||||||
|
mock_get_image.side_effect = None
|
||||||
self.engine_api.rebuild(admin_context, fake_server_obj)
|
self.engine_api.rebuild(admin_context, fake_server_obj)
|
||||||
self.assertTrue(mock_rebuild.called)
|
self.assertTrue(mock_rebuild.called)
|
||||||
|
|
||||||
@mock.patch.object(engine_rpcapi.EngineAPI, 'rebuild_server')
|
@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(
|
fake_server = db_utils.get_test_server(
|
||||||
user_id=self.user_id, project_id=self.project_id)
|
user_id=self.user_id, project_id=self.project_id)
|
||||||
fake_server_obj = self._create_fake_server_obj(fake_server)
|
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.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)
|
self.assertTrue(mock_rebuild.called)
|
||||||
|
|
||||||
@mock.patch.object(engine_rpcapi.EngineAPI, 'detach_interface')
|
@mock.patch.object(engine_rpcapi.EngineAPI, 'detach_interface')
|
||||||
|
|
Loading…
Reference in New Issue