Merge "Allow vendor_data to be included in a configdrive dict"
This commit is contained in:
commit
acfc2ea440
@ -561,6 +561,7 @@ configdrive:
|
||||
* ``network_data`` (optional) - JSON object with networking configuration.
|
||||
* ``user_data`` (optional) - user data. May be a string (which will be
|
||||
UTF-8 encoded); a JSON object, or a JSON array.
|
||||
* ``vendor_data`` (optional) - JSON object with extra vendor data.
|
||||
|
||||
This parameter is only accepted when setting the state to "active" or
|
||||
"rebuild".
|
||||
|
@ -2,6 +2,12 @@
|
||||
REST API Version History
|
||||
========================
|
||||
|
||||
1.59 (Ussuri, master)
|
||||
|
||||
Added the ability to specify a ``vendor_data`` dictionary field in the
|
||||
``configdrive`` parameter submitted with the deployment of a node. The value
|
||||
is a dictionary which is served as ``vendor_data2.json`` in the config drive.
|
||||
|
||||
1.58 (Train, 12.2.0)
|
||||
--------------------
|
||||
|
||||
|
@ -616,7 +616,8 @@ _CONFIG_DRIVE_SCHEMA = {
|
||||
'network_data': {'type': 'object'},
|
||||
'user_data': {
|
||||
'type': ['object', 'array', 'string', 'null']
|
||||
}
|
||||
},
|
||||
'vendor_data': {'type': 'object'},
|
||||
},
|
||||
'additionalProperties': False
|
||||
},
|
||||
@ -648,13 +649,22 @@ def check_allow_configdrive(target, configdrive=None):
|
||||
raise wsme.exc.ClientSideError(
|
||||
msg, status_code=http_client.BAD_REQUEST)
|
||||
|
||||
if isinstance(configdrive, dict) and not allow_build_configdrive():
|
||||
msg = _('Providing a JSON object for configdrive is only supported'
|
||||
' starting with API version %(base)s.%(opr)s') % {
|
||||
'base': versions.BASE_VERSION,
|
||||
'opr': versions.MINOR_56_BUILD_CONFIGDRIVE}
|
||||
raise wsme.exc.ClientSideError(
|
||||
msg, status_code=http_client.BAD_REQUEST)
|
||||
if isinstance(configdrive, dict):
|
||||
if not allow_build_configdrive():
|
||||
msg = _('Providing a JSON object for configdrive is only supported'
|
||||
' starting with API version %(base)s.%(opr)s') % {
|
||||
'base': versions.BASE_VERSION,
|
||||
'opr': versions.MINOR_56_BUILD_CONFIGDRIVE}
|
||||
raise wsme.exc.ClientSideError(
|
||||
msg, status_code=http_client.BAD_REQUEST)
|
||||
if ('vendor_data' in configdrive and
|
||||
not allow_configdrive_vendor_data()):
|
||||
msg = _('Providing vendor_data in configdrive is only supported'
|
||||
' starting with API version %(base)s.%(opr)s') % {
|
||||
'base': versions.BASE_VERSION,
|
||||
'opr': versions.MINOR_59_CONFIGDRIVE_VENDOR_DATA}
|
||||
raise wsme.exc.ClientSideError(
|
||||
msg, status_code=http_client.BAD_REQUEST)
|
||||
|
||||
|
||||
def check_allow_filter_by_fault(fault):
|
||||
@ -1163,6 +1173,15 @@ def allow_build_configdrive():
|
||||
return api.request.version.minor >= versions.MINOR_56_BUILD_CONFIGDRIVE
|
||||
|
||||
|
||||
def allow_configdrive_vendor_data():
|
||||
"""Check if configdrive can contain a vendor_data key.
|
||||
|
||||
Version 1.59 of the API added support for configdrive vendor_data.
|
||||
"""
|
||||
return (api.request.version.minor >=
|
||||
versions.MINOR_59_CONFIGDRIVE_VENDOR_DATA)
|
||||
|
||||
|
||||
def allow_allocation_update():
|
||||
"""Check if updating an existing allocation is allowed or not.
|
||||
|
||||
|
@ -96,6 +96,7 @@ BASE_VERSION = 1
|
||||
# v1.56: Add support for building configdrives.
|
||||
# v1.57: Add support for updating an exisiting allocation.
|
||||
# v1.58: Add support for backfilling allocations.
|
||||
# v1.59: Add support vendor data in configdrives.
|
||||
|
||||
MINOR_0_JUNO = 0
|
||||
MINOR_1_INITIAL_VERSION = 1
|
||||
@ -156,6 +157,7 @@ MINOR_55_DEPLOY_TEMPLATES = 55
|
||||
MINOR_56_BUILD_CONFIGDRIVE = 56
|
||||
MINOR_57_ALLOCATION_UPDATE = 57
|
||||
MINOR_58_ALLOCATION_BACKFILL = 58
|
||||
MINOR_59_CONFIGDRIVE_VENDOR_DATA = 59
|
||||
|
||||
# When adding another version, update:
|
||||
# - MINOR_MAX_VERSION
|
||||
@ -163,7 +165,7 @@ MINOR_58_ALLOCATION_BACKFILL = 58
|
||||
# explanation of what changed in the new version
|
||||
# - common/release_mappings.py, RELEASE_MAPPING['master']['api']
|
||||
|
||||
MINOR_MAX_VERSION = MINOR_58_ALLOCATION_BACKFILL
|
||||
MINOR_MAX_VERSION = MINOR_59_CONFIGDRIVE_VENDOR_DATA
|
||||
|
||||
# String representations of the minor and maximum versions
|
||||
_MIN_VERSION_STRING = '{}.{}'.format(BASE_VERSION, MINOR_1_INITIAL_VERSION)
|
||||
|
@ -197,7 +197,7 @@ RELEASE_MAPPING = {
|
||||
}
|
||||
},
|
||||
'master': {
|
||||
'api': '1.58',
|
||||
'api': '1.59',
|
||||
'rpc': '1.48',
|
||||
'objects': {
|
||||
'Allocation': ['1.0'],
|
||||
|
@ -831,7 +831,7 @@ def build_configdrive(node, configdrive):
|
||||
|
||||
:param node: an Ironic node object.
|
||||
:param configdrive: A configdrive as a dict with keys ``meta_data``,
|
||||
``network_data`` and ``user_data`` (all optional).
|
||||
``network_data``, ``user_data`` and ``vendor_data`` (all optional).
|
||||
:returns: A gzipped and base64 encoded configdrive as a string.
|
||||
"""
|
||||
meta_data = configdrive.setdefault('meta_data', {})
|
||||
@ -847,7 +847,8 @@ def build_configdrive(node, configdrive):
|
||||
|
||||
LOG.debug('Building a configdrive for node %s', node.uuid)
|
||||
return os_configdrive.build(meta_data, user_data=user_data,
|
||||
network_data=configdrive.get('network_data'))
|
||||
network_data=configdrive.get('network_data'),
|
||||
vendor_data=configdrive.get('vendor_data'))
|
||||
|
||||
|
||||
def fast_track_able(task):
|
||||
|
@ -4162,11 +4162,12 @@ class TestPut(test_api_base.BaseApiTest):
|
||||
def test_provision_with_deploy_configdrive_as_dict_all_fields(self):
|
||||
fake_cd = {'user_data': {'serialize': 'me'},
|
||||
'meta_data': {'hostname': 'example.com'},
|
||||
'network_data': {'links': []}}
|
||||
'network_data': {'links': []},
|
||||
'vendor_data': {'foo': 'bar'}}
|
||||
ret = self.put_json('/nodes/%s/states/provision' % self.node.uuid,
|
||||
{'target': states.ACTIVE,
|
||||
'configdrive': fake_cd},
|
||||
headers={api_base.Version.string: '1.56'})
|
||||
headers={api_base.Version.string: '1.59'})
|
||||
self.assertEqual(http_client.ACCEPTED, ret.status_code)
|
||||
self.assertEqual(b'', ret.body)
|
||||
self.mock_dnd.assert_called_once_with(context=mock.ANY,
|
||||
|
@ -479,6 +479,12 @@ class TestCheckAllowFields(base.TestCase):
|
||||
mock_request.version.minor = 34
|
||||
self.assertFalse(utils.allow_node_rebuild_with_configdrive())
|
||||
|
||||
def test_allow_configdrive_vendor_data(self, mock_request):
|
||||
mock_request.version.minor = 59
|
||||
self.assertTrue(utils.allow_configdrive_vendor_data())
|
||||
mock_request.version.minor = 58
|
||||
self.assertFalse(utils.allow_configdrive_vendor_data())
|
||||
|
||||
def test_check_allow_configdrive_fails(self, mock_request):
|
||||
mock_request.version.minor = 35
|
||||
self.assertRaises(wsme.exc.ClientSideError,
|
||||
@ -500,16 +506,27 @@ class TestCheckAllowFields(base.TestCase):
|
||||
utils.check_allow_configdrive(states.ACTIVE, "abcd")
|
||||
|
||||
def test_check_allow_configdrive_as_dict(self, mock_request):
|
||||
mock_request.version.minor = 56
|
||||
mock_request.version.minor = 59
|
||||
utils.check_allow_configdrive(states.ACTIVE, {'meta_data': {}})
|
||||
utils.check_allow_configdrive(states.ACTIVE, {'meta_data': {},
|
||||
'network_data': {},
|
||||
'user_data': {}})
|
||||
'user_data': {},
|
||||
'vendor_data': {}})
|
||||
utils.check_allow_configdrive(states.ACTIVE, {'user_data': 'foo'})
|
||||
utils.check_allow_configdrive(states.ACTIVE, {'user_data': ['foo']})
|
||||
|
||||
def test_check_allow_configdrive_vendor_data_failed(self, mock_request):
|
||||
mock_request.version.minor = 58
|
||||
self.assertRaises(wsme.exc.ClientSideError,
|
||||
utils.check_allow_configdrive,
|
||||
states.ACTIVE,
|
||||
{'meta_data': {},
|
||||
'network_data': {},
|
||||
'user_data': {},
|
||||
'vendor_data': {}})
|
||||
|
||||
def test_check_allow_configdrive_as_dict_invalid(self, mock_request):
|
||||
mock_request.version.minor = 56
|
||||
mock_request.version.minor = 59
|
||||
self.assertRaises(wsme.exc.ClientSideError,
|
||||
utils.check_allow_configdrive, states.REBUILD,
|
||||
{'foo': 'bar'})
|
||||
|
@ -2205,7 +2205,7 @@ class DoNodeDeployTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):
|
||||
configdrive = 'foo'
|
||||
self._test__do_node_deploy_ok(configdrive=configdrive)
|
||||
|
||||
@mock.patch('openstack.baremetal.configdrive.build', autospec=True)
|
||||
@mock.patch('openstack.baremetal.configdrive.build')
|
||||
def test__do_node_deploy_configdrive_as_dict(self, mock_cd):
|
||||
mock_cd.return_value = 'foo'
|
||||
configdrive = {'user_data': 'abcd'}
|
||||
@ -2213,9 +2213,10 @@ class DoNodeDeployTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):
|
||||
expected_configdrive='foo')
|
||||
mock_cd.assert_called_once_with({'uuid': self.node.uuid},
|
||||
network_data=None,
|
||||
user_data=b'abcd')
|
||||
user_data=b'abcd',
|
||||
vendor_data=None)
|
||||
|
||||
@mock.patch('openstack.baremetal.configdrive.build', autospec=True)
|
||||
@mock.patch('openstack.baremetal.configdrive.build')
|
||||
def test__do_node_deploy_configdrive_as_dict_with_meta_data(self, mock_cd):
|
||||
mock_cd.return_value = 'foo'
|
||||
configdrive = {'meta_data': {'uuid': uuidutils.generate_uuid(),
|
||||
@ -2225,9 +2226,10 @@ class DoNodeDeployTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):
|
||||
expected_configdrive='foo')
|
||||
mock_cd.assert_called_once_with(configdrive['meta_data'],
|
||||
network_data=None,
|
||||
user_data=None)
|
||||
user_data=None,
|
||||
vendor_data=None)
|
||||
|
||||
@mock.patch('openstack.baremetal.configdrive.build', autospec=True)
|
||||
@mock.patch('openstack.baremetal.configdrive.build')
|
||||
def test__do_node_deploy_configdrive_with_network_data(self, mock_cd):
|
||||
mock_cd.return_value = 'foo'
|
||||
configdrive = {'network_data': {'links': []}}
|
||||
@ -2235,9 +2237,10 @@ class DoNodeDeployTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):
|
||||
expected_configdrive='foo')
|
||||
mock_cd.assert_called_once_with({'uuid': self.node.uuid},
|
||||
network_data={'links': []},
|
||||
user_data=None)
|
||||
user_data=None,
|
||||
vendor_data=None)
|
||||
|
||||
@mock.patch('openstack.baremetal.configdrive.build', autospec=True)
|
||||
@mock.patch('openstack.baremetal.configdrive.build')
|
||||
def test__do_node_deploy_configdrive_and_user_data_as_dict(self, mock_cd):
|
||||
mock_cd.return_value = 'foo'
|
||||
configdrive = {'user_data': {'user': 'data'}}
|
||||
@ -2245,7 +2248,19 @@ class DoNodeDeployTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):
|
||||
expected_configdrive='foo')
|
||||
mock_cd.assert_called_once_with({'uuid': self.node.uuid},
|
||||
network_data=None,
|
||||
user_data=b'{"user": "data"}')
|
||||
user_data=b'{"user": "data"}',
|
||||
vendor_data=None)
|
||||
|
||||
@mock.patch('openstack.baremetal.configdrive.build')
|
||||
def test__do_node_deploy_configdrive_with_vendor_data(self, mock_cd):
|
||||
mock_cd.return_value = 'foo'
|
||||
configdrive = {'vendor_data': {'foo': 'bar'}}
|
||||
self._test__do_node_deploy_ok(configdrive=configdrive,
|
||||
expected_configdrive='foo')
|
||||
mock_cd.assert_called_once_with({'uuid': self.node.uuid},
|
||||
network_data=None,
|
||||
user_data=None,
|
||||
vendor_data={'foo': 'bar'})
|
||||
|
||||
@mock.patch.object(swift, 'SwiftAPI')
|
||||
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.prepare')
|
||||
|
@ -20,7 +20,7 @@ keystoneauth1==3.15.0
|
||||
keystonemiddleware==4.17.0
|
||||
mock==3.0.0
|
||||
openstackdocstheme==1.20.0
|
||||
openstacksdk==0.31.2
|
||||
openstacksdk==0.37.0
|
||||
os-api-ref==1.4.0
|
||||
os-traits==0.4.0
|
||||
oslo.concurrency==3.26.0
|
||||
|
@ -0,0 +1,8 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Adds support for specifying vendor_data when building config drives.
|
||||
Starting with API version 1.59, a JSON based ``configdrive`` parameter to
|
||||
``/v1/nodes/<node>/states/provision`` can include the key vendor_data.
|
||||
This data will be built into the configdrive contents as
|
||||
vendor_data2.json.
|
@ -47,4 +47,4 @@ jsonschema>=2.6.0 # MIT
|
||||
psutil>=3.2.2 # BSD
|
||||
futurist>=1.2.0 # Apache-2.0
|
||||
tooz>=1.58.0 # Apache-2.0
|
||||
openstacksdk>=0.31.2 # Apache-2.0
|
||||
openstacksdk>=0.37.0 # Apache-2.0
|
||||
|
Loading…
Reference in New Issue
Block a user