Aliases for a few unfortunately named state transitions
This RFE proposes a new microversion that will provide aliases to two poorly named provisioning verbs to match the existing CLI commands Story: #2007551 Task: #39402 Change-Id: Ifd14aebbfb4b17c5108f44092dac0b89d1c2c50a
This commit is contained in:
parent
bc028e0b65
commit
5c303a5e0a
@ -2,6 +2,11 @@
|
|||||||
REST API Version History
|
REST API Version History
|
||||||
========================
|
========================
|
||||||
|
|
||||||
|
1.73 (Xena)
|
||||||
|
----------------------
|
||||||
|
Add a new ``deploy`` verb as an alias to ``active`` and
|
||||||
|
``undeploy`` verb as an alias to ``deleted``.
|
||||||
|
|
||||||
1.72 (Wallaby, 17.0)
|
1.72 (Wallaby, 17.0)
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
@ -825,7 +825,7 @@ class NodeStatesController(rest.RestController):
|
|||||||
# Note that there is a race condition. The node state(s) could change
|
# Note that there is a race condition. The node state(s) could change
|
||||||
# by the time the RPC call is made and the TaskManager manager gets a
|
# by the time the RPC call is made and the TaskManager manager gets a
|
||||||
# lock.
|
# lock.
|
||||||
if target in (ir_states.ACTIVE, ir_states.REBUILD):
|
if target in (ir_states.ACTIVE, ir_states.REBUILD, ir_states.DEPLOY):
|
||||||
rebuild = (target == ir_states.REBUILD)
|
rebuild = (target == ir_states.REBUILD)
|
||||||
if deploy_steps:
|
if deploy_steps:
|
||||||
_check_deploy_steps(deploy_steps)
|
_check_deploy_steps(deploy_steps)
|
||||||
@ -847,7 +847,7 @@ class NodeStatesController(rest.RestController):
|
|||||||
msg, status_code=http_client.BAD_REQUEST)
|
msg, status_code=http_client.BAD_REQUEST)
|
||||||
api.request.rpcapi.do_node_rescue(
|
api.request.rpcapi.do_node_rescue(
|
||||||
api.request.context, rpc_node.uuid, rescue_password, topic)
|
api.request.context, rpc_node.uuid, rescue_password, topic)
|
||||||
elif target == ir_states.DELETED:
|
elif target in (ir_states.DELETED, ir_states.UNDEPLOY):
|
||||||
api.request.rpcapi.do_node_tear_down(
|
api.request.rpcapi.do_node_tear_down(
|
||||||
api.request.context, rpc_node.uuid, topic)
|
api.request.context, rpc_node.uuid, topic)
|
||||||
elif target == ir_states.VERBS['inspect']:
|
elif target == ir_states.VERBS['inspect']:
|
||||||
|
@ -67,6 +67,8 @@ MIN_VERB_VERSIONS = {
|
|||||||
states.VERBS['adopt']: versions.MINOR_17_ADOPT_VERB,
|
states.VERBS['adopt']: versions.MINOR_17_ADOPT_VERB,
|
||||||
states.VERBS['rescue']: versions.MINOR_38_RESCUE_INTERFACE,
|
states.VERBS['rescue']: versions.MINOR_38_RESCUE_INTERFACE,
|
||||||
states.VERBS['unrescue']: versions.MINOR_38_RESCUE_INTERFACE,
|
states.VERBS['unrescue']: versions.MINOR_38_RESCUE_INTERFACE,
|
||||||
|
states.VERBS['deploy']: versions.MINOR_73_DEPLOY_UNDEPLOY_VERBS,
|
||||||
|
states.VERBS['undeploy']: versions.MINOR_73_DEPLOY_UNDEPLOY_VERBS,
|
||||||
}
|
}
|
||||||
|
|
||||||
V31_FIELDS = [
|
V31_FIELDS = [
|
||||||
|
@ -110,6 +110,7 @@ BASE_VERSION = 1
|
|||||||
# v1.70: Add disable_ramdisk to manual cleaning.
|
# v1.70: Add disable_ramdisk to manual cleaning.
|
||||||
# v1.71: Add signifier for Scope based roles.
|
# v1.71: Add signifier for Scope based roles.
|
||||||
# v1.72: Add agent_status and agent_status_message to /v1/heartbeat
|
# v1.72: Add agent_status and agent_status_message to /v1/heartbeat
|
||||||
|
# v1.73: Add support for deploy and undeploy verbs
|
||||||
|
|
||||||
MINOR_0_JUNO = 0
|
MINOR_0_JUNO = 0
|
||||||
MINOR_1_INITIAL_VERSION = 1
|
MINOR_1_INITIAL_VERSION = 1
|
||||||
@ -184,6 +185,7 @@ MINOR_69_DEPLOY_STEPS = 69
|
|||||||
MINOR_70_CLEAN_DISABLE_RAMDISK = 70
|
MINOR_70_CLEAN_DISABLE_RAMDISK = 70
|
||||||
MINOR_71_RBAC_SCOPES = 71
|
MINOR_71_RBAC_SCOPES = 71
|
||||||
MINOR_72_HEARTBEAT_STATUS = 72
|
MINOR_72_HEARTBEAT_STATUS = 72
|
||||||
|
MINOR_73_DEPLOY_UNDEPLOY_VERBS = 73
|
||||||
|
|
||||||
# When adding another version, update:
|
# When adding another version, update:
|
||||||
# - MINOR_MAX_VERSION
|
# - MINOR_MAX_VERSION
|
||||||
@ -191,7 +193,7 @@ MINOR_72_HEARTBEAT_STATUS = 72
|
|||||||
# explanation of what changed in the new version
|
# explanation of what changed in the new version
|
||||||
# - common/release_mappings.py, RELEASE_MAPPING['master']['api']
|
# - common/release_mappings.py, RELEASE_MAPPING['master']['api']
|
||||||
|
|
||||||
MINOR_MAX_VERSION = MINOR_72_HEARTBEAT_STATUS
|
MINOR_MAX_VERSION = MINOR_73_DEPLOY_UNDEPLOY_VERBS
|
||||||
|
|
||||||
# String representations of the minor and maximum versions
|
# String representations of the minor and maximum versions
|
||||||
_MIN_VERSION_STRING = '{}.{}'.format(BASE_VERSION, MINOR_1_INITIAL_VERSION)
|
_MIN_VERSION_STRING = '{}.{}'.format(BASE_VERSION, MINOR_1_INITIAL_VERSION)
|
||||||
|
@ -320,7 +320,7 @@ RELEASE_MAPPING = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
'master': {
|
'master': {
|
||||||
'api': '1.72',
|
'api': '1.73',
|
||||||
'rpc': '1.54',
|
'rpc': '1.54',
|
||||||
'objects': {
|
'objects': {
|
||||||
'Allocation': ['1.1'],
|
'Allocation': ['1.1'],
|
||||||
|
@ -41,7 +41,9 @@ LOG = logging.getLogger(__name__)
|
|||||||
# TODO(tenbrae): add add'l state mappings here
|
# TODO(tenbrae): add add'l state mappings here
|
||||||
VERBS = {
|
VERBS = {
|
||||||
'active': 'deploy',
|
'active': 'deploy',
|
||||||
|
'deploy': 'deploy',
|
||||||
'deleted': 'delete',
|
'deleted': 'delete',
|
||||||
|
'undeploy': 'delete',
|
||||||
'manage': 'manage',
|
'manage': 'manage',
|
||||||
'provide': 'provide',
|
'provide': 'provide',
|
||||||
'inspect': 'inspect',
|
'inspect': 'inspect',
|
||||||
@ -96,6 +98,11 @@ This state is replacing the NOSTATE state used prior to Kilo.
|
|||||||
ACTIVE = 'active'
|
ACTIVE = 'active'
|
||||||
""" Node is successfully deployed and associated with an instance. """
|
""" Node is successfully deployed and associated with an instance. """
|
||||||
|
|
||||||
|
DEPLOY = 'deploy'
|
||||||
|
""" Node is successfully deployed and associated with an instance.
|
||||||
|
This is an alias for ACTIVE.
|
||||||
|
"""
|
||||||
|
|
||||||
DEPLOYWAIT = 'wait call-back'
|
DEPLOYWAIT = 'wait call-back'
|
||||||
""" Node is waiting to be deployed.
|
""" Node is waiting to be deployed.
|
||||||
|
|
||||||
@ -137,6 +144,11 @@ represented in target_provision_state.
|
|||||||
CLEANING = 'cleaning'
|
CLEANING = 'cleaning'
|
||||||
""" Node is being automatically cleaned to prepare it for provisioning. """
|
""" Node is being automatically cleaned to prepare it for provisioning. """
|
||||||
|
|
||||||
|
UNDEPLOY = 'undeploy'
|
||||||
|
""" Node tear down process has started.
|
||||||
|
This is an alias for DELETED.
|
||||||
|
"""
|
||||||
|
|
||||||
CLEANWAIT = 'clean wait'
|
CLEANWAIT = 'clean wait'
|
||||||
""" Node is waiting for a clean step to be finished.
|
""" Node is waiting for a clean step to be finished.
|
||||||
|
|
||||||
|
@ -5093,6 +5093,25 @@ class TestPut(test_api_base.BaseApiTest):
|
|||||||
self.assertEqual(urlparse.urlparse(ret.location).path,
|
self.assertEqual(urlparse.urlparse(ret.location).path,
|
||||||
expected_location)
|
expected_location)
|
||||||
|
|
||||||
|
def test_provision_deploy(self):
|
||||||
|
ret = self.put_json('/nodes/%s/states/provision' % self.node.uuid,
|
||||||
|
{'target': states.DEPLOY},
|
||||||
|
headers={api_base.Version.string: "1.73"})
|
||||||
|
self.assertEqual(http_client.ACCEPTED, ret.status_code)
|
||||||
|
self.assertEqual(b'', ret.body)
|
||||||
|
self.mock_dnd.assert_called_once_with(mock.ANY,
|
||||||
|
context=mock.ANY,
|
||||||
|
node_id=self.node.uuid,
|
||||||
|
rebuild=False,
|
||||||
|
configdrive=None,
|
||||||
|
topic='test-topic',
|
||||||
|
deploy_steps=None)
|
||||||
|
# Check location header
|
||||||
|
self.assertIsNotNone(ret.location)
|
||||||
|
expected_location = '/v1/nodes/%s/states' % self.node.uuid
|
||||||
|
self.assertEqual(urlparse.urlparse(ret.location).path,
|
||||||
|
expected_location)
|
||||||
|
|
||||||
def test_provision_by_name_unsupported(self):
|
def test_provision_by_name_unsupported(self):
|
||||||
ret = self.put_json('/nodes/%s/states/provision' % self.node.name,
|
ret = self.put_json('/nodes/%s/states/provision' % self.node.name,
|
||||||
{'target': states.ACTIVE},
|
{'target': states.ACTIVE},
|
||||||
@ -5354,6 +5373,23 @@ ORHMKeXMO8fcK0By7CiMKwHSXCoEQgfQhWwpMdSsO8LgHCjh87DQc= """
|
|||||||
self.assertEqual(urlparse.urlparse(ret.location).path,
|
self.assertEqual(urlparse.urlparse(ret.location).path,
|
||||||
expected_location)
|
expected_location)
|
||||||
|
|
||||||
|
def test_provision_with_tear_down_undeploy(self):
|
||||||
|
node = self.node
|
||||||
|
node.provision_state = states.ACTIVE
|
||||||
|
node.target_provision_state = states.NOSTATE
|
||||||
|
node.save()
|
||||||
|
ret = self.put_json('/nodes/%s/states/provision' % node.uuid,
|
||||||
|
{'target': states.UNDEPLOY})
|
||||||
|
self.assertEqual(http_client.ACCEPTED, ret.status_code)
|
||||||
|
self.assertEqual(b'', ret.body)
|
||||||
|
self.mock_dntd.assert_called_once_with(
|
||||||
|
mock.ANY, mock.ANY, node.uuid, 'test-topic')
|
||||||
|
# Check location header
|
||||||
|
self.assertIsNotNone(ret.location)
|
||||||
|
expected_location = '/v1/nodes/%s/states' % node.uuid
|
||||||
|
self.assertEqual(urlparse.urlparse(ret.location).path,
|
||||||
|
expected_location)
|
||||||
|
|
||||||
def test_provision_already_in_progress(self):
|
def test_provision_already_in_progress(self):
|
||||||
node = self.node
|
node = self.node
|
||||||
node.provision_state = states.DEPLOYING
|
node.provision_state = states.DEPLOYING
|
||||||
|
@ -556,6 +556,24 @@ class TestCheckAllowFields(base.TestCase):
|
|||||||
self.assertRaises(exception.NotAcceptable,
|
self.assertRaises(exception.NotAcceptable,
|
||||||
utils.check_allow_management_verbs, 'clean')
|
utils.check_allow_management_verbs, 'clean')
|
||||||
|
|
||||||
|
def test_check_allow_deploy_verbs(self, mock_request):
|
||||||
|
mock_request.version.minor = 73
|
||||||
|
utils.check_allow_management_verbs('deploy')
|
||||||
|
|
||||||
|
def test_check_allow_deploy_verbs_fail(self, mock_request):
|
||||||
|
mock_request.version.minor = 72
|
||||||
|
self.assertRaises(exception.NotAcceptable,
|
||||||
|
utils.check_allow_management_verbs, 'deploy')
|
||||||
|
|
||||||
|
def test_check_allow_undeploy_verbs(self, mock_request):
|
||||||
|
mock_request.version.minor = 73
|
||||||
|
utils.check_allow_management_verbs('undeploy')
|
||||||
|
|
||||||
|
def test_check_allow_undeploy_verbs_fail(self, mock_request):
|
||||||
|
mock_request.version.minor = 72
|
||||||
|
self.assertFalse(
|
||||||
|
utils.check_allow_management_verbs('undeploy'))
|
||||||
|
|
||||||
def test_check_allow_unknown_verbs(self, mock_request):
|
def test_check_allow_unknown_verbs(self, mock_request):
|
||||||
utils.check_allow_management_verbs('rebuild')
|
utils.check_allow_management_verbs('rebuild')
|
||||||
|
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Adds a new ``deploy`` verb as an alias to ``active`` and
|
||||||
|
``undeploy`` verb as an alias to ``deleted``
|
||||||
|
See `story 2007551 <https://storyboard.openstack.org/#!/story/2007551>`_.
|
Loading…
Reference in New Issue
Block a user