summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Fournier <bfournie@redhat.com>2021-04-16 15:15:53 -0400
committerBob Fournier <bfournie@redhat.com>2021-05-27 12:15:20 -0400
commite15440370cca1f1a998d3607910697c3129d040a (patch)
tree679da9689641befecc922a83f2c4542999807825
parentcaa4c8fd2964cd0c75025705497b7040c973dbe0 (diff)
downloadironic-e15440370cca1f1a998d3607910697c3129d040a.tar.gz
Include bios registry fields in bios API
Provide the fields in the BIOS setting API - ``/v1/nodes/{node}/bios/{setting}``, and in the BIOS setting list API when details are requested - ``/v1/nodes/<node>/bios?detail=True``. Story: #2008571 Task: #42483 Change-Id: Ie86ec57e428e2bb2efd099a839105e51a94824ab
-rw-r--r--api-ref/source/baremetal-api-v1-nodes-bios.inc68
-rw-r--r--api-ref/source/parameters.yaml67
-rw-r--r--api-ref/source/samples/node-bios-detail-response.json13
-rw-r--r--api-ref/source/samples/node-bios-list-details-response.json30
-rw-r--r--api-ref/source/samples/node-bios-list-response.json4
-rw-r--r--doc/source/contributor/webapi-version-history.rst11
-rw-r--r--ironic/api/controllers/v1/bios.py41
-rw-r--r--ironic/api/controllers/v1/utils.py26
-rw-r--r--ironic/api/controllers/v1/versions.py4
-rw-r--r--ironic/common/release_mappings.py3
-rw-r--r--ironic/conductor/utils.py3
-rw-r--r--ironic/db/api.py4
-rw-r--r--ironic/db/sqlalchemy/alembic/versions/2bbd96b6ccb9_add_bios_fields_from_registry.py46
-rw-r--r--ironic/db/sqlalchemy/api.py21
-rw-r--r--ironic/db/sqlalchemy/models.py9
-rw-r--r--ironic/objects/bios.py67
-rw-r--r--ironic/tests/unit/api/controllers/v1/test_node.py113
-rw-r--r--ironic/tests/unit/common/test_release_mappings.py2
-rw-r--r--ironic/tests/unit/db/sqlalchemy/test_migrations.py34
-rw-r--r--ironic/tests/unit/db/test_bios_settings.py18
-rw-r--r--ironic/tests/unit/db/utils.py16
-rw-r--r--ironic/tests/unit/objects/test_bios.py50
-rw-r--r--ironic/tests/unit/objects/test_objects.py2
-rw-r--r--releasenotes/notes/bios-registry-support-e7fd62908e9c222d.yaml8
24 files changed, 613 insertions, 47 deletions
diff --git a/api-ref/source/baremetal-api-v1-nodes-bios.inc b/api-ref/source/baremetal-api-v1-nodes-bios.inc
index 4602b134b..887e2029a 100644
--- a/api-ref/source/baremetal-api-v1-nodes-bios.inc
+++ b/api-ref/source/baremetal-api-v1-nodes-bios.inc
@@ -19,6 +19,11 @@ List all Bios settings by Node
Return a list of Bios settings associated with ``node_ident``.
+.. versionadded:: 1.74
+ Added additional fields from bios registry which can be retrieved using
+ ``?detail=True`` (see detailed response below).
+ Added ``fields`` selector to query for particular fields.
+
Normal response code: 200
Error codes: 404
@@ -29,6 +34,8 @@ Request
.. rest_parameters:: parameters.yaml
- node_ident: node_ident
+ - fields: fields
+ - detail: detail
Response
--------
@@ -46,6 +53,55 @@ Response
.. literalinclude:: samples/node-bios-list-response.json
+List detailed Bios settings by Node
+===================================
+
+.. rest_method:: GET /v1/nodes/{node_ident}/bios/?detail=True
+
+Return a list of detailed Bios settings associated with ``node_ident``.
+The detailed list includes the BIOS Attribute Registry information
+retrieved via Redfish.
+
+.. versionadded:: 1.74
+ Introduced
+
+
+Normal response code: 200
+
+Error codes: 404
+
+Request
+-------
+
+.. rest_parameters:: parameters.yaml
+
+ - node_ident: node_ident
+
+Response
+--------
+
+.. rest_parameters:: parameters.yaml
+
+ - bios: bios_settings
+ - created_at: created_at
+ - updated_at: updated_at
+ - links: links
+ - name: bios_setting_name
+ - value: bios_setting_value
+ - attribute_type: bios_setting_attribute_type
+ - allowable_values: bios_setting_allowable_values
+ - lower_bound: bios_setting_lower_bound
+ - max_length: bios_setting_max_length
+ - min_length: bios_setting_min_length
+ - read_only: bios_setting_read_only
+ - reset_required: bios_setting_reset_required
+ - unique: bios_setting_unique
+ - upper_bound: bios_setting_upper_bound
+
+**Example list of a Node's Bios settings:**
+
+.. literalinclude:: samples/node-bios-list-details-response.json
+
Show single Bios setting of a Node
==================================
@@ -55,6 +111,9 @@ Show single Bios setting of a Node
Return the content of the specific bios ``bios_setting`` associated with
``node_ident``.
+. versionadded:: 1.74
+ Introduced fields from the BIOS registry.
+
Normal response code: 200
Error codes: 404
@@ -78,6 +137,15 @@ Response
- links: links
- name: bios_setting_name
- value: bios_setting_value
+ - attribute_type: bios_setting_attribute_type
+ - allowable_values: bios_setting_allowable_values
+ - lower_bound: bios_setting_lower_bound
+ - max_length: bios_setting_max_length
+ - min_length: bios_setting_min_length
+ - read_only: bios_setting_read_only
+ - reset_required: bios_setting_reset_required
+ - unique: bios_setting_unique
+ - upper_bound: bios_setting_upper_bound
**Example details of a Node's Bios setting details:**
diff --git a/api-ref/source/parameters.yaml b/api-ref/source/parameters.yaml
index 5129333f0..ef9b1b975 100644
--- a/api-ref/source/parameters.yaml
+++ b/api-ref/source/parameters.yaml
@@ -505,12 +505,75 @@ bios_interface:
in: body
required: true
type: string
+bios_setting_allowable_values:
+ description: |
+ A list of allowable values when the attribute_type is "Enumeration",
+ otherwise None.
+ in: body
+ required: true
+ type: array
+bios_setting_attribute_type:
+ description: |
+ A string describing the type of the Bios setting - "Enumeration",
+ "Integer", "String", "Boolean", or "Password". May be None.
+ in: body
+ required: true
+ type: string
+bios_setting_lower_bound:
+ description: |
+ The lowest allowed value when attribute_type is "Integer".
+ May be None.
+ in: body
+ required: true
+ type: integer
+bios_setting_max_length:
+ description: |
+ The maximum length when attribute_type is "String".
+ May be None.
+ in: body
+ required: true
+ type: integer
+bios_setting_min_length:
+ description: |
+ The minimum length when attribute_type is "String".
+ May be None.
+ in: body
+ required: true
+ type: integer
bios_setting_name:
description: |
The name of a Bios setting for a Node, eg. "virtualization".
in: body
required: true
type: string
+bios_setting_read_only:
+ description: |
+ This Bios seting is read only and can't be changed.
+ May be None.
+ in: body
+ required: true
+ type: boolean
+bios_setting_reset_required:
+ description: |
+ After setting this Bios setting a node reboot is required.
+ May be None.
+ in: body
+ required: true
+ type: boolean
+bios_setting_unique:
+ description: |
+ This Bios setting is unique to this node.
+ May be None.
+ in: body
+ required: true
+ type: boolean
+bios_setting_upper_bound:
+ description: |
+ The lowest allowed value when attribute_type is "Integer".
+ May be None.
+ in: body
+ required: true
+ type: integer
bios_setting_value:
description: |
The value of a Bios setting for a Node, eg. "on".
@@ -520,7 +583,9 @@ bios_setting_value:
bios_settings:
description: |
Optional list of one or more Bios settings. It includes following fields
- "created_at", "updated_at", "links", "name", "value".
+ "created_at", "updated_at", "links", "name", "value", "attribute_type",
+ "allowable_values", "lower_bound", "max_length", "min_length", "read_only",
+ "reset_required", "unique", "upper_bound"
in: body
required: true
type: array
diff --git a/api-ref/source/samples/node-bios-detail-response.json b/api-ref/source/samples/node-bios-detail-response.json
index a7b01028c..195f89721 100644
--- a/api-ref/source/samples/node-bios-detail-response.json
+++ b/api-ref/source/samples/node-bios-detail-response.json
@@ -12,7 +12,16 @@
"rel": "bookmark"
}
],
- "name": "virtualization",
- "value": "on"
+ "name": "Virtualization",
+ "value": "Enabled",
+ "attribute_type": "Enumeration",
+ "allowable_values": ["Enabled", "Disabled"],
+ "lower_bound": None,
+ "max_length": None,
+ "min_length": None,
+ "read_only": false,
+ "reset_required": None,
+ "unique": None,
+ "upper_bound": None
}
}
diff --git a/api-ref/source/samples/node-bios-list-details-response.json b/api-ref/source/samples/node-bios-list-details-response.json
new file mode 100644
index 000000000..52a48b3b1
--- /dev/null
+++ b/api-ref/source/samples/node-bios-list-details-response.json
@@ -0,0 +1,30 @@
+{
+ "bios": [
+ {
+ "created_at": "2016-08-18T22:28:49.653974+00:00",
+ "updated_at": "2016-08-18T22:28:49.653974+00:00",
+ "links": [
+ {
+ "href": "http://127.0.0.1:6385/v1/nodes/6d85703a-565d-469a-96ce-30b6de53079d/bios/virtualization",
+ "rel": "self"
+ },
+ {
+ "href": "http://127.0.0.1:6385/v1/nodes/6d85703a-565d-469a-96ce-30b6de53079d/bios/virtualization",
+ "rel": "bookmark"
+ }
+ ],
+ "name": "Virtualization",
+ "value": "Enabled",
+ "attribute_type": "Enumeration",
+ "allowable_values": ["Enabled", "Disabled"],
+ "lower_bound": None,
+ "max_length": None,
+ "min_length": None,
+ "read_only": false,
+ "reset_required": None,
+ "unique": None,
+ "upper_bound": None
+ }
+ ]
+}
+
diff --git a/api-ref/source/samples/node-bios-list-response.json b/api-ref/source/samples/node-bios-list-response.json
index 87d5e9c89..8255c240e 100644
--- a/api-ref/source/samples/node-bios-list-response.json
+++ b/api-ref/source/samples/node-bios-list-response.json
@@ -13,8 +13,8 @@
"rel": "bookmark"
}
],
- "name": "virtualization",
- "value": "on"
+ "name": "Virtualization",
+ "value": "Enabled"
}
]
}
diff --git a/doc/source/contributor/webapi-version-history.rst b/doc/source/contributor/webapi-version-history.rst
index 37adc74cf..10816c529 100644
--- a/doc/source/contributor/webapi-version-history.rst
+++ b/doc/source/contributor/webapi-version-history.rst
@@ -2,8 +2,19 @@
REST API Version History
========================
+1.74 (Xena)
+----------------------
+
+Add support for BIOS registry fields which include details about the BIOS
+setting. Included in the ``/v1/nodes/{node_ident}/bios/{setting}`` response.
+Add a new selector to include the fields in the BIOS settings list:
+* ``/v1/nodes/{node_ident}/bios/?detail=``
+Also add a fields selector to the the BIOS settings list:
+* ``/v1/nodes/{node_ident}/bios/?fields=``
+
1.73 (Xena)
----------------------
+
Add a new ``deploy`` verb as an alias to ``active`` and
``undeploy`` verb as an alias to ``deleted``.
diff --git a/ironic/api/controllers/v1/bios.py b/ironic/api/controllers/v1/bios.py
index 05fc46d8a..8a3adf3b7 100644
--- a/ironic/api/controllers/v1/bios.py
+++ b/ironic/api/controllers/v1/bios.py
@@ -25,23 +25,34 @@ from ironic import objects
METRICS = metrics_utils.get_metrics_logger(__name__)
+_DEFAULT_RETURN_FIELDS = ('name', 'value')
+_DEFAULT_FIELDS_WITH_REGISTRY = ('name', 'value', 'attribute_type',
+ 'allowable_values', 'lower_bound',
+ 'max_length', 'min_length', 'read_only',
+ 'reset_required', 'unique', 'upper_bound')
-def convert_with_links(rpc_bios, node_uuid):
+
+def convert_with_links(rpc_bios, node_uuid, detail=None, fields=None):
"""Build a dict containing a bios setting value."""
+
+ if detail:
+ fields = _DEFAULT_FIELDS_WITH_REGISTRY
+
bios = api_utils.object_to_dict(
rpc_bios,
include_uuid=False,
- fields=('name', 'value'),
+ fields=fields,
link_resource='nodes',
link_resource_args="%s/bios/%s" % (node_uuid, rpc_bios.name),
)
return bios
-def collection_from_list(node_ident, bios_settings):
+def collection_from_list(node_ident, bios_settings, detail=None, fields=None):
bios_list = []
for bios_setting in bios_settings:
- bios_list.append(convert_with_links(bios_setting, node_ident))
+ bios_list.append(convert_with_links(bios_setting, node_ident,
+ detail, fields))
return {'bios': bios_list}
@@ -54,14 +65,23 @@ class NodeBiosController(rest.RestController):
@METRICS.timer('NodeBiosController.get_all')
@method.expose()
- def get_all(self):
+ @args.validate(fields=args.string_list, detail=args.boolean)
+ def get_all(self, detail=None, fields=None):
"""List node bios settings."""
node = api_utils.check_node_policy_and_retrieve(
'baremetal:node:bios:get', self.node_ident)
+ # The BIOS detail and fields query were added in a later
+ # version, check if they are valid based on version
+ allow_query = api_utils.allow_query_bios
+ fields = api_utils.get_request_return_fields(fields, detail,
+ _DEFAULT_RETURN_FIELDS,
+ allow_query, allow_query)
+
settings = objects.BIOSSettingList.get_by_node_id(
api.request.context, node.id)
- return collection_from_list(self.node_ident, settings)
+ return collection_from_list(self.node_ident, settings,
+ detail, fields)
@METRICS.timer('NodeBiosController.get_one')
@method.expose()
@@ -81,4 +101,11 @@ class NodeBiosController(rest.RestController):
raise exception.BIOSSettingNotFound(node=node.uuid,
name=setting_name)
- return {setting_name: convert_with_links(setting, node.uuid)}
+ # Return fields based on version
+ if api_utils.allow_query_bios():
+ fields = _DEFAULT_FIELDS_WITH_REGISTRY
+ else:
+ fields = _DEFAULT_RETURN_FIELDS
+
+ return {setting_name: convert_with_links(setting, node.uuid,
+ fields=fields)}
diff --git a/ironic/api/controllers/v1/utils.py b/ironic/api/controllers/v1/utils.py
index 83c2a1602..4a753c4d1 100644
--- a/ironic/api/controllers/v1/utils.py
+++ b/ironic/api/controllers/v1/utils.py
@@ -1321,18 +1321,27 @@ def allow_detail_query():
return api.request.version.minor >= versions.MINOR_43_ENABLE_DETAIL_QUERY
+def allow_query_bios():
+ """Check if BIOS queries should be allowed based on version"""
+
+ return api.request.version.minor >= versions.MINOR_74_BIOS_REGISTRY
+
+
def allow_reset_interfaces():
"""Check if passing a reset_interfaces query string is allowed."""
return api.request.version.minor >= versions.MINOR_45_RESET_INTERFACES
-def get_request_return_fields(fields, detail, default_fields):
+def get_request_return_fields(fields, detail, default_fields,
+ check_detail_version=allow_detail_query,
+ check_fields_version=None):
"""Calculate fields to return from an API request
The fields query and detail=True query can not be passed into a request at
the same time. To use the detail query we need to be on a version of the
- API greater than 1.43. This function raises an InvalidParameterValue
- exception if either of these conditions are not met.
+ API greater than expected, likewise some APIs require a certain version for
+ the fields query. This function raises an InvalidParameterValue exception
+ if any of these conditions are not met.
If these checks pass then this function will return either the fields
passed in or the default fields provided.
@@ -1341,15 +1350,24 @@ def get_request_return_fields(fields, detail, default_fields):
:param detail: The detail query passed into the API request.
:param default_fields: The default fields to return if fields=None and
detail=None.
+ :param check_detail_version: Function to check if detail query is allowed
+ based on the version.
+ :param check_fields_version: Function to check if fields query is allowed
+ based on the version.
:raises: InvalidParameterValue if there is an invalid combination of query
strings or API version.
:returns: 'fields' passed in value or 'default_fields'
"""
- if detail is not None and not allow_detail_query():
+ if detail is not None and not check_detail_version():
raise exception.InvalidParameterValue(
"Invalid query parameter ?detail=%s received." % detail)
+ if (fields is not None and callable(check_fields_version)
+ and not check_fields_version()):
+ raise exception.InvalidParameterValue(
+ "Invalid query parameter ?fields=%s received." % fields)
+
if fields is not None and detail:
raise exception.InvalidParameterValue(
"Can not specify ?detail=True and fields in the same request.")
diff --git a/ironic/api/controllers/v1/versions.py b/ironic/api/controllers/v1/versions.py
index 97e03485e..677a27475 100644
--- a/ironic/api/controllers/v1/versions.py
+++ b/ironic/api/controllers/v1/versions.py
@@ -111,6 +111,7 @@ BASE_VERSION = 1
# v1.71: Add signifier for Scope based roles.
# v1.72: Add agent_status and agent_status_message to /v1/heartbeat
# v1.73: Add support for deploy and undeploy verbs
+# v1.74: Add bios registry to /v1/nodes/{node}/bios/{setting}
MINOR_0_JUNO = 0
MINOR_1_INITIAL_VERSION = 1
@@ -186,6 +187,7 @@ MINOR_70_CLEAN_DISABLE_RAMDISK = 70
MINOR_71_RBAC_SCOPES = 71
MINOR_72_HEARTBEAT_STATUS = 72
MINOR_73_DEPLOY_UNDEPLOY_VERBS = 73
+MINOR_74_BIOS_REGISTRY = 74
# When adding another version, update:
# - MINOR_MAX_VERSION
@@ -193,7 +195,7 @@ MINOR_73_DEPLOY_UNDEPLOY_VERBS = 73
# explanation of what changed in the new version
# - common/release_mappings.py, RELEASE_MAPPING['master']['api']
-MINOR_MAX_VERSION = MINOR_73_DEPLOY_UNDEPLOY_VERBS
+MINOR_MAX_VERSION = MINOR_74_BIOS_REGISTRY
# String representations of the minor and maximum versions
_MIN_VERSION_STRING = '{}.{}'.format(BASE_VERSION, MINOR_1_INITIAL_VERSION)
diff --git a/ironic/common/release_mappings.py b/ironic/common/release_mappings.py
index 526f424f7..29cde3fc0 100644
--- a/ironic/common/release_mappings.py
+++ b/ironic/common/release_mappings.py
@@ -320,10 +320,11 @@ RELEASE_MAPPING = {
}
},
'master': {
- 'api': '1.73',
+ 'api': '1.74',
'rpc': '1.54',
'objects': {
'Allocation': ['1.1'],
+ 'BIOSSetting': ['1.1'],
'Node': ['1.35'],
'Conductor': ['1.3'],
'Chassis': ['1.3'],
diff --git a/ironic/conductor/utils.py b/ironic/conductor/utils.py
index 2a3e6b4f8..cbadd091c 100644
--- a/ironic/conductor/utils.py
+++ b/ironic/conductor/utils.py
@@ -1385,8 +1385,7 @@ def store_agent_certificate(node, agent_verify_ca):
def node_cache_bios_settings(task, node):
"""Do caching of bios settings if supported by driver"""
try:
- LOG.debug('BF getting BIOS info for node %s',
- node.uuid)
+ LOG.debug('Getting BIOS info for node %s', node.uuid)
task.driver.bios.cache_bios_settings(task)
except exception.UnsupportedDriverExtension:
LOG.warning('BIOS settings are not supported for node %s, '
diff --git a/ironic/db/api.py b/ironic/db/api.py
index da0838478..0845fcd55 100644
--- a/ironic/db/api.py
+++ b/ironic/db/api.py
@@ -1054,10 +1054,12 @@ class Connection(object, metaclass=abc.ABCMeta):
{
'name': String,
'value': String,
+ additional settings from BIOS registry
},
{
'name': String,
'value': String,
+ additional settings from BIOS registry
},
...
]
@@ -1081,10 +1083,12 @@ class Connection(object, metaclass=abc.ABCMeta):
{
'name': String,
'value': String,
+ additional settings from BIOS registry
},
{
'name': String,
'value': String,
+ additional settings from BIOS registry
},
...
]
diff --git a/ironic/db/sqlalchemy/alembic/versions/2bbd96b6ccb9_add_bios_fields_from_registry.py b/ironic/db/sqlalchemy/alembic/versions/2bbd96b6ccb9_add_bios_fields_from_registry.py
new file mode 100644
index 000000000..204bc46fd
--- /dev/null
+++ b/ironic/db/sqlalchemy/alembic/versions/2bbd96b6ccb9_add_bios_fields_from_registry.py
@@ -0,0 +1,46 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""Add fields from BIOS registry
+
+Revision ID: 2bbd96b6ccb9
+Revises: ac00b586ab95
+Create Date: 2021-04-29 08:52:23.938863
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+# revision identifiers, used by Alembic.
+revision = '2bbd96b6ccb9'
+down_revision = 'ac00b586ab95'
+
+
+def upgrade():
+ op.add_column('bios_settings', sa.Column('attribute_type',
+ sa.String(length=255), nullable=True))
+ op.add_column('bios_settings', sa.Column('allowable_values',
+ sa.Text(), nullable=True))
+ op.add_column('bios_settings', sa.Column('lower_bound',
+ sa.Integer(), nullable=True))
+ op.add_column('bios_settings', sa.Column('max_length',
+ sa.Integer(), nullable=True))
+ op.add_column('bios_settings', sa.Column('min_length',
+ sa.Integer(), nullable=True))
+ op.add_column('bios_settings', sa.Column('read_only',
+ sa.Boolean(), nullable=True))
+ op.add_column('bios_settings', sa.Column('reset_required',
+ sa.Boolean(), nullable=True))
+ op.add_column('bios_settings', sa.Column('unique',
+ sa.Boolean(), nullable=True))
+ op.add_column('bios_settings', sa.Column('upper_bound',
+ sa.Integer(), nullable=True))
diff --git a/ironic/db/sqlalchemy/api.py b/ironic/db/sqlalchemy/api.py
index 702755e97..6f027c96a 100644
--- a/ironic/db/sqlalchemy/api.py
+++ b/ironic/db/sqlalchemy/api.py
@@ -1675,6 +1675,15 @@ class Connection(api.Connection):
node_id=node_id,
name=setting['name'],
value=setting['value'],
+ attribute_type=setting.get('attribute_type'),
+ allowable_values=setting.get('allowable_values'),
+ lower_bound=setting.get('lower_bound'),
+ max_length=setting.get('max_length'),
+ min_length=setting.get('min_length'),
+ read_only=setting.get('read_only'),
+ reset_required=setting.get('reset_required'),
+ unique=setting.get('unique'),
+ upper_bound=setting.get('upper_bound'),
version=version)
bios_settings.append(bios_setting)
session.add(bios_setting)
@@ -1695,6 +1704,18 @@ class Connection(api.Connection):
node_id=node_id, name=setting['name'])
ref = query.one()
ref.update({'value': setting['value'],
+ 'attribute_type':
+ setting.get('attribute_type'),
+ 'allowable_values':
+ setting.get('allowable_values'),
+ 'lower_bound': setting.get('lower_bound'),
+ 'max_length': setting.get('max_length'),
+ 'min_length': setting.get('min_length'),
+ 'read_only': setting.get('read_only'),
+ 'reset_required':
+ setting.get('reset_required'),
+ 'unique': setting.get('unique'),
+ 'upper_bound': setting.get('upper_bound'),
'version': version})
bios_settings.append(ref)
session.flush()
diff --git a/ironic/db/sqlalchemy/models.py b/ironic/db/sqlalchemy/models.py
index ef85b5d6d..96c18af26 100644
--- a/ironic/db/sqlalchemy/models.py
+++ b/ironic/db/sqlalchemy/models.py
@@ -339,6 +339,15 @@ class BIOSSetting(Base):
primary_key=True, nullable=False)
name = Column(String(255), primary_key=True, nullable=False)
value = Column(Text, nullable=True)
+ attribute_type = Column(String(255), nullable=True)
+ allowable_values = Column(db_types.JsonEncodedList, nullable=True)
+ lower_bound = Column(Integer, nullable=True)
+ max_length = Column(Integer, nullable=True)
+ min_length = Column(Integer, nullable=True)
+ read_only = Column(Boolean, nullable=True)
+ reset_required = Column(Boolean, nullable=True)
+ unique = Column(Boolean, nullable=True)
+ upper_bound = Column(Integer, nullable=True)
class Allocation(Base):
diff --git a/ironic/objects/bios.py b/ironic/objects/bios.py
index c7f705ef7..cb6718074 100644
--- a/ironic/objects/bios.py
+++ b/ironic/objects/bios.py
@@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+from oslo_utils import versionutils
from oslo_versionedobjects import base as object_base
from ironic.db import api as dbapi
@@ -23,14 +24,29 @@ from ironic.objects import fields as object_fields
@base.IronicObjectRegistry.register
class BIOSSetting(base.IronicObject):
# Version 1.0: Initial version
- VERSION = '1.0'
+ # Version 1.1: Added registry
+ VERSION = '1.1'
dbapi = dbapi.get_instance()
+ registry_fields = ('attribute_type', 'allowable_values', 'lower_bound',
+ 'max_length', 'min_length', 'read_only',
+ 'reset_required', 'unique', 'upper_bound')
+
fields = {
'node_id': object_fields.StringField(nullable=False),
'name': object_fields.StringField(nullable=False),
'value': object_fields.StringField(nullable=True),
+ 'attribute_type': object_fields.StringField(nullable=True),
+ 'allowable_values': object_fields.ListOfStringsField(
+ nullable=True),
+ 'lower_bound': object_fields.IntegerField(nullable=True),
+ 'max_length': object_fields.IntegerField(nullable=True),
+ 'min_length': object_fields.IntegerField(nullable=True),
+ 'read_only': object_fields.BooleanField(nullable=True),
+ 'reset_required': object_fields.BooleanField(nullable=True),
+ 'unique': object_fields.BooleanField(nullable=True),
+ 'upper_bound': object_fields.IntegerField(nullable=True)
}
# NOTE(xek): We don't want to enable RPC on this call just yet. Remotable
@@ -50,9 +66,12 @@ class BIOSSetting(base.IronicObject):
:raises: BIOSSettingAlreadyExists if the setting record already exists.
"""
values = self.do_version_changes_for_db()
- setting = [{'name': values['name'], 'value': values['value']}]
+ settings = {'name': values['name'], 'value': values['value']}
+ for r in self.registry_fields:
+ settings[r] = values.get(r)
+
db_bios_setting = self.dbapi.create_bios_setting_list(
- values['node_id'], setting, values['version'])
+ values['node_id'], [settings], values['version'])
self._from_db_object(self._context, self, db_bios_setting[0])
# NOTE(xek): We don't want to enable RPC on this call just yet. Remotable
@@ -72,9 +91,13 @@ class BIOSSetting(base.IronicObject):
:raises: BIOSSettingNotFound if the bios setting name is not found.
"""
values = self.do_version_changes_for_db()
- setting = [{'name': values['name'], 'value': values['value']}]
+
+ settings = {'name': values['name'], 'value': values['value']}
+ for r in self.registry_fields:
+ settings[r] = values.get(r)
+
updated_bios_setting = self.dbapi.update_bios_setting_list(
- values['node_id'], setting, values['version'])
+ values['node_id'], [settings], values['version'])
self._from_db_object(self._context, self, updated_bios_setting[0])
# NOTE(xek): We don't want to enable RPC on this call just yet. Remotable
@@ -111,6 +134,40 @@ class BIOSSetting(base.IronicObject):
"""
cls.dbapi.delete_bios_setting_list(node_id, [name])
+ def _convert_to_version(self, target_version,
+ remove_unavailable_fields=True):
+ """Convert to the target version.
+
+ Convert the object to the target version. The target version may be
+ the same, older, or newer than the version of the object. This is
+ used for DB interactions as well as for serialization/deserialization.
+
+ Version 1.74: remove registry field for unsupported versions if
+ remove_unavailable_fields is True.
+
+ :param target_version: the desired version of the object
+ :param remove_unavailable_fields: True to remove fields that are
+ unavailable in the target version; set this to True when
+ (de)serializing. False to set the unavailable fields to appropriate
+ values; set this to False for DB interactions.
+ """
+ target_version = versionutils.convert_version_to_tuple(target_version)
+
+ for field in self.get_registry_fields():
+ field_is_set = self.obj_attr_is_set(field)
+ if target_version >= (1, 74):
+ # target version supports the major/minor specified
+ if not field_is_set:
+ # set it to its default value if it is not set
+ setattr(self, field, None)
+ elif field_is_set:
+ # target version does not support the field, and it is set
+ if remove_unavailable_fields:
+ # (De)serialising: remove unavailable fields
+ delattr(self, field)
+ elif self.registry:
+ setattr(self, field, None)
+
@base.IronicObjectRegistry.register
class BIOSSettingList(base.IronicObjectListBase, base.IronicObject):
diff --git a/ironic/tests/unit/api/controllers/v1/test_node.py b/ironic/tests/unit/api/controllers/v1/test_node.py
index baa21d5a9..4a94671a9 100644
--- a/ironic/tests/unit/api/controllers/v1/test_node.py
+++ b/ironic/tests/unit/api/controllers/v1/test_node.py
@@ -6685,7 +6685,7 @@ class TestBIOS(test_api_base.BaseApiTest):
def setUp(self):
super(TestBIOS, self).setUp()
- self.version = "1.40"
+ self.version = "1.74"
self.node = obj_utils.create_test_node(
self.context, id=1)
self.bios = obj_utils.create_test_bios_setting(self.context,
@@ -6718,13 +6718,40 @@ class TestBIOS(test_api_base.BaseApiTest):
expected_json = {
'virtualization': {
+ 'allowable_values': ['on', 'off'],
+ 'attribute_type': 'Enumeration',
'created_at': ret['virtualization']['created_at'],
- 'updated_at': ret['virtualization']['updated_at'],
'links': [
{'href': 'http://localhost/v1/nodes/%s/bios/virtualization'
% self.node.uuid, u'rel': u'self'},
{'href': 'http://localhost/nodes/%s/bios/virtualization'
% self.node.uuid, u'rel': u'bookmark'}],
+ 'lower_bound': None,
+ 'min_length': None,
+ 'max_length': None,
+ 'name': 'virtualization',
+ 'read_only': False,
+ 'reset_required': True,
+ 'unique': False,
+ 'updated_at': None,
+ 'upper_bound': None,
+ 'value': 'on'}}
+
+ self.assertEqual(expected_json, ret)
+
+ def test_get_one_bios_no_registry(self):
+ ret = self.get_json('/nodes/%s/bios/virtualization' % self.node.uuid,
+ headers={api_base.Version.string: "1.73"})
+
+ expected_json = {
+ 'virtualization': {
+ 'created_at': ret['virtualization']['created_at'],
+ 'updated_at': ret['virtualization']['updated_at'],
+ 'links': [
+ {'href': 'http://localhost/v1/nodes/%s/bios/virtualization'
+ % self.node.uuid, 'rel': 'self'},
+ {'href': 'http://localhost/nodes/%s/bios/virtualization'
+ % self.node.uuid, 'rel': 'bookmark'}],
'name': 'virtualization', 'value': 'on'}}
self.assertEqual(expected_json, ret)
@@ -6742,6 +6769,88 @@ class TestBIOS(test_api_base.BaseApiTest):
self.assertIn("fake_setting", ret.json['error_message'])
self.assertNotIn(self.node.id, ret.json['error_message'])
+ def test_get_all_bios_with_detail(self):
+ ret = self.get_json('/nodes/%s/bios?detail=True' % self.node.uuid,
+ headers={api_base.Version.string: self.version})
+
+ expected_json = [
+ {'allowable_values': ['on', 'off'],
+ 'attribute_type': 'Enumeration',
+ 'created_at': ret['bios'][0]['created_at'],
+ 'links': [
+ {'href': 'http://localhost/v1/nodes/%s/bios/virtualization'
+ % self.node.uuid, 'rel': 'self'},
+ {'href': 'http://localhost/nodes/%s/bios/virtualization'
+ % self.node.uuid, 'rel': 'bookmark'}],
+ 'lower_bound': None,
+ 'max_length': None,
+ 'min_length': None,
+ 'name': 'virtualization',
+ 'read_only': False,
+ 'reset_required': True,
+ 'unique': False,
+ 'updated_at': None,
+ 'upper_bound': None,
+ 'value': 'on'}]
+
+ self.assertEqual({'bios': expected_json}, ret)
+
+ def test_get_all_bios_detail_false(self):
+ ret = self.get_json('/nodes/%s/bios?detail=False' % self.node.uuid,
+ headers={api_base.Version.string: self.version})
+
+ expected_json = [
+ {'created_at': ret['bios'][0]['created_at'],
+ 'updated_at': ret['bios'][0]['updated_at'],
+ 'links': [
+ {'href': 'http://localhost/v1/nodes/%s/bios/virtualization'
+ % self.node.uuid, 'rel': 'self'},
+ {'href': 'http://localhost/nodes/%s/bios/virtualization'
+ % self.node.uuid, 'rel': 'bookmark'}],
+ 'name': 'virtualization', 'value': 'on'}]
+ self.assertEqual({'bios': expected_json}, ret)
+
+ def test_get_all_bios_detail_old_version(self):
+ ret = self.get_json('/nodes/%s/bios?detail=True' % self.node.uuid,
+ headers={api_base.Version.string: "1.73"},
+ expect_errors=True)
+
+ self.assertEqual(http_client.BAD_REQUEST, ret.status_int)
+
+ def test_get_bios_fields_old_version(self):
+ ret = self.get_json('/nodes/%s/bios?fields=name,read_only'
+ % self.node.uuid,
+ headers={api_base.Version.string: "1.73"},
+ expect_errors=True)
+
+ self.assertEqual(http_client.BAD_REQUEST, ret.status_int)
+
+ def test_get_bios_detail_and_fields(self):
+ ret = self.get_json('/nodes/%s/bios?detail=True?fields=name,read_only'
+ % self.node.uuid,
+ headers={api_base.Version.string: "1.74"},
+ expect_errors=True)
+
+ self.assertEqual(http_client.BAD_REQUEST, ret.status_int)
+
+ def test_get_bios_fields(self):
+ ret = self.get_json('/nodes/%s/bios?fields=name,read_only'
+ % self.node.uuid,
+ headers={api_base.Version.string: self.version})
+
+ expected_json = [
+ {'created_at': ret['bios'][0]['created_at'],
+ 'links': [
+ {'href': 'http://localhost/v1/nodes/%s/bios/virtualization'
+ % self.node.uuid, 'rel': 'self'},
+ {'href': 'http://localhost/nodes/%s/bios/virtualization'
+ % self.node.uuid, 'rel': 'bookmark'}],
+ 'name': 'virtualization',
+ 'read_only': False,
+ 'updated_at': None}]
+
+ self.assertEqual({'bios': expected_json}, ret)
+
class TestTraits(test_api_base.BaseApiTest):
diff --git a/ironic/tests/unit/common/test_release_mappings.py b/ironic/tests/unit/common/test_release_mappings.py
index b5adfa060..db2d37c60 100644
--- a/ironic/tests/unit/common/test_release_mappings.py
+++ b/ironic/tests/unit/common/test_release_mappings.py
@@ -85,7 +85,7 @@ class ReleaseMappingsTestCase(base.TestCase):
self.assertIn('master', release_mappings.RELEASE_MAPPING)
model_names = set((s.__name__ for s in models.Base.__subclasses__()))
exceptions = set(['NodeTag', 'ConductorHardwareInterfaces',
- 'NodeTrait', 'BIOSSetting', 'DeployTemplateStep'])
+ 'NodeTrait', 'DeployTemplateStep'])
# NOTE(xek): As a rule, all models which can be changed between
# releases or are sent through RPC should have their counterpart
# versioned objects.
diff --git a/ironic/tests/unit/db/sqlalchemy/test_migrations.py b/ironic/tests/unit/db/sqlalchemy/test_migrations.py
index 7a2641323..3b81e3b92 100644
--- a/ironic/tests/unit/db/sqlalchemy/test_migrations.py
+++ b/ironic/tests/unit/db/sqlalchemy/test_migrations.py
@@ -705,6 +705,40 @@ class MigrationCheckersMixin(object):
bios_settings.c.name == setting['name'])).execute().first()
self.assertEqual('on', setting['value'])
+ def _check_2bbd96b6ccb9(self, engine, data):
+ bios_settings = db_utils.get_table(engine, 'bios_settings')
+ col_names = [column.name for column in bios_settings.c]
+ self.assertIn('attribute_type', col_names)
+ self.assertIn('allowable_values', col_names)
+ self.assertIn('lower_bound', col_names)
+ self.assertIn('max_length', col_names)
+ self.assertIn('min_length', col_names)
+ self.assertIn('read_only', col_names)
+ self.assertIn('reset_required', col_names)
+ self.assertIn('unique', col_names)
+ self.assertIn('upper_bound', col_names)
+ self.assertIsInstance(bios_settings.c.attribute_type.type,
+ sqlalchemy.types.String)
+ self.assertIsInstance(bios_settings.c.allowable_values.type,
+ sqlalchemy.types.TEXT)
+ self.assertIsInstance(bios_settings.c.lower_bound.type,
+ sqlalchemy.types.Integer)
+ self.assertIsInstance(bios_settings.c.max_length.type,
+ sqlalchemy.types.Integer)
+ self.assertIsInstance(bios_settings.c.min_length.type,
+ sqlalchemy.types.Integer)
+ self.assertIsInstance(bios_settings.c.read_only.type,
+ (sqlalchemy.types.Boolean,
+ sqlalchemy.types.Integer))
+ self.assertIsInstance(bios_settings.c.reset_required.type,
+ (sqlalchemy.types.Boolean,
+ sqlalchemy.types.Integer))
+ self.assertIsInstance(bios_settings.c.unique.type,
+ (sqlalchemy.types.Boolean,
+ sqlalchemy.types.Integer))
+ self.assertIsInstance(bios_settings.c.upper_bound.type,
+ sqlalchemy.types.Integer)
+
def _check_2d13bc3d6bba(self, engine, data):
nodes = db_utils.get_table(engine, 'nodes')
col_names = [column.name for column in nodes.c]
diff --git a/ironic/tests/unit/db/test_bios_settings.py b/ironic/tests/unit/db/test_bios_settings.py
index a13f516a3..9cb077e07 100644
--- a/ironic/tests/unit/db/test_bios_settings.py
+++ b/ironic/tests/unit/db/test_bios_settings.py
@@ -29,7 +29,7 @@ class DbBIOSSettingTestCase(base.DbTestCase):
self.assertEqual(result['node_id'], self.node.id)
self.assertEqual(result['name'], 'virtualization')
self.assertEqual(result['value'], 'on')
- self.assertEqual(result['version'], '1.0')
+ self.assertEqual(result['version'], '1.1')
def test_get_bios_setting_node_not_exist(self):
self.assertRaises(exception.NodeNotFound,
@@ -50,7 +50,7 @@ class DbBIOSSettingTestCase(base.DbTestCase):
self.assertEqual(result[0]['node_id'], self.node.id)
self.assertEqual(result[0]['name'], 'virtualization')
self.assertEqual(result[0]['value'], 'on')
- self.assertEqual(result[0]['version'], '1.0')
+ self.assertEqual(result[0]['version'], '1.1')
self.assertEqual(len(result), 1)
def test_get_bios_setting_list_node_not_exist(self):
@@ -61,7 +61,7 @@ class DbBIOSSettingTestCase(base.DbTestCase):
def test_create_bios_setting_list(self):
settings = db_utils.get_test_bios_setting_setting_list()
result = self.dbapi.create_bios_setting_list(
- self.node.id, settings, '1.0')
+ self.node.id, settings, '1.1')
self.assertCountEqual(['virtualization', 'hyperthread', 'numlock'],
[setting.name for setting in result])
self.assertCountEqual(['on', 'enabled', 'off'],
@@ -69,7 +69,7 @@ class DbBIOSSettingTestCase(base.DbTestCase):
def test_create_bios_setting_list_duplicate(self):
settings = db_utils.get_test_bios_setting_setting_list()
- self.dbapi.create_bios_setting_list(self.node.id, settings, '1.0')
+ self.dbapi.create_bios_setting_list(self.node.id, settings, '1.1')
self.assertRaises(exception.BIOSSettingAlreadyExists,
self.dbapi.create_bios_setting_list,
self.node.id, settings, '1.0')
@@ -81,18 +81,18 @@ class DbBIOSSettingTestCase(base.DbTestCase):
def test_update_bios_setting_list(self):
settings = db_utils.get_test_bios_setting_setting_list()
- self.dbapi.create_bios_setting_list(self.node.id, settings, '1.0')
+ self.dbapi.create_bios_setting_list(self.node.id, settings, '1.1')
settings = [{'name': 'virtualization', 'value': 'off'},
{'name': 'hyperthread', 'value': 'disabled'},
{'name': 'numlock', 'value': 'on'}]
result = self.dbapi.update_bios_setting_list(
- self.node.id, settings, '1.0')
+ self.node.id, settings, '1.1')
self.assertCountEqual(['off', 'disabled', 'on'],
[setting.value for setting in result])
def test_update_bios_setting_list_setting_not_exist(self):
settings = db_utils.get_test_bios_setting_setting_list()
- self.dbapi.create_bios_setting_list(self.node.id, settings, '1.0')
+ self.dbapi.create_bios_setting_list(self.node.id, settings, '1.1')
for setting in settings:
setting['name'] = 'bios_name'
self.assertRaises(exception.BIOSSettingNotFound,
@@ -106,7 +106,7 @@ class DbBIOSSettingTestCase(base.DbTestCase):
def test_delete_bios_setting_list(self):
settings = db_utils.get_test_bios_setting_setting_list()
- self.dbapi.create_bios_setting_list(self.node.id, settings, '1.0')
+ self.dbapi.create_bios_setting_list(self.node.id, settings, '1.1')
name_list = [setting['name'] for setting in settings]
self.dbapi.delete_bios_setting_list(self.node.id, name_list)
self.assertRaises(exception.BIOSSettingNotFound,
@@ -126,7 +126,7 @@ class DbBIOSSettingTestCase(base.DbTestCase):
def test_delete_bios_setting_list_setting_not_exist(self):
settings = db_utils.get_test_bios_setting_setting_list()
- self.dbapi.create_bios_setting_list(self.node.id, settings, '1.0')
+ self.dbapi.create_bios_setting_list(self.node.id, settings, '1.1')
self.assertRaises(exception.BIOSSettingListNotFound,
self.dbapi.delete_bios_setting_list,
self.node.id, ['fake-bios-option'])
diff --git a/ironic/tests/unit/db/utils.py b/ironic/tests/unit/db/utils.py
index bf025d6af..cb8e55338 100644
--- a/ironic/tests/unit/db/utils.py
+++ b/ironic/tests/unit/db/utils.py
@@ -566,7 +566,12 @@ def create_test_bios_setting(**kw):
node_id = bios_setting['node_id']
version = bios_setting['version']
settings = [{'name': bios_setting['name'],
- 'value': bios_setting['value']}]
+ 'value': bios_setting['value'],
+ 'attribute_type': bios_setting['attribute_type'],
+ 'allowable_values': bios_setting['allowable_values'],
+ 'read_only': bios_setting['read_only'],
+ 'reset_required': bios_setting['reset_required'],
+ 'unique': bios_setting['unique']}]
return dbapi.create_bios_setting_list(node_id, settings, version)[0]
@@ -575,6 +580,15 @@ def get_test_bios_setting(**kw):
'node_id': kw.get('node_id', '123'),
'name': kw.get('name', 'virtualization'),
'value': kw.get('value', 'on'),
+ 'attribute_type': kw.get('attribute_type', 'Enumeration'),
+ 'allowable_values': kw.get('allowable_values', ['on', 'off']),
+ 'lower_bound': kw.get('lower_bound', None),
+ 'max_length': kw.get('max_length', None),
+ 'min_length': kw.get('max_length', None),
+ 'read_only': kw.get('read_only', False),
+ 'reset_required': kw.get('reset_required', True),
+ 'unique': kw.get('unique', False),
+ 'upper_bound': kw.get('upper_bound', None),
'version': kw.get('version', bios.BIOSSetting.VERSION),
'created_at': kw.get('created_at'),
'updated_at': kw.get('updated_at'),
diff --git a/ironic/tests/unit/objects/test_bios.py b/ironic/tests/unit/objects/test_bios.py
index 57538fbbf..5f4d8b999 100644
--- a/ironic/tests/unit/objects/test_bios.py
+++ b/ironic/tests/unit/objects/test_bios.py
@@ -42,6 +42,15 @@ class TestBIOSSettingObject(db_base.DbTestCase, obj_utils.SchemasTestMixIn):
self.assertEqual(self.bios_setting['node_id'], bios_obj.node_id)
self.assertEqual(self.bios_setting['name'], bios_obj.name)
self.assertEqual(self.bios_setting['value'], bios_obj.value)
+ self.assertEqual(self.bios_setting['attribute_type'],
+ bios_obj.attribute_type)
+ self.assertEqual(self.bios_setting['allowable_values'],
+ bios_obj.allowable_values)
+ self.assertEqual(self.bios_setting['reset_required'],
+ bios_obj.reset_required)
+ self.assertEqual(self.bios_setting['read_only'],
+ bios_obj.read_only)
+ self.assertEqual(self.bios_setting['unique'], bios_obj.unique)
@mock.patch.object(dbapi.IMPL, 'get_bios_setting_list', autospec=True)
def test_get_by_node_id(self, mock_get_setting_list):
@@ -67,9 +76,22 @@ class TestBIOSSettingObject(db_base.DbTestCase, obj_utils.SchemasTestMixIn):
fake_call_args = {'node_id': self.bios_setting['node_id'],
'name': self.bios_setting['name'],
'value': self.bios_setting['value'],
+ 'attribute_type':
+ self.bios_setting['attribute_type'],
+ 'allowable_values':
+ self.bios_setting['allowable_values'],
+ 'read_only': self.bios_setting['read_only'],
+ 'reset_required':
+ self.bios_setting['reset_required'],
+ 'unique': self.bios_setting['unique'],
'version': self.bios_setting['version']}
- setting = [{'name': self.bios_setting['name'],
- 'value': self.bios_setting['value']}]
+ setting = [{'name': 'virtualization', 'value': 'on', 'attribute_type':
+ 'Enumeration', 'allowable_values': ['on', 'off'],
+ 'lower_bound': None, 'max_length': None,
+ 'min_length': None, 'read_only': False,
+ 'reset_required': True, 'unique': False,
+ 'upper_bound': None}]
+
bios_obj = objects.BIOSSetting(context=self.context,
**fake_call_args)
mock_create_list.return_value = [self.bios_setting]
@@ -81,6 +103,15 @@ class TestBIOSSettingObject(db_base.DbTestCase, obj_utils.SchemasTestMixIn):
self.assertEqual(self.bios_setting['node_id'], bios_obj.node_id)
self.assertEqual(self.bios_setting['name'], bios_obj.name)
self.assertEqual(self.bios_setting['value'], bios_obj.value)
+ self.assertEqual(self.bios_setting['attribute_type'],
+ bios_obj.attribute_type)
+ self.assertEqual(self.bios_setting['allowable_values'],
+ bios_obj.allowable_values)
+ self.assertEqual(self.bios_setting['read_only'],
+ bios_obj.read_only)
+ self.assertEqual(self.bios_setting['reset_required'],
+ bios_obj.reset_required)
+ self.assertEqual(self.bios_setting['unique'], bios_obj.unique)
@mock.patch.object(dbapi.IMPL, 'update_bios_setting_list', autospec=True)
def test_save(self, mock_update_list):
@@ -89,7 +120,12 @@ class TestBIOSSettingObject(db_base.DbTestCase, obj_utils.SchemasTestMixIn):
'value': self.bios_setting['value'],
'version': self.bios_setting['version']}
setting = [{'name': self.bios_setting['name'],
- 'value': self.bios_setting['value']}]
+ 'value': self.bios_setting['value'],
+ 'attribute_type': None, 'allowable_values': None,
+ 'lower_bound': None, 'max_length': None,
+ 'min_length': None, 'read_only': None,
+ 'reset_required': None, 'unique': None,
+ 'upper_bound': None}]
bios_obj = objects.BIOSSetting(context=self.context,
**fake_call_args)
mock_update_list.return_value = [self.bios_setting]
@@ -111,7 +147,7 @@ class TestBIOSSettingObject(db_base.DbTestCase, obj_utils.SchemasTestMixIn):
bios_obj_list = objects.BIOSSettingList.create(
self.context, self.node_id, settings)
- mock_create_list.assert_called_once_with(self.node_id, settings, '1.0')
+ mock_create_list.assert_called_once_with(self.node_id, settings, '1.1')
self.assertEqual(self.context, bios_obj_list._context)
self.assertEqual(2, len(bios_obj_list))
self.assertEqual(self.bios_setting['node_id'],
@@ -120,7 +156,6 @@ class TestBIOSSettingObject(db_base.DbTestCase, obj_utils.SchemasTestMixIn):
self.assertEqual(self.bios_setting['value'], bios_obj_list[0].value)
self.assertEqual(bios_setting2['node_id'], bios_obj_list[1].node_id)
self.assertEqual(bios_setting2['name'], bios_obj_list[1].name)
- self.assertEqual(bios_setting2['value'], bios_obj_list[1].value)
@mock.patch.object(dbapi.IMPL, 'update_bios_setting_list', autospec=True)
def test_list_save(self, mock_update_list):
@@ -131,7 +166,7 @@ class TestBIOSSettingObject(db_base.DbTestCase, obj_utils.SchemasTestMixIn):
bios_obj_list = objects.BIOSSettingList.save(
self.context, self.node_id, settings)
- mock_update_list.assert_called_once_with(self.node_id, settings, '1.0')
+ mock_update_list.assert_called_once_with(self.node_id, settings, '1.1')
self.assertEqual(self.context, bios_obj_list._context)
self.assertEqual(2, len(bios_obj_list))
self.assertEqual(self.bios_setting['node_id'],
@@ -189,8 +224,7 @@ class TestBIOSSettingObject(db_base.DbTestCase, obj_utils.SchemasTestMixIn):
objects.BIOSSettingList.sync_node_setting(self.ctxt, node.id,
settings))
- expected_delete = [{'name': bios_obj_1.name,
- 'value': bios_obj_1.value}]
+ expected_delete = [{'name': 'virtualization', 'value': 'on'}]
self.assertEqual(create, settings[:2])
self.assertEqual(update, [])
self.assertEqual(delete, expected_delete)
diff --git a/ironic/tests/unit/objects/test_objects.py b/ironic/tests/unit/objects/test_objects.py
index 7b7788933..4e38e123d 100644
--- a/ironic/tests/unit/objects/test_objects.py
+++ b/ironic/tests/unit/objects/test_objects.py
@@ -711,7 +711,7 @@ expected_object_fingerprints = {
'VolumeTargetCRUDPayload': '1.0-30dcc4735512c104a3a36a2ae1e2aeb2',
'Trait': '1.0-3f26cb70c8a10a3807d64c219453e347',
'TraitList': '1.0-33a2e1bb91ad4082f9f63429b77c1244',
- 'BIOSSetting': '1.0-fd4a791dc2139a7cc21cefbbaedfd9e7',
+ 'BIOSSetting': '1.1-1137db88675a4e2d7f7bcc3a0d52345a',
'BIOSSettingList': '1.0-33a2e1bb91ad4082f9f63429b77c1244',
'Allocation': '1.1-38937f2854722f1057ec667b12878708',
'AllocationCRUDNotification': '1.0-59acc533c11d306f149846f922739c15',
diff --git a/releasenotes/notes/bios-registry-support-e7fd62908e9c222d.yaml b/releasenotes/notes/bios-registry-support-e7fd62908e9c222d.yaml
new file mode 100644
index 000000000..adb49983e
--- /dev/null
+++ b/releasenotes/notes/bios-registry-support-e7fd62908e9c222d.yaml
@@ -0,0 +1,8 @@
+---
+features:
+ - |
+ Provide the registry fields in the BIOS setting API and in the BIOS setting
+ list when detail is requested. Also added fields selector to query API.
+ See `story
+ 2008571 <https://storyboard.openstack.org/#!/story/2008571>`_.
+