Merge "Introduce BIOS API"
This commit is contained in:
commit
acc27a1b15
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
Adds support for the BIOS resource to the library.
|
|
@ -20,3 +20,10 @@ class ActionField(base.CompositeField):
|
|||
class ResetActionField(ActionField):
|
||||
allowed_values = base.Field('ResetType@Redfish.AllowableValues',
|
||||
adapter=list)
|
||||
|
||||
|
||||
class IdRefField(base.CompositeField):
|
||||
"""Reference to the resource for updating settings"""
|
||||
|
||||
resource_uri = base.Field('@odata.id')
|
||||
"""The unique identifier for a resource"""
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
# 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.
|
||||
|
||||
# This is referred from Redfish standard schema.
|
||||
# http://redfish.dmtf.org/schemas/v1/Settings.v1_0_0.json
|
||||
|
||||
|
||||
from sushy.resources import base
|
||||
from sushy.resources import common
|
||||
|
||||
|
||||
class MessageListField(base.ListField):
|
||||
"""List of messages with details of settings update status"""
|
||||
|
||||
message_id = base.Field('MessageId', required=True)
|
||||
"""The key for this message which can be used
|
||||
to look up the message in a message registry
|
||||
"""
|
||||
|
||||
message = base.Field('Message')
|
||||
"""Human readable message, if provided"""
|
||||
|
||||
severity = base.Field('Severity')
|
||||
"""Severity of the error"""
|
||||
|
||||
resolution = base.Field('Resolution')
|
||||
"""Used to provide suggestions on how to resolve
|
||||
the situation that caused the error
|
||||
"""
|
||||
|
||||
_related_properties = base.Field('RelatedProperties')
|
||||
"""List of properties described by the message"""
|
||||
|
||||
message_args = base.Field('MessageArgs')
|
||||
"""List of message substitution arguments for the message
|
||||
referenced by `message_id` from the message registry
|
||||
"""
|
||||
|
||||
|
||||
class SettingsField(base.CompositeField):
|
||||
"""The settings of a resource
|
||||
|
||||
Represents the future state and configuration of the resource. The
|
||||
field is added to resources that support future state and
|
||||
configuration.
|
||||
|
||||
This field includes several properties to help clients monitor when
|
||||
the resource is consumed by the service and determine the results of
|
||||
applying the values, which may or may not have been successful.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(SettingsField, self).__init__(path="@Redfish.Settings")
|
||||
|
||||
time = base.Field('Time')
|
||||
"""Indicates the time the settings were applied to the server"""
|
||||
|
||||
_etag = base.Field('ETag')
|
||||
"""The ETag of the resource to which the settings were applied,
|
||||
after the application
|
||||
"""
|
||||
|
||||
_settings_object_idref = common.IdRefField("SettingsObject")
|
||||
"""Reference to the resource the client may PUT/PATCH in order
|
||||
to change this resource
|
||||
"""
|
||||
|
||||
messages = MessageListField("Messages")
|
||||
"""Represents the results of the last time the values of the Settings
|
||||
resource were applied to the server"""
|
||||
|
||||
def commit(self, connector, value, etag=None):
|
||||
"""Commits new settings values
|
||||
|
||||
The new values will be applied when the system or a service
|
||||
restarts.
|
||||
|
||||
:param connector: A Connector instance
|
||||
:param value: Value representing JSON whose structure is specific
|
||||
to each resource and the caller must format it correctly
|
||||
:param etag: Optional ETag of resource version to update. If
|
||||
this ETag is provided and it does not match on server, then
|
||||
the new values will not be committed
|
||||
"""
|
||||
|
||||
connector.patch(self.resource_uri,
|
||||
data=value,
|
||||
headers={'If-Match': etag} if etag else None)
|
||||
|
||||
@property
|
||||
def resource_uri(self):
|
||||
return self._settings_object_idref.resource_uri
|
|
@ -0,0 +1,162 @@
|
|||
# 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.
|
||||
|
||||
# This is referred from Redfish standard schema.
|
||||
# https://redfish.dmtf.org/schemas/Bios.v1_0_3.json
|
||||
|
||||
import logging
|
||||
|
||||
from sushy import exceptions
|
||||
from sushy.resources import base
|
||||
from sushy.resources import common
|
||||
from sushy.resources import settings
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ActionsField(base.CompositeField):
|
||||
change_password = common.ActionField('#Bios.ChangePassword')
|
||||
reset_bios = common.ActionField('#Bios.ResetBios')
|
||||
|
||||
|
||||
class Bios(base.ResourceBase):
|
||||
|
||||
identity = base.Field('Id', required=True)
|
||||
"""The Bios resource identity string"""
|
||||
|
||||
name = base.Field('Name')
|
||||
"""The name of the resource"""
|
||||
|
||||
description = base.Field('Description')
|
||||
"""Human-readable description of the BIOS resource"""
|
||||
|
||||
attribute_registry = base.Field('AttributeRegistry')
|
||||
"""The Resource ID of the Attribute Registry
|
||||
for the BIOS Attributes resource
|
||||
"""
|
||||
|
||||
_settings = settings.SettingsField()
|
||||
"""Results of last BIOS attribute update"""
|
||||
|
||||
attributes = base.Field('Attributes')
|
||||
"""Vendor-specific key-value dict of effective BIOS attributes
|
||||
|
||||
Attributes cannot be updated directly.
|
||||
To update use :py:func:`~set_attribute` or :py:func:`~set_attributes`
|
||||
"""
|
||||
|
||||
_actions = ActionsField('Actions')
|
||||
|
||||
_etag = base.Field('@odata.etag')
|
||||
|
||||
_pending_settings_resource = None
|
||||
|
||||
@property
|
||||
def pending_attributes(self):
|
||||
"""Pending BIOS attributes
|
||||
|
||||
BIOS attributes that have been comitted to the system,
|
||||
but for them to take effect system restart is necessary
|
||||
"""
|
||||
|
||||
if not self._pending_settings_resource:
|
||||
self._pending_settings_resource = Bios(
|
||||
self._conn,
|
||||
self._settings.resource_uri,
|
||||
redfish_version=self.redfish_version)
|
||||
self._pending_settings_resource.refresh(force=False)
|
||||
return self._pending_settings_resource.attributes
|
||||
|
||||
def set_attribute(self, key, value):
|
||||
"""Update an attribute
|
||||
|
||||
Attribute update is not immediate but requires system restart.
|
||||
Committed attributes can be checked at :py:attr:`~pending_attributes`
|
||||
property
|
||||
|
||||
:param key: Attribute name
|
||||
:param value: Attribute value
|
||||
"""
|
||||
self.set_attributes({key: value})
|
||||
|
||||
def set_attributes(self, value):
|
||||
"""Update many attributes at once
|
||||
|
||||
Attribute update is not immediate but requires system restart.
|
||||
Committed attributes can be checked at :py:attr:`~pending_attributes`
|
||||
property
|
||||
|
||||
:param value: Key-value pairs for attribute name and value
|
||||
"""
|
||||
self._settings.commit(self._conn,
|
||||
{'Attributes': value},
|
||||
self._etag)
|
||||
if self._pending_settings_resource:
|
||||
self._pending_settings_resource.invalidate()
|
||||
|
||||
def _get_reset_bios_action_element(self):
|
||||
actions = self._actions
|
||||
|
||||
if not actions:
|
||||
raise exceptions.MissingAttributeError(attribute="Actions",
|
||||
resource=self._path)
|
||||
|
||||
reset_bios_action = actions.reset_bios
|
||||
|
||||
if not reset_bios_action:
|
||||
raise exceptions.MissingActionError(action='#Bios.ResetBios',
|
||||
resource=self._path)
|
||||
return reset_bios_action
|
||||
|
||||
def _get_change_password_element(self):
|
||||
actions = self._actions
|
||||
|
||||
if not actions:
|
||||
raise exceptions.MissingAttributeError(attribute="Actions",
|
||||
resource=self._path)
|
||||
|
||||
change_password_action = actions.change_password
|
||||
|
||||
if not change_password_action:
|
||||
raise exceptions.MissingActionError(action='#Bios.ChangePassword',
|
||||
resource=self._path)
|
||||
return change_password_action
|
||||
|
||||
def reset_bios(self):
|
||||
"""Reset the BIOS attributes to default"""
|
||||
|
||||
target_uri = self._get_reset_bios_action_element().target_uri
|
||||
|
||||
LOG.debug('Resetting BIOS attributes %s ...', self.identity)
|
||||
self._conn.post(target_uri)
|
||||
LOG.info('BIOS attributes %s is being reset', self.identity)
|
||||
|
||||
def change_password(self, new_password, old_password, password_name):
|
||||
"""Change BIOS password"""
|
||||
|
||||
target_uri = self._get_change_password_element().target_uri
|
||||
|
||||
LOG.debug('Changing BIOS password %s ...', self.identity)
|
||||
self._conn.post(target_uri, data={'NewPassword': new_password,
|
||||
'OldPassword': old_password,
|
||||
'PasswordName': password_name})
|
||||
LOG.info('BIOS password %s is being changed', self.identity)
|
||||
|
||||
def _do_refresh(self, force=False):
|
||||
"""Do custom resource specific refresh activities
|
||||
|
||||
On refresh, all sub-resources are marked as stale, i.e.
|
||||
greedy-refresh not done for them unless forced by ``force``
|
||||
argument.
|
||||
"""
|
||||
if self._pending_settings_resource is not None:
|
||||
self._pending_settings_resource.invalidate(force)
|
|
@ -18,6 +18,7 @@ import logging
|
|||
from sushy import exceptions
|
||||
from sushy.resources import base
|
||||
from sushy.resources import common
|
||||
from sushy.resources.system import bios
|
||||
from sushy.resources.system import constants as sys_cons
|
||||
from sushy.resources.system import ethernet_interface
|
||||
from sushy.resources.system import mappings as sys_maps
|
||||
|
@ -130,6 +131,8 @@ class System(base.ResourceBase):
|
|||
|
||||
_ethernet_interfaces = None
|
||||
|
||||
_bios = None
|
||||
|
||||
def __init__(self, connector, identity, redfish_version=None):
|
||||
"""A class representing a ComputerSystem
|
||||
|
||||
|
@ -289,6 +292,23 @@ class System(base.ResourceBase):
|
|||
self._ethernet_interfaces.refresh(force=False)
|
||||
return self._ethernet_interfaces
|
||||
|
||||
@property
|
||||
def bios(self):
|
||||
"""Property to reference `Bios` instance
|
||||
|
||||
It is set once when the first time it is queried. On refresh,
|
||||
this property is marked as stale (greedy-refresh not done).
|
||||
Here the actual refresh of the sub-resource happens, if stale.
|
||||
"""
|
||||
if self._bios is None:
|
||||
self._bios = bios.Bios(
|
||||
self._conn,
|
||||
utils.get_sub_resource_path_by(self, 'Bios'),
|
||||
redfish_version=self.redfish_version)
|
||||
|
||||
self._bios.refresh(force=False)
|
||||
return self._bios
|
||||
|
||||
def _do_refresh(self, force=False):
|
||||
"""Do custom resource specific refresh activities
|
||||
|
||||
|
@ -300,6 +320,8 @@ class System(base.ResourceBase):
|
|||
self._processors.invalidate(force)
|
||||
if self._ethernet_interfaces is not None:
|
||||
self._ethernet_interfaces.invalidate(force)
|
||||
if self._bios is not None:
|
||||
self._bios.invalidate(force)
|
||||
|
||||
|
||||
class SystemCollection(base.ResourceCollectionBase):
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
"@odata.type": "#Bios.v1_0_0.Bios",
|
||||
"Id": "BIOS",
|
||||
"Name": "BIOS Configuration Current Settings",
|
||||
"AttributeRegistry": "BiosAttributeRegistryP89.v1_0_0",
|
||||
"Attributes": {
|
||||
"AdminPhone": "",
|
||||
"BootMode": "Uefi",
|
||||
"EmbeddedSata": "Raid",
|
||||
"NicBoot1": "NetworkBoot",
|
||||
"NicBoot2": "Disabled",
|
||||
"PowerProfile": "MaxPerf",
|
||||
"ProcCoreDisable": 0,
|
||||
"ProcHyperthreading": "Enabled",
|
||||
"ProcTurboMode": "Enabled",
|
||||
"UsbControl": "UsbEnabled"
|
||||
},
|
||||
"@Redfish.Settings": {
|
||||
"@odata.type": "#Settings.v1_0_0.Settings",
|
||||
"ETag": "9234ac83b9700123cc32",
|
||||
"Messages": [
|
||||
{
|
||||
"MessageId": "Base.1.0.SettingsFailed",
|
||||
"RelatedProperties": [
|
||||
"#/Attributes/ProcTurboMode"
|
||||
]
|
||||
}
|
||||
],
|
||||
"SettingsObject": {
|
||||
"@odata.id": "/redfish/v1/Systems/437XR1138R2/BIOS/Settings"
|
||||
},
|
||||
"Time": "2016-03-07T14:44.30-05:00"
|
||||
},
|
||||
"Actions": {
|
||||
"#Bios.ResetBios": {
|
||||
"target": "/redfish/v1/Systems/437XR1138R2/BIOS/Actions/Bios.ResetBios"
|
||||
},
|
||||
"#Bios.ChangePassword": {
|
||||
"target": "/redfish/v1/Systems/437XR1138R2/BIOS/Actions/Bios.ChangePassword"
|
||||
}
|
||||
},
|
||||
"@odata.etag": "123",
|
||||
"@odata.context": "/redfish/v1/$metadata#Bios.Bios",
|
||||
"@odata.id": "/redfish/v1/Systems/437XR1138R2/BIOS"
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"@odata.type": "#Bios.v1_0_0.Bios",
|
||||
"Id": "Settings",
|
||||
"Name": "BIOS Configuration Pending Settings",
|
||||
"AttributeRegistry": "BiosAttributeRegistryP89.v1_0_0",
|
||||
"Attributes": {
|
||||
"AdminPhone": "(404) 555-1212",
|
||||
"BootMode": "Uefi",
|
||||
"EmbeddedSata": "Ahci",
|
||||
"NicBoot1": "NetworkBoot",
|
||||
"NicBoot2": "NetworkBoot",
|
||||
"PowerProfile": "MaxPerf",
|
||||
"ProcCoreDisable": 0,
|
||||
"ProcHyperthreading": "Enabled",
|
||||
"ProcTurboMode": "Disabled",
|
||||
"UsbControl": "UsbEnabled"
|
||||
},
|
||||
"@odata.context": "/redfish/v1/$metadata#Bios.Bios",
|
||||
"@odata.id": "/redfish/v1/Systems/437XR1138R2/BIOS/Settings",
|
||||
"@Redfish.Copyright": "Copyright 2014-2016 Distributed Management Task Force, Inc. (DMTF). For the full DMTF copyright policy, see http://www.dmtf.org/about/policies/copyright."
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"@Redfish.Settings": {
|
||||
"@odata.type": "#Settings.v1_0_0.Settings",
|
||||
"ETag": "9234ac83b9700123cc32",
|
||||
"Messages": [{
|
||||
"MessageId": "Base.1.0.SettingsFailed",
|
||||
"Message": "Settings update failed due to invalid value",
|
||||
"Severity": "High",
|
||||
"Resolution": "Fix the value and try again",
|
||||
"MessageArgs": [
|
||||
"arg1"
|
||||
],
|
||||
"RelatedProperties": [
|
||||
"#/Attributes/ProcTurboMode"
|
||||
]
|
||||
}],
|
||||
"SettingsObject": {
|
||||
"@odata.id": "/redfish/v1/Systems/437XR1138R2/BIOS/Settings"
|
||||
},
|
||||
"Time": "2016-03-07T14:44.30-05:00"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
import json
|
||||
|
||||
import mock
|
||||
|
||||
from sushy import exceptions
|
||||
from sushy.resources.system import bios
|
||||
from sushy.tests.unit import base
|
||||
|
||||
|
||||
class BiosTestCase(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(BiosTestCase, self).setUp()
|
||||
self.conn = mock.Mock()
|
||||
with open('sushy/tests/unit/json_samples/bios.json', 'r') as f:
|
||||
bios_json = json.loads(f.read())
|
||||
with open('sushy/tests/unit/json_samples/bios_settings.json',
|
||||
'r') as f:
|
||||
bios_settings_json = json.loads(f.read())
|
||||
|
||||
self.conn.get.return_value.json.side_effect = [
|
||||
bios_json,
|
||||
bios_settings_json,
|
||||
bios_settings_json]
|
||||
|
||||
self.sys_bios = bios.Bios(
|
||||
self.conn, '/redfish/v1/Systems/437XR1138R2/BIOS',
|
||||
redfish_version='1.0.2')
|
||||
|
||||
def test__parse_attributes(self):
|
||||
self.sys_bios._parse_attributes()
|
||||
self.assertEqual('1.0.2', self.sys_bios.redfish_version)
|
||||
self.assertEqual('BIOS', self.sys_bios.identity)
|
||||
self.assertEqual('BIOS Configuration Current Settings',
|
||||
self.sys_bios.name)
|
||||
self.assertIsNone(self.sys_bios.description)
|
||||
self.assertEqual('123', self.sys_bios._etag)
|
||||
self.assertEqual('BiosAttributeRegistryP89.v1_0_0',
|
||||
self.sys_bios.attribute_registry)
|
||||
self.assertEqual('', self.sys_bios.attributes['AdminPhone'])
|
||||
self.assertEqual('Uefi', self.sys_bios.attributes['BootMode'])
|
||||
self.assertEqual(0, self.sys_bios.attributes['ProcCoreDisable'])
|
||||
# testing here if settings subfield parsed by checking ETag,
|
||||
# other settings fields tested in specific settings test
|
||||
self.assertEqual('9234ac83b9700123cc32',
|
||||
self.sys_bios._settings._etag)
|
||||
self.assertEqual('(404) 555-1212',
|
||||
self.sys_bios.pending_attributes['AdminPhone'])
|
||||
|
||||
def test_set_attribute(self):
|
||||
self.sys_bios.set_attribute('ProcTurboMode', 'Disabled')
|
||||
self.sys_bios._conn.patch.assert_called_once_with(
|
||||
'/redfish/v1/Systems/437XR1138R2/BIOS/Settings',
|
||||
data={'Attributes': {'ProcTurboMode': 'Disabled'}},
|
||||
headers={'If-Match': '123'})
|
||||
|
||||
def test_set_attribute_on_refresh(self):
|
||||
# make it to instantiate pending attributes
|
||||
self.sys_bios.pending_attributes
|
||||
self.sys_bios.set_attribute('ProcTurboMode', 'Disabled')
|
||||
self.assertTrue(self.sys_bios._pending_settings_resource._is_stale)
|
||||
# make it to refresh pending attributes on next retrieval
|
||||
self.sys_bios.pending_attributes
|
||||
self.assertFalse(self.sys_bios._pending_settings_resource._is_stale)
|
||||
|
||||
def test_set_attributes(self):
|
||||
self.sys_bios.set_attributes({'ProcTurboMode': 'Disabled',
|
||||
'UsbControl': 'UsbDisabled'})
|
||||
self.sys_bios._conn.patch.assert_called_once_with(
|
||||
'/redfish/v1/Systems/437XR1138R2/BIOS/Settings',
|
||||
data={'Attributes': {'ProcTurboMode': 'Disabled',
|
||||
'UsbControl': 'UsbDisabled'}},
|
||||
headers={'If-Match': '123'})
|
||||
|
||||
def test_set_attributes_on_refresh(self):
|
||||
# make it to instantiate pending attributes
|
||||
self.sys_bios.pending_attributes
|
||||
self.sys_bios.set_attributes({'ProcTurboMode': 'Disabled',
|
||||
'UsbControl': 'UsbDisabled'})
|
||||
self.assertTrue(self.sys_bios._pending_settings_resource._is_stale)
|
||||
# make it to refresh pending attributes on next retrieval
|
||||
self.sys_bios.pending_attributes
|
||||
self.assertFalse(self.sys_bios._pending_settings_resource._is_stale)
|
||||
|
||||
def test__get_reset_bios_action_element(self):
|
||||
value = self.sys_bios._get_reset_bios_action_element()
|
||||
self.assertEqual('/redfish/v1/Systems/437XR1138R2/BIOS/Actions/'
|
||||
'Bios.ResetBios',
|
||||
value.target_uri)
|
||||
|
||||
def test_reset_bios_missing_action(self):
|
||||
self.sys_bios._actions.reset_bios = None
|
||||
self.assertRaisesRegex(
|
||||
exceptions.MissingActionError, '#Bios.ResetBios',
|
||||
self.sys_bios.reset_bios)
|
||||
|
||||
def test__parse_attributes_missing_reset_bios_target(self):
|
||||
self.sys_bios.json['Actions']['#Bios.ResetBios'].pop(
|
||||
'target')
|
||||
self.assertRaisesRegex(
|
||||
exceptions.MissingAttributeError,
|
||||
'attribute Actions/#Bios.ResetBios/target',
|
||||
self.sys_bios._parse_attributes)
|
||||
|
||||
def test_reset_bios(self):
|
||||
self.sys_bios.reset_bios()
|
||||
self.sys_bios._conn.post.assert_called_once_with(
|
||||
'/redfish/v1/Systems/437XR1138R2/BIOS/Actions/Bios.ResetBios')
|
||||
|
||||
def test__get_change_password_element(self):
|
||||
value = self.sys_bios._get_change_password_element()
|
||||
self.assertEqual("/redfish/v1/Systems/437XR1138R2/BIOS/Actions/"
|
||||
"Bios.ChangePassword",
|
||||
value.target_uri)
|
||||
|
||||
def test_change_password_missing_action(self):
|
||||
self.sys_bios._actions.change_password = None
|
||||
self.assertRaisesRegex(
|
||||
exceptions.MissingActionError, '#Bios.ChangePassword',
|
||||
self.sys_bios.change_password, 'newpassword',
|
||||
'oldpassword',
|
||||
'adminpassword')
|
||||
|
||||
def test__parse_attributes_missing_change_password_target(self):
|
||||
self.sys_bios.json['Actions']['#Bios.ChangePassword'].pop(
|
||||
'target')
|
||||
self.assertRaisesRegex(
|
||||
exceptions.MissingAttributeError,
|
||||
'attribute Actions/#Bios.ChangePassword/target',
|
||||
self.sys_bios._parse_attributes)
|
||||
|
||||
def test_change_password(self):
|
||||
self.sys_bios.change_password('newpassword',
|
||||
'oldpassword',
|
||||
'adminpassword')
|
||||
self.sys_bios._conn.post.assert_called_once_with(
|
||||
'/redfish/v1/Systems/437XR1138R2/BIOS/Actions/Bios.ChangePassword',
|
||||
data={'OldPassword': 'oldpassword',
|
||||
'NewPassword': 'newpassword',
|
||||
'PasswordName': 'adminpassword'})
|
|
@ -19,6 +19,7 @@ import mock
|
|||
|
||||
import sushy
|
||||
from sushy import exceptions
|
||||
from sushy.resources.system import bios
|
||||
from sushy.resources.system import constants as sys_cons
|
||||
from sushy.resources.system import ethernet_interface
|
||||
from sushy.resources.system import mappings as sys_map
|
||||
|
@ -66,6 +67,7 @@ class SystemTestCase(base.TestCase):
|
|||
self.assertEqual("OK", self.sys_inst.memory_summary.health)
|
||||
self.assertIsNone(self.sys_inst._processors)
|
||||
self.assertIsNone(self.sys_inst._ethernet_interfaces)
|
||||
self.assertIsNone(self.sys_inst._bios)
|
||||
|
||||
def test__parse_attributes_missing_actions(self):
|
||||
self.sys_inst.json.pop('Actions')
|
||||
|
@ -379,6 +381,18 @@ class SystemTestCase(base.TestCase):
|
|||
self.assertIsInstance(self.sys_inst._ethernet_interfaces,
|
||||
ethernet_interface.EthernetInterfaceCollection)
|
||||
|
||||
def test_bios(self):
|
||||
self.conn.get.return_value.json.reset_mock()
|
||||
bios_return_value = None
|
||||
with open('sushy/tests/unit/json_samples/bios.json', 'r') as f:
|
||||
bios_return_value = json.loads(f.read())
|
||||
self.conn.get.return_value.json.side_effect = [bios_return_value]
|
||||
|
||||
self.assertIsNone(self.sys_inst._bios)
|
||||
self.assertIsInstance(self.sys_inst.bios, bios.Bios)
|
||||
self.assertEqual('BIOS Configuration Current Settings',
|
||||
self.sys_inst.bios.name)
|
||||
|
||||
|
||||
class SystemCollectionTestCase(base.TestCase):
|
||||
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
# Copyright 2017 Red Hat, Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
import json
|
||||
import mock
|
||||
|
||||
from sushy.resources import settings
|
||||
from sushy.tests.unit import base
|
||||
|
||||
|
||||
class SettingsFieldTestCase(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(SettingsFieldTestCase, self).setUp()
|
||||
with open('sushy/tests/unit/json_samples/settings.json',
|
||||
'r') as f:
|
||||
self.json = json.loads(f.read())
|
||||
|
||||
self.settings = settings.SettingsField()
|
||||
|
||||
def test__load(self):
|
||||
instance = self.settings._load(self.json, mock.Mock())
|
||||
|
||||
self.assertEqual('9234ac83b9700123cc32',
|
||||
instance._etag)
|
||||
self.assertEqual('2016-03-07T14:44.30-05:00',
|
||||
instance.time)
|
||||
self.assertEqual('/redfish/v1/Systems/437XR1138R2/BIOS/Settings',
|
||||
instance._settings_object_idref.resource_uri)
|
||||
self.assertEqual('Base.1.0.SettingsFailed',
|
||||
instance.messages[0].message_id)
|
||||
self.assertEqual('Settings update failed due to invalid value',
|
||||
instance.messages[0].message)
|
||||
self.assertEqual('High',
|
||||
instance.messages[0].severity)
|
||||
self.assertEqual('Fix the value and try again',
|
||||
instance.messages[0].resolution)
|
||||
self.assertEqual('arg1',
|
||||
instance.messages[0].message_args[0])
|
||||
self.assertEqual('#/Attributes/ProcTurboMode',
|
||||
instance.messages[0]._related_properties[0])
|
||||
self.assertEqual('/redfish/v1/Systems/437XR1138R2/BIOS/Settings',
|
||||
instance._settings_object_idref.resource_uri)
|
||||
|
||||
def test_commit(self):
|
||||
conn = mock.Mock()
|
||||
instance = self.settings._load(self.json, conn)
|
||||
instance.commit(conn, {'Attributes': {'key': 'value'}})
|
||||
conn.patch.assert_called_once_with(
|
||||
'/redfish/v1/Systems/437XR1138R2/BIOS/Settings',
|
||||
data={'Attributes': {'key': 'value'}}, headers=None)
|
||||
|
||||
def test_commit_with_etag(self):
|
||||
conn = mock.Mock()
|
||||
instance = self.settings._load(self.json, conn)
|
||||
instance.commit(conn,
|
||||
{'Attributes': {'key': 'value'}},
|
||||
'123')
|
||||
conn.patch.assert_called_once_with(
|
||||
'/redfish/v1/Systems/437XR1138R2/BIOS/Settings',
|
||||
data={'Attributes': {'key': 'value'}},
|
||||
headers={'If-Match': '123'})
|
Loading…
Reference in New Issue