Deploy steps - API & notifications
Adds a 'deploy_step' field to the nodes API. Co-Authored-By: Ruby Loo <rloo@oath.com> Change-Id: I1baeeaaa6ed521e4189958fd7624cd6c5de96707 Story: #1753128 Task: #22592
This commit is contained in:
parent
65a68e4e96
commit
5a14eed467
@ -86,6 +86,9 @@ supplied when the Node is created, or the resource may be updated later.
|
||||
Introduced the ``rescue_interface`` field. If this field is not supplied
|
||||
when creating the Node, the default value will be used.
|
||||
|
||||
.. versionadded:: 1.44
|
||||
Introduced the ``deploy_step`` field.
|
||||
|
||||
Normal response codes: 201
|
||||
|
||||
Error codes: 400,403,406
|
||||
@ -132,7 +135,7 @@ and any defaults added for non-specified fields. Most fields default to "null"
|
||||
or "".
|
||||
|
||||
The list and example below are representative of the response as of API
|
||||
microversion 1.43.
|
||||
microversion 1.44.
|
||||
|
||||
.. rest_parameters:: parameters.yaml
|
||||
|
||||
@ -159,6 +162,7 @@ microversion 1.43.
|
||||
- raid_config: raid_config
|
||||
- target_raid_config: target_raid_config
|
||||
- clean_step: clean_step
|
||||
- deploy_step: deploy_step
|
||||
- links: links
|
||||
- ports: n_ports
|
||||
- portgroups: n_portgroups
|
||||
@ -333,6 +337,7 @@ Response
|
||||
- raid_config: raid_config
|
||||
- target_raid_config: target_raid_config
|
||||
- clean_step: clean_step
|
||||
- deploy_step: deploy_step
|
||||
- links: links
|
||||
- ports: n_ports
|
||||
- portgroups: n_portgroups
|
||||
@ -416,6 +421,7 @@ Response
|
||||
- raid_config: raid_config
|
||||
- target_raid_config: target_raid_config
|
||||
- clean_step: clean_step
|
||||
- deploy_step: deploy_step
|
||||
- links: links
|
||||
- ports: n_ports
|
||||
- portgroups: n_portgroups
|
||||
@ -500,6 +506,7 @@ Response
|
||||
- raid_config: raid_config
|
||||
- target_raid_config: target_raid_config
|
||||
- clean_step: clean_step
|
||||
- deploy_step: deploy_step
|
||||
- links: links
|
||||
- ports: n_ports
|
||||
- portgroups: n_portgroups
|
||||
|
@ -492,6 +492,12 @@ deploy_interface:
|
||||
in: body
|
||||
required: true
|
||||
type: string
|
||||
deploy_step:
|
||||
description: |
|
||||
The current deploy step.
|
||||
in: body
|
||||
required: false
|
||||
type: string
|
||||
description:
|
||||
description: |
|
||||
Descriptive text about the Ironic service.
|
||||
|
@ -6,6 +6,7 @@
|
||||
"console_interface": null,
|
||||
"created_at": "2016-08-18T22:28:48.643434+11:11",
|
||||
"deploy_interface": null,
|
||||
"deploy_step": {},
|
||||
"driver": "agent_ipmitool",
|
||||
"driver_info": {
|
||||
"ipmi_password": "******",
|
||||
|
@ -6,6 +6,7 @@
|
||||
"console_interface": null,
|
||||
"created_at": "2016-08-18T22:28:48.643434+11:11",
|
||||
"deploy_interface": null,
|
||||
"deploy_step": {},
|
||||
"driver": "fake",
|
||||
"driver_info": {
|
||||
"ipmi_password": "******",
|
||||
|
@ -6,6 +6,7 @@
|
||||
"console_interface": null,
|
||||
"created_at": "2016-08-18T22:28:48.643434+11:11",
|
||||
"deploy_interface": null,
|
||||
"deploy_step": {},
|
||||
"driver": "fake",
|
||||
"driver_info": {
|
||||
"deploy_kernel": "http://127.0.0.1/images/kernel",
|
||||
|
@ -8,6 +8,7 @@
|
||||
"console_interface": null,
|
||||
"created_at": "2016-08-18T22:28:48.643434+11:11",
|
||||
"deploy_interface": null,
|
||||
"deploy_step": {},
|
||||
"driver": "fake",
|
||||
"driver_info": {
|
||||
"ipmi_password": "******",
|
||||
@ -105,6 +106,7 @@
|
||||
"console_interface": "no-console",
|
||||
"created_at": "2016-08-18T22:28:48.643434+11:11",
|
||||
"deploy_interface": "iscsi",
|
||||
"deploy_step": {},
|
||||
"driver": "ipmi",
|
||||
"driver_info": {
|
||||
"ipmi_password": "******",
|
||||
|
@ -132,12 +132,13 @@ Example of node CRUD notification::
|
||||
"payload":{
|
||||
"ironic_object.namespace":"ironic",
|
||||
"ironic_object.name":"NodeCRUDPayload",
|
||||
"ironic_object.version":"1.5",
|
||||
"ironic_object.version":"1.6",
|
||||
"ironic_object.data":{
|
||||
"chassis_uuid": "db0eef9d-45b2-4dc0-94a8-fc283c01171f",
|
||||
"clean_step": None,
|
||||
"console_enabled": False,
|
||||
"created_at": "2016-01-26T20:41:03+00:00",
|
||||
"deploy_step": None,
|
||||
"driver": "ipmi",
|
||||
"driver_info": {
|
||||
"ipmi_address": "192.168.0.111",
|
||||
@ -359,7 +360,7 @@ node maintenance notification::
|
||||
"payload":{
|
||||
"ironic_object.namespace":"ironic",
|
||||
"ironic_object.name":"NodePayload",
|
||||
"ironic_object.version":"1.8",
|
||||
"ironic_object.version":"1.9",
|
||||
"ironic_object.data":{
|
||||
"clean_step": None,
|
||||
"console_enabled": False,
|
||||
@ -440,7 +441,7 @@ level, "error" has ERROR. Example of node console notification::
|
||||
"payload":{
|
||||
"ironic_object.namespace":"ironic",
|
||||
"ironic_object.name":"NodePayload",
|
||||
"ironic_object.version":"1.8",
|
||||
"ironic_object.version":"1.9",
|
||||
"ironic_object.data":{
|
||||
"clean_step": None,
|
||||
"console_enabled": True,
|
||||
@ -515,11 +516,12 @@ ironic-conductor is attempting to change the node::
|
||||
"payload":{
|
||||
"ironic_object.namespace":"ironic",
|
||||
"ironic_object.name":"NodeSetPowerStatePayload",
|
||||
"ironic_object.version":"1.7",
|
||||
"ironic_object.version":"1.9",
|
||||
"ironic_object.data":{
|
||||
"clean_step": None,
|
||||
"console_enabled": False,
|
||||
"created_at": "2016-01-26T20:41:03+00:00",
|
||||
"deploy_step": None,
|
||||
"driver": "ipmi",
|
||||
"extra": {},
|
||||
"inspection_finished_at": None,
|
||||
@ -583,11 +585,12 @@ prior to the correction::
|
||||
"payload":{
|
||||
"ironic_object.namespace":"ironic",
|
||||
"ironic_object.name":"NodeCorrectedPowerStatePayload",
|
||||
"ironic_object.version":"1.7",
|
||||
"ironic_object.version":"1.9",
|
||||
"ironic_object.data":{
|
||||
"clean_step": None,
|
||||
"console_enabled": False,
|
||||
"created_at": "2016-01-26T20:41:03+00:00",
|
||||
"deploy_step": None,
|
||||
"driver": "ipmi",
|
||||
"extra": {},
|
||||
"inspection_finished_at": None,
|
||||
@ -662,11 +665,12 @@ indicate a node's provision states before state change, "event" is the FSM
|
||||
"payload":{
|
||||
"ironic_object.namespace":"ironic",
|
||||
"ironic_object.name":"NodeSetProvisionStatePayload",
|
||||
"ironic_object.version":"1.7",
|
||||
"ironic_object.version":"1.9",
|
||||
"ironic_object.data":{
|
||||
"clean_step": None,
|
||||
"console_enabled": False,
|
||||
"created_at": "2016-01-26T20:41:03+00:00",
|
||||
"deploy_step": None,
|
||||
"driver": "ipmi",
|
||||
"extra": {},
|
||||
"inspection_finished_at": None,
|
||||
|
@ -2,6 +2,12 @@
|
||||
REST API Version History
|
||||
========================
|
||||
|
||||
1.44 (Rocky, master)
|
||||
--------------------
|
||||
|
||||
Added ``deploy_step`` to the node object, to indicate the current deploy
|
||||
step (if any) being performed on the node.
|
||||
|
||||
1.43 (Rocky, 11.0.0)
|
||||
--------------------
|
||||
|
||||
|
@ -150,6 +150,9 @@ def hide_fields_in_newer_versions(obj):
|
||||
if pecan.request.version.minor < versions.MINOR_42_FAULT:
|
||||
obj.fault = wsme.Unset
|
||||
|
||||
if pecan.request.version.minor < versions.MINOR_44_NODE_DEPLOY_STEP:
|
||||
obj.deploy_step = wsme.Unset
|
||||
|
||||
if not api_utils.allow_resource_class():
|
||||
obj.resource_class = wsme.Unset
|
||||
|
||||
@ -990,6 +993,9 @@ class Node(base.APIBase):
|
||||
clean_step = wsme.wsattr({wtypes.text: types.jsontype}, readonly=True)
|
||||
"""The current clean step"""
|
||||
|
||||
deploy_step = wsme.wsattr({wtypes.text: types.jsontype}, readonly=True)
|
||||
"""The current deploy step"""
|
||||
|
||||
raid_config = wsme.wsattr({wtypes.text: types.jsontype}, readonly=True)
|
||||
"""Represents the current RAID configuration of the node """
|
||||
|
||||
@ -1215,7 +1221,7 @@ class Node(base.APIBase):
|
||||
provision_updated_at=time, instance_info={},
|
||||
maintenance=False, maintenance_reason=None, fault=None,
|
||||
inspection_finished_at=None, inspection_started_at=time,
|
||||
console_enabled=False, clean_step={},
|
||||
console_enabled=False, clean_step={}, deploy_step={},
|
||||
raid_config=None, target_raid_config=None,
|
||||
network_interface='flat', resource_class='baremetal-gold',
|
||||
boot_interface=None, console_interface=None,
|
||||
@ -1247,6 +1253,7 @@ class NodePatchType(types.JsonPatchType):
|
||||
'/provision_updated_at', '/maintenance_reason',
|
||||
'/driver_internal_info', '/inspection_finished_at',
|
||||
'/inspection_started_at', '/clean_step',
|
||||
'/deploy_step',
|
||||
'/raid_config', '/target_raid_config',
|
||||
'/fault']
|
||||
|
||||
@ -1484,7 +1491,8 @@ class NodesController(rest.RestController):
|
||||
|
||||
invalid_sort_key_list = ['properties', 'driver_info', 'extra',
|
||||
'instance_info', 'driver_internal_info',
|
||||
'clean_step', 'raid_config', 'target_raid_config',
|
||||
'clean_step', 'deploy_step',
|
||||
'raid_config', 'target_raid_config',
|
||||
'traits']
|
||||
|
||||
_subcontroller_map = {
|
||||
|
@ -81,6 +81,7 @@ BASE_VERSION = 1
|
||||
# v1.41: Add inspection abort support.
|
||||
# v1.42: Expose fault field to node.
|
||||
# v1.43: Add detail=True flag to all API endpoints
|
||||
# v1.44: Add node deploy_step field
|
||||
|
||||
MINOR_0_JUNO = 0
|
||||
MINOR_1_INITIAL_VERSION = 1
|
||||
@ -126,6 +127,7 @@ MINOR_40_BIOS_INTERFACE = 40
|
||||
MINOR_41_INSPECTION_ABORT = 41
|
||||
MINOR_42_FAULT = 42
|
||||
MINOR_43_ENABLE_DETAIL_QUERY = 43
|
||||
MINOR_44_NODE_DEPLOY_STEP = 44
|
||||
|
||||
# When adding another version, update:
|
||||
# - MINOR_MAX_VERSION
|
||||
@ -133,7 +135,7 @@ MINOR_43_ENABLE_DETAIL_QUERY = 43
|
||||
# explanation of what changed in the new version
|
||||
# - common/release_mappings.py, RELEASE_MAPPING['master']['api']
|
||||
|
||||
MINOR_MAX_VERSION = MINOR_43_ENABLE_DETAIL_QUERY
|
||||
MINOR_MAX_VERSION = MINOR_44_NODE_DEPLOY_STEP
|
||||
|
||||
# String representations of the minor and maximum versions
|
||||
_MIN_VERSION_STRING = '{}.{}'.format(BASE_VERSION, MINOR_1_INITIAL_VERSION)
|
||||
|
@ -115,7 +115,7 @@ RELEASE_MAPPING = {
|
||||
}
|
||||
},
|
||||
'master': {
|
||||
'api': '1.43',
|
||||
'api': '1.44',
|
||||
'rpc': '1.45',
|
||||
'objects': {
|
||||
'Node': ['1.26'],
|
||||
|
@ -633,11 +633,13 @@ class NodePayload(notification.NotificationPayloadBase):
|
||||
# Version 1.6: Add traits field exposed via API.
|
||||
# Version 1.7: Add fault field exposed via API.
|
||||
# Version 1.8: Add bios interface field exposed via API.
|
||||
VERSION = '1.8'
|
||||
# Version 1.9: Add deploy_step field exposed via API.
|
||||
VERSION = '1.9'
|
||||
fields = {
|
||||
'clean_step': object_fields.FlexibleDictField(nullable=True),
|
||||
'console_enabled': object_fields.BooleanField(nullable=True),
|
||||
'created_at': object_fields.DateTimeField(nullable=True),
|
||||
'deploy_step': object_fields.FlexibleDictField(nullable=True),
|
||||
'driver': object_fields.StringField(nullable=True),
|
||||
'extra': object_fields.FlexibleDictField(nullable=True),
|
||||
'inspection_finished_at': object_fields.DateTimeField(nullable=True),
|
||||
@ -706,7 +708,8 @@ class NodeSetPowerStatePayload(NodePayload):
|
||||
# Version 1.6: Parent NodePayload version 1.6
|
||||
# Version 1.7: Parent NodePayload version 1.7
|
||||
# Version 1.8: Parent NodePayload version 1.8
|
||||
VERSION = '1.8'
|
||||
# Version 1.9: Parent NodePayload version 1.9
|
||||
VERSION = '1.9'
|
||||
|
||||
fields = {
|
||||
# "to_power" indicates the future target_power_state of the node. A
|
||||
@ -755,7 +758,8 @@ class NodeCorrectedPowerStatePayload(NodePayload):
|
||||
# Version 1.6: Parent NodePayload version 1.6
|
||||
# Version 1.7: Parent NodePayload version 1.7
|
||||
# Version 1.8: Parent NodePayload version 1.8
|
||||
VERSION = '1.8'
|
||||
# Version 1.9: Parent NodePayload version 1.9
|
||||
VERSION = '1.9'
|
||||
|
||||
fields = {
|
||||
'from_power': object_fields.StringField(nullable=True)
|
||||
@ -788,7 +792,8 @@ class NodeSetProvisionStatePayload(NodePayload):
|
||||
# Version 1.6: Parent NodePayload version 1.6
|
||||
# Version 1.7: Parent NodePayload version 1.7
|
||||
# Version 1.8: Parent NodePayload version 1.8
|
||||
VERSION = '1.8'
|
||||
# Version 1.9: Parent NodePayload version 1.9
|
||||
VERSION = '1.9'
|
||||
|
||||
SCHEMA = dict(NodePayload.SCHEMA,
|
||||
**{'instance_info': ('node', 'instance_info')})
|
||||
@ -828,7 +833,8 @@ class NodeCRUDPayload(NodePayload):
|
||||
# Version 1.4: Parent NodePayload version 1.6
|
||||
# Version 1.5: Parent NodePayload version 1.7
|
||||
# Version 1.6: Parent NodePayload version 1.8
|
||||
VERSION = '1.6'
|
||||
# Version 1.7: Parent NodePayload version 1.9
|
||||
VERSION = '1.7'
|
||||
|
||||
SCHEMA = dict(NodePayload.SCHEMA,
|
||||
**{'instance_info': ('node', 'instance_info'),
|
||||
|
@ -122,6 +122,7 @@ class TestListNodes(test_api_base.BaseApiTest):
|
||||
# never expose the chassis_id
|
||||
self.assertNotIn('chassis_id', data['nodes'][0])
|
||||
self.assertNotIn('bios_interface', data['nodes'][0])
|
||||
self.assertNotIn('deploy_step', data['nodes'][0])
|
||||
|
||||
def test_get_one(self):
|
||||
node = obj_utils.create_test_node(self.context,
|
||||
@ -158,6 +159,7 @@ class TestListNodes(test_api_base.BaseApiTest):
|
||||
# never expose the chassis_id
|
||||
self.assertNotIn('chassis_id', data)
|
||||
self.assertIn('bios_interface', data)
|
||||
self.assertIn('deploy_step', data)
|
||||
|
||||
def test_get_one_with_json(self):
|
||||
# Test backward compatibility with guess_content_type_from_ext
|
||||
@ -250,6 +252,10 @@ class TestListNodes(test_api_base.BaseApiTest):
|
||||
self._test_node_field_hidden_in_lower_version('fault',
|
||||
'1.41', '1.42')
|
||||
|
||||
def test_node_deploy_step_hidden_in_lower_version(self):
|
||||
self._test_node_field_hidden_in_lower_version('deploy_step',
|
||||
'1.43', '1.44')
|
||||
|
||||
def test_get_one_custom_fields(self):
|
||||
node = obj_utils.create_test_node(self.context,
|
||||
chassis_id=self.chassis.id)
|
||||
@ -2419,6 +2425,19 @@ class TestPatch(test_api_base.BaseApiTest):
|
||||
self.assertEqual(http_client.BAD_REQUEST, response.status_code)
|
||||
self.assertTrue(response.json['error_message'])
|
||||
|
||||
def test_patch_deploy_step_forbidden(self):
|
||||
node = obj_utils.create_test_node(self.context,
|
||||
uuid=uuidutils.generate_uuid())
|
||||
response = self.patch_json('/nodes/%s' % node.uuid,
|
||||
[{'path': '/deploy_step',
|
||||
'op': 'replace',
|
||||
'value': 'deploy this'}],
|
||||
headers={api_base.Version.string: "1.43"},
|
||||
expect_errors=True)
|
||||
self.assertEqual('application/json', response.content_type)
|
||||
self.assertEqual(http_client.BAD_REQUEST, response.status_code)
|
||||
self.assertTrue(response.json['error_message'])
|
||||
|
||||
|
||||
def _create_node_locally(node):
|
||||
driver_factory.check_and_update_node_interfaces(node)
|
||||
|
@ -100,9 +100,6 @@ def node_post_data(**kw):
|
||||
node.pop('chassis_id')
|
||||
node.pop('tags')
|
||||
node.pop('traits')
|
||||
# TODO(mgoddard): Remove this once the deploy_step field is supported in
|
||||
# the API.
|
||||
node.pop('deploy_step')
|
||||
|
||||
# NOTE(jroll): pop out fields that were introduced in later API versions,
|
||||
# unless explicitly requested. Otherwise, these will cause tests using
|
||||
|
@ -672,21 +672,21 @@ expected_object_fingerprints = {
|
||||
'Conductor': '1.2-5091f249719d4a465062a1b3dc7f860d',
|
||||
'EventType': '1.1-aa2ba1afd38553e3880c267404e8d370',
|
||||
'NotificationPublisher': '1.0-51a09397d6c0687771fb5be9a999605d',
|
||||
'NodePayload': '1.8-2c327dfc77ce8c7a28b02eafaed509f0',
|
||||
'NodePayload': '1.9-c0aa5dd602adca3a28f091ca7848a41b',
|
||||
'NodeSetPowerStateNotification': '1.0-59acc533c11d306f149846f922739c15',
|
||||
'NodeSetPowerStatePayload': '1.8-916c39939609254de1f8050a1c8da7d1',
|
||||
'NodeSetPowerStatePayload': '1.9-07cd9053faa76199ffeaa45db78728a2',
|
||||
'NodeCorrectedPowerStateNotification':
|
||||
'1.0-59acc533c11d306f149846f922739c15',
|
||||
'NodeCorrectedPowerStatePayload': '1.8-1afef2b5c0538941defa00232302cd89',
|
||||
'NodeCorrectedPowerStatePayload': '1.9-321b389cd4aa2552da25a5001f7fcb71',
|
||||
'NodeSetProvisionStateNotification':
|
||||
'1.0-59acc533c11d306f149846f922739c15',
|
||||
'NodeSetProvisionStatePayload': '1.8-d4aa7eb5a449e9f8271b3127a2d2b6ea',
|
||||
'NodeSetProvisionStatePayload': '1.9-995f311c21e5e54bf2183db4056542a5',
|
||||
'VolumeConnector': '1.0-3e0252c0ab6e6b9d158d09238a577d97',
|
||||
'VolumeTarget': '1.0-0b10d663d8dae675900b2c7548f76f5e',
|
||||
'ChassisCRUDNotification': '1.0-59acc533c11d306f149846f922739c15',
|
||||
'ChassisCRUDPayload': '1.0-dce63895d8186279a7dd577cffccb202',
|
||||
'NodeCRUDNotification': '1.0-59acc533c11d306f149846f922739c15',
|
||||
'NodeCRUDPayload': '1.6-3ab7db0fc4574999fca91a1f04b4998f',
|
||||
'NodeCRUDPayload': '1.7-af856321c0531f52be431217214d203a',
|
||||
'PortCRUDNotification': '1.0-59acc533c11d306f149846f922739c15',
|
||||
'PortCRUDPayload': '1.2-233d259df442eb15cc584fae1fe81504',
|
||||
'NodeMaintenanceNotification': '1.0-59acc533c11d306f149846f922739c15',
|
||||
|
Loading…
Reference in New Issue
Block a user