From da78c87db211bc5c98d1da45652dcd8fd90b0e97 Mon Sep 17 00:00:00 2001 From: Imre Farkas Date: Thu, 15 Oct 2015 15:43:02 +0200 Subject: [PATCH] Add support for BIOS configuration Change-Id: I574696e460f08cececc47a69b5c2b090a6cd44a2 --- dracclient/client.py | 43 +- dracclient/resources/bios.py | 340 +++- dracclient/tests/test_client.py | 219 ++- dracclient/tests/utils.py | 26 +- .../wsman_mocks/bios_enumeration-enum-ok.xml | 1495 +++++++++++++++++ .../wsman_mocks/bios_integer-enum-mutable.xml | 36 + .../wsman_mocks/bios_integer-enum-ok.xml | 56 + ...os_service-invoke-set_attributes-error.xml | 20 + .../bios_service-invoke-set_attributes-ok.xml | 19 + .../bios_string-enum-colliding.xml | 53 + .../tests/wsman_mocks/bios_string-enum-ok.xml | 581 +++++++ .../wsman_mocks/bios_string-enum-regexp.xml | 37 + dracclient/utils.py | 23 +- 13 files changed, 2934 insertions(+), 14 deletions(-) create mode 100644 dracclient/tests/wsman_mocks/bios_enumeration-enum-ok.xml create mode 100644 dracclient/tests/wsman_mocks/bios_integer-enum-mutable.xml create mode 100644 dracclient/tests/wsman_mocks/bios_integer-enum-ok.xml create mode 100644 dracclient/tests/wsman_mocks/bios_service-invoke-set_attributes-error.xml create mode 100644 dracclient/tests/wsman_mocks/bios_service-invoke-set_attributes-ok.xml create mode 100644 dracclient/tests/wsman_mocks/bios_string-enum-colliding.xml create mode 100644 dracclient/tests/wsman_mocks/bios_string-enum-ok.xml create mode 100644 dracclient/tests/wsman_mocks/bios_string-enum-regexp.xml diff --git a/dracclient/client.py b/dracclient/client.py index de3f2d5..451b239 100644 --- a/dracclient/client.py +++ b/dracclient/client.py @@ -49,6 +49,7 @@ class DRACClient(object): self._job_mgmt = job.JobManagement(self.client) self._power_mgmt = bios.PowerManagement(self.client) self._boot_mgmt = bios.BootManagement(self.client) + self._bios_cfg = bios.BIOSConfiguration(self.client) def get_power_state(self): """Returns the current power state of the node @@ -116,6 +117,41 @@ class DRACClient(object): return self._boot_mgmt.change_boot_device_order(boot_mode, boot_device_list) + def list_bios_settings(self): + """List the BIOS configuration settings + + :returns: a dictionary with the BIOS settings using its name as the + key. The attributes are either BIOSEnumerableAttribute, + BIOSStringAttribute or BIOSIntegerAttribute objects. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface + """ + return self._bios_cfg.list_bios_settings() + + def set_bios_settings(self, settings): + """Sets the BIOS configuration + + To be more precise, it sets the pending_value parameter for each of the + attributes passed in. For the values to be applied, a config job must + be created and the node must be rebooted. + + :param: settings: a dictionary containing the proposed values, with + each key being the name of attribute and the + value being the proposed value. + :returns: a dictionary containing the commit_needed key with a boolean + value indicating whether a config job must be created for the + values to be applied. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface + :raises: DRACUnexpectedReturnValue on return value mismatch + :raises: InvalidParameterValue on invalid BIOS attribute + """ + return self._bios_cfg.set_bios_settings(settings) + def list_jobs(self, only_unfinished=False): """Returns a list of jobs from the job queue @@ -208,9 +244,11 @@ class DRACClient(object): resource_uri, cim_creation_class_name, cim_name, target, cim_system_creation_class_name, cim_system_name) - def commit_pending_bios_changes(self): + def commit_pending_bios_changes(self, reboot=False): """Applies all pending changes on the BIOS by creating a config job + :param: reboot: indicates whether a RebootJob should be also be + created or not :returns: id of the created job :raises: WSManRequestFailure on request failures :raises: WSManInvalidResponse when receiving invalid response @@ -221,7 +259,8 @@ class DRACClient(object): return self._job_mgmt.create_config_job( resource_uri=uris.DCIM_BIOSService, cim_creation_class_name='DCIM_BIOSService', - cim_name='DCIM:BIOSService', target=self.BIOS_DEVICE_FQDD) + cim_name='DCIM:BIOSService', target=self.BIOS_DEVICE_FQDD, + reboot=reboot) def abandon_pending_bios_changes(self): """Deletes all pending changes on the BIOS diff --git a/dracclient/resources/bios.py b/dracclient/resources/bios.py index eb8a9c3..02853ac 100644 --- a/dracclient/resources/bios.py +++ b/dracclient/resources/bios.py @@ -12,12 +12,17 @@ # under the License. import collections +import logging +import re from dracclient import constants from dracclient import exceptions from dracclient.resources import lifecycle_controller from dracclient.resources import uris from dracclient import utils +from dracclient import wsman + +LOG = logging.getLogger(__name__) POWER_STATES = { '2': constants.POWER_ON, @@ -43,11 +48,10 @@ LC_CONTROLLER_VERSION_12G = (2, 0, 0) BootMode = collections.namedtuple('BootMode', ['id', 'name', 'is_current', 'is_next']) -BootDevice = collections.namedtuple('BootDevice', - ['id', 'boot_mode', - 'current_assigned_sequence', - 'pending_assigned_sequence', - 'bios_boot_string']) +BootDevice = collections.namedtuple( + 'BootDevice', + ['id', 'boot_mode', 'current_assigned_sequence', + 'pending_assigned_sequence', 'bios_boot_string']) class PowerManagement(object): @@ -252,3 +256,329 @@ class BootManagement(object): return utils.get_wsman_resource_attr(drac_boot_device, uris.DCIM_BootSourceSetting, attr_name) + + +class BIOSAttribute(object): + """Generic BIOS attribute class""" + + def __init__(self, name, current_value, pending_value, read_only): + """Creates BIOSAttribute object + + :param name: name of the BIOS attribute + :param current_value: current value of the BIOS attribute + :param pending_value: pending value of the BIOS attribute, reflecting + an unprocessed change (eg. config job not completed) + :param read_only: indicates whether this BIOS attribute can be changed + """ + self.name = name + self.current_value = current_value + self.pending_value = pending_value + self.read_only = read_only + + def __eq__(self, other): + return self.__dict__ == other.__dict__ + + @classmethod + def parse(cls, namespace, bios_attr_xml): + """Parses XML and creates BIOSAttribute object""" + + name = utils.get_wsman_resource_attr( + bios_attr_xml, namespace, 'AttributeName') + current_value = utils.get_wsman_resource_attr( + bios_attr_xml, namespace, 'CurrentValue', nullable=True) + pending_value = utils.get_wsman_resource_attr( + bios_attr_xml, namespace, 'PendingValue', nullable=True) + read_only = utils.get_wsman_resource_attr( + bios_attr_xml, namespace, 'IsReadOnly') + + return cls(name, current_value, pending_value, (read_only == 'true')) + + +class BIOSEnumerableAttribute(BIOSAttribute): + """Enumerable BIOS attribute class""" + + namespace = uris.DCIM_BIOSEnumeration + + def __init__(self, name, current_value, pending_value, read_only, + possible_values): + """Creates BIOSEnumerableAttribute object + + :param name: name of the BIOS attribute + :param current_value: current value of the BIOS attribute + :param pending_value: pending value of the BIOS attribute, reflecting + an unprocessed change (eg. config job not completed) + :param read_only: indicates whether this BIOS attribute can be changed + :param possible_values: list containing the allowed values for the BIOS + attribute + """ + super(BIOSEnumerableAttribute, self).__init__(name, current_value, + pending_value, read_only) + self.possible_values = possible_values + + @classmethod + def parse(cls, bios_attr_xml): + """Parses XML and creates BIOSEnumerableAttribute object""" + + bios_attr = BIOSAttribute.parse(cls.namespace, bios_attr_xml) + possible_values = [attr.text for attr + in utils.find_xml(bios_attr_xml, 'PossibleValues', + cls.namespace, find_all=True)] + + return cls(bios_attr.name, bios_attr.current_value, + bios_attr.pending_value, bios_attr.read_only, + possible_values) + + def validate(self, new_value): + """Validates new value""" + + if str(new_value) not in self.possible_values: + msg = ("Attribute '%(attr)s' cannot be set to value '%(val)s'." + " It must be in %(possible_values)r.") % { + 'attr': self.name, + 'val': new_value, + 'possible_values': self.possible_values} + return msg + + +class BIOSStringAttribute(BIOSAttribute): + """String BIOS attribute class""" + + namespace = uris.DCIM_BIOSString + + def __init__(self, name, current_value, pending_value, read_only, + min_length, max_length, pcre_regex): + """Creates BIOSStringAttribute object + + :param name: name of the BIOS attribute + :param current_value: current value of the BIOS attribute + :param pending_value: pending value of the BIOS attribute, reflecting + an unprocessed change (eg. config job not completed) + :param read_only: indicates whether this BIOS attribute can be changed + :param min_length: minimum length of the string + :param max_length: maximum length of the string + :param pcre_regex: is a PCRE compatible regular expression that the + string must match + """ + super(BIOSStringAttribute, self).__init__(name, current_value, + pending_value, read_only) + self.min_length = min_length + self.max_length = max_length + self.pcre_regex = pcre_regex + + @classmethod + def parse(cls, bios_attr_xml): + """Parses XML and creates BIOSStringAttribute object""" + + bios_attr = BIOSAttribute.parse(cls.namespace, bios_attr_xml) + min_length = int(utils.get_wsman_resource_attr( + bios_attr_xml, cls.namespace, 'MinLength')) + max_length = int(utils.get_wsman_resource_attr( + bios_attr_xml, cls.namespace, 'MaxLength')) + pcre_regex = utils.get_wsman_resource_attr( + bios_attr_xml, cls.namespace, 'ValueExpression', nullable=True) + + return cls(bios_attr.name, bios_attr.current_value, + bios_attr.pending_value, bios_attr.read_only, + min_length, max_length, pcre_regex) + + def validate(self, new_value): + """Validates new value""" + + if self.pcre_regex is not None: + regex = re.compile(self.pcre_regex) + if regex.search(str(new_value)) is None: + msg = ("Attribute '%(attr)s' cannot be set to value '%(val)s.'" + " It must match regex '%(re)s'.") % { + 'attr': self.name, + 'val': new_value, + 're': self.pcre_regex} + return msg + + +class BIOSIntegerAttribute(BIOSAttribute): + """Integer BIOS attribute class""" + + namespace = uris.DCIM_BIOSInteger + + def __init__(self, name, current_value, pending_value, read_only, + lower_bound, upper_bound): + """Creates BIOSIntegerAttribute object + + :param name: name of the BIOS attribute + :param current_value: current value of the BIOS attribute + :param pending_value: pending value of the BIOS attribute, reflecting + an unprocessed change (eg. config job not completed) + :param read_only: indicates whether this BIOS attribute can be changed + :param lower_bound: minimum value for the BIOS attribute + :param upper_bound: maximum value for the BOIS attribute + """ + super(BIOSIntegerAttribute, self).__init__(name, current_value, + pending_value, read_only) + self.lower_bound = lower_bound + self.upper_bound = upper_bound + + @classmethod + def parse(cls, bios_attr_xml): + """Parses XML and creates BIOSIntegerAttribute object""" + + bios_attr = BIOSAttribute.parse(cls.namespace, bios_attr_xml) + lower_bound = utils.get_wsman_resource_attr( + bios_attr_xml, cls.namespace, 'LowerBound') + upper_bound = utils.get_wsman_resource_attr( + bios_attr_xml, cls.namespace, 'UpperBound') + + if bios_attr.current_value: + bios_attr.current_value = int(bios_attr.current_value) + if bios_attr.pending_value: + bios_attr.pending_value = int(bios_attr.pending_value) + + return cls(bios_attr.name, bios_attr.current_value, + bios_attr.pending_value, bios_attr.read_only, + int(lower_bound), int(upper_bound)) + + def validate(self, new_value): + """Validates new value""" + + val = int(new_value) + if val < self.lower_bound or val > self.upper_bound: + msg = ('Attribute %(attr)s cannot be set to value %(val)d.' + ' It must be between %(lower)d and %(upper)d.') % { + 'attr': self.name, + 'val': new_value, + 'lower': self.lower_bound, + 'upper': self.upper_bound} + return msg + + +class BIOSConfiguration(object): + + def __init__(self, client): + """Creates BIOSConfiguration object + + :param client: an instance of WSManClient + """ + self.client = client + + def list_bios_settings(self): + """List the BIOS configuration settings + + :returns: a dictionary with the BIOS settings using its name as the + key. The attributes are either BIOSEnumerableAttribute, + BIOSStringAttribute or BIOSIntegerAttribute objects. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface + """ + + result = {} + namespaces = [(uris.DCIM_BIOSEnumeration, BIOSEnumerableAttribute), + (uris.DCIM_BIOSString, BIOSStringAttribute), + (uris.DCIM_BIOSInteger, BIOSIntegerAttribute)] + for (namespace, attr_cls) in namespaces: + attribs = self._get_config(namespace, attr_cls) + if not set(result).isdisjoint(set(attribs)): + raise exceptions.DRACOperationFailed( + drac_messages=('Colliding attributes %r' % ( + set(result) & set(attribs)))) + result.update(attribs) + return result + + def _get_config(self, resource, attr_cls): + result = {} + + doc = self.client.enumerate(resource) + items = doc.find('.//{%s}Items' % wsman.NS_WSMAN) + + for item in items: + attribute = attr_cls.parse(item) + result[attribute.name] = attribute + + return result + + def set_bios_settings(self, new_settings): + """Sets the BIOS configuration + + To be more precise, it sets the pending_value parameter for each of the + attributes passed in. For the values to be applied, a config job must + be created and the node must be rebooted. + + :param: new_settings: a dictionary containing the proposed values, with + each key being the name of attribute and the + value being the proposed value. + :returns: a dictionary containing the commit_needed key with a boolean + value indicating whether a config job must be created for the + values to be applied. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface + :raises: DRACUnexpectedReturnValue on return value mismatch + :raises: InvalidParameterValue on invalid BIOS attribute + """ + + current_settings = self.list_bios_settings() + unknown_keys = set(new_settings) - set(current_settings) + if unknown_keys: + msg = ('Unknown BIOS attributes found: %(unknown_keys)r' % + {'unknown_keys': unknown_keys}) + raise exceptions.InvalidParameterValue(reason=msg) + + read_only_keys = [] + unchanged_attribs = [] + invalid_attribs_msgs = [] + attrib_names = [] + candidates = set(new_settings) + + for attr in candidates: + if str(new_settings[attr]) == str( + current_settings[attr].current_value): + unchanged_attribs.append(attr) + elif current_settings[attr].read_only: + read_only_keys.append(attr) + else: + validation_msg = current_settings[attr].validate( + new_settings[attr]) + if validation_msg is None: + attrib_names.append(attr) + else: + invalid_attribs_msgs.append(validation_msg) + + if unchanged_attribs: + LOG.warn('Ignoring unchanged BIOS attributes: %r' % + unchanged_attribs) + + if invalid_attribs_msgs or read_only_keys: + if read_only_keys: + read_only_msg = ['Cannot set read-only BIOS attributes: %r.' + % read_only_keys] + else: + read_only_msg = [] + + drac_messages = '\n'.join(invalid_attribs_msgs + read_only_msg) + raise exceptions.DRACOperationFailed( + drac_messages=drac_messages) + + if not attrib_names: + return {'commit_required': False} + + selectors = {'CreationClassName': 'DCIM_BIOSService', + 'Name': 'DCIM:BIOSService', + 'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'DCIM:ComputerSystem'} + properties = {'Target': 'BIOS.Setup.1-1', + 'AttributeName': attrib_names, + 'AttributeValue': [new_settings[attr] for attr + in attrib_names]} + doc = self.client.invoke(uris.DCIM_BIOSService, 'SetAttributes', + selectors, properties) + + # Checking for RebootRequired attribute in the response, which + # indicates whether we need to create a config job and then reboot, so + # that the Lifecycle controller can commit the BIOS config changes that + # have been proposed. + reboot_required = utils.find_xml(doc, 'RebootRequired', + uris.DCIM_BIOSService) + commit_required = (reboot_required.text == 'Yes') + + return {'commit_required': commit_required} diff --git a/dracclient/tests/test_client.py b/dracclient/tests/test_client.py index d62a56c..58d9c8b 100644 --- a/dracclient/tests/test_client.py +++ b/dracclient/tests/test_client.py @@ -11,6 +11,8 @@ # License for the specific language governing permissions and limitations # under the License. +import re + import lxml.etree import mock import requests_mock @@ -189,6 +191,210 @@ class ClientBootManagementTestCase(base.BaseTest): self.drac_client.change_boot_device_order, 'IPL', 'foo') +class ClientBIOSConfigurationTestCase(base.BaseTest): + + def setUp(self): + super(ClientBIOSConfigurationTestCase, self).setUp() + self.drac_client = dracclient.client.DRACClient( + **test_utils.FAKE_ENDPOINT) + + @requests_mock.Mocker() + def test_list_bios_settings(self, mock_requests): + expected_enum_attr = bios.BIOSEnumerableAttribute( + name='MemTest', + read_only=False, + current_value='Disabled', + pending_value=None, + possible_values=['Enabled', 'Disabled']) + expected_string_attr = bios.BIOSStringAttribute( + name='SystemModelName', + read_only=True, + current_value='PowerEdge R320', + pending_value=None, + min_length=0, + max_length=32, + pcre_regex=None) + expected_integer_attr = bios.BIOSIntegerAttribute( + name='Proc1NumCores', + read_only=True, + current_value=8, + pending_value=None, + lower_bound=0, + upper_bound=65535) + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSEnumeration]['ok']}, + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSString]['ok']}, + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSInteger]['ok']}]) + + bios_settings = self.drac_client.list_bios_settings() + + self.assertEqual(103, len(bios_settings)) + # enumerable attribute + self.assertIn('MemTest', bios_settings) + self.assertEqual(expected_enum_attr, bios_settings['MemTest']) + # string attribute + self.assertIn('SystemModelName', bios_settings) + self.assertEqual(expected_string_attr, + bios_settings['SystemModelName']) + # integer attribute + self.assertIn('Proc1NumCores', bios_settings) + self.assertEqual(expected_integer_attr, bios_settings['Proc1NumCores']) + + @requests_mock.Mocker() + def test_list_bios_settings_with_colliding_attrs(self, mock_requests): + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSEnumeration]['ok']}, + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSString]['colliding']}, + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSInteger]['ok']}]) + + self.assertRaises(exceptions.DRACOperationFailed, + self.drac_client.list_bios_settings) + + @requests_mock.Mocker() + @mock.patch.object(dracclient.client.WSManClient, 'invoke', + spec_set=True, autospec=True) + def test_set_bios_settings(self, mock_requests, mock_invoke): + expected_selectors = {'CreationClassName': 'DCIM_BIOSService', + 'SystemName': 'DCIM:ComputerSystem', + 'Name': 'DCIM:BIOSService', + 'SystemCreationClassName': 'DCIM_ComputerSystem'} + expected_properties = {'Target': 'BIOS.Setup.1-1', + 'AttributeName': ['ProcVirtualization'], + 'AttributeValue': ['Disabled']} + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSEnumeration]['ok']}, + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSString]['ok']}, + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSInteger]['ok']}]) + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.BIOSInvocations[uris.DCIM_BIOSService][ + 'SetAttributes']['ok']) + + result = self.drac_client.set_bios_settings( + {'ProcVirtualization': 'Disabled'}) + + self.assertEqual({'commit_required': True}, result) + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_BIOSService, 'SetAttributes', + expected_selectors, expected_properties) + + @requests_mock.Mocker() + def test_set_bios_settings_error(self, mock_requests): + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSEnumeration]['ok']}, + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSString]['ok']}, + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSInteger]['ok']}, + {'text': test_utils.BIOSInvocations[ + uris.DCIM_BIOSService]['SetAttributes']['error']}]) + + self.assertRaises(exceptions.DRACOperationFailed, + self.drac_client.set_bios_settings, + {'ProcVirtualization': 'Disabled'}) + + @requests_mock.Mocker() + def test_set_bios_settings_with_unknown_attr(self, mock_requests): + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSEnumeration]['ok']}, + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSString]['ok']}, + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSInteger]['ok']}]) + + self.assertRaises(exceptions.InvalidParameterValue, + self.drac_client.set_bios_settings, {'foo': 'bar'}) + + @requests_mock.Mocker() + def test_set_bios_settings_with_unchanged_attr(self, mock_requests): + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSEnumeration]['ok']}, + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSString]['ok']}, + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSInteger]['ok']}]) + + result = self.drac_client.set_bios_settings( + {'ProcVirtualization': 'Enabled'}) + + self.assertEqual({'commit_required': False}, result) + + @requests_mock.Mocker() + def test_set_bios_settings_with_readonly_attr(self, mock_requests): + expected_message = ("Cannot set read-only BIOS attributes: " + "['Proc1NumCores'].") + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSEnumeration]['ok']}, + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSString]['ok']}, + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSInteger]['ok']}]) + + self.assertRaisesRegexp( + exceptions.DRACOperationFailed, re.escape(expected_message), + self.drac_client.set_bios_settings, {'Proc1NumCores': 42}) + + @requests_mock.Mocker() + def test_set_bios_settings_with_incorrect_enum_value(self, mock_requests): + expected_message = ("Attribute 'MemTest' cannot be set to value " + "'foo'. It must be in ['Enabled', 'Disabled'].") + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSEnumeration]['ok']}, + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSString]['ok']}, + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSInteger]['ok']}]) + + self.assertRaisesRegexp( + exceptions.DRACOperationFailed, re.escape(expected_message), + self.drac_client.set_bios_settings, {'MemTest': 'foo'}) + + @requests_mock.Mocker() + def test_set_bios_settings_with_incorrect_regexp(self, mock_requests): + expected_message = ("Attribute 'SystemModelName' cannot be set to " + "value 'bar.' It must match regex 'foo'.") + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSEnumeration]['ok']}, + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSString]['regexp']}, + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSInteger]['ok']}]) + + self.assertRaisesRegexp( + exceptions.DRACOperationFailed, re.escape(expected_message), + self.drac_client.set_bios_settings, {'SystemModelName': 'bar'}) + + @requests_mock.Mocker() + def test_set_bios_settings_with_out_of_bounds_value(self, mock_requests): + expected_message = ('Attribute Proc1NumCores cannot be set to value ' + '-42. It must be between 0 and 65535.') + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSEnumeration]['ok']}, + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSString]['ok']}, + {'text': test_utils.BIOSEnumerations[ + uris.DCIM_BIOSInteger]['mutable']}]) + + self.assertRaisesRegexp( + exceptions.DRACOperationFailed, re.escape(expected_message), + self.drac_client.set_bios_settings, {'Proc1NumCores': -42}) + + class ClientJobManagementTestCase(base.BaseTest): def setUp(self): @@ -383,7 +589,18 @@ class ClientBIOSChangesTestCase(base.BaseTest): mock_create_config_job.assert_called_once_with( mock.ANY, resource_uri=uris.DCIM_BIOSService, cim_creation_class_name='DCIM_BIOSService', - cim_name='DCIM:BIOSService', target='BIOS.Setup.1-1') + cim_name='DCIM:BIOSService', target='BIOS.Setup.1-1', reboot=False) + + @mock.patch.object(dracclient.resources.job.JobManagement, + 'create_config_job', spec_set=True, autospec=True) + def test_commit_pending_bios_changes_with_reboot(self, + mock_create_config_job): + self.drac_client.commit_pending_bios_changes(reboot=True) + + mock_create_config_job.assert_called_once_with( + mock.ANY, resource_uri=uris.DCIM_BIOSService, + cim_creation_class_name='DCIM_BIOSService', + cim_name='DCIM:BIOSService', target='BIOS.Setup.1-1', reboot=True) @mock.patch.object(dracclient.resources.job.JobManagement, 'delete_pending_config', spec_set=True, autospec=True) diff --git a/dracclient/tests/utils.py b/dracclient/tests/utils.py index 1446773..c515236 100644 --- a/dracclient/tests/utils.py +++ b/dracclient/tests/utils.py @@ -44,8 +44,17 @@ WSManEnumerations = { } BIOSEnumerations = { - uris.DCIM_ComputerSystem: { - 'ok': load_wsman_xml('computer_system-enum-ok') + uris.DCIM_BIOSEnumeration: { + 'ok': load_wsman_xml('bios_enumeration-enum-ok') + }, + uris.DCIM_BIOSInteger: { + 'mutable': load_wsman_xml('bios_integer-enum-mutable'), + 'ok': load_wsman_xml('bios_integer-enum-ok') + }, + uris.DCIM_BIOSString: { + 'colliding': load_wsman_xml('bios_string-enum-colliding'), + 'ok': load_wsman_xml('bios_string-enum-ok'), + 'regexp': load_wsman_xml('bios_string-enum-regexp') }, uris.DCIM_BootConfigSetting: { 'ok': load_wsman_xml('boot_config_setting-enum-ok') @@ -53,7 +62,10 @@ BIOSEnumerations = { uris.DCIM_BootSourceSetting: { 'ok': load_wsman_xml('boot_source_setting-enum-ok'), 'ok-11g': load_wsman_xml('boot_source_setting-enum-ok-11g') - } + }, + uris.DCIM_ComputerSystem: { + 'ok': load_wsman_xml('computer_system-enum-ok') + }, } BIOSInvocations = { @@ -65,6 +77,14 @@ BIOSInvocations = { 'computer_system-invoke-request_state_change-error'), }, }, + uris.DCIM_BIOSService: { + 'SetAttributes': { + 'ok': load_wsman_xml( + 'bios_service-invoke-set_attributes-ok'), + 'error': load_wsman_xml( + 'bios_service-invoke-set_attributes-error'), + } + }, uris.DCIM_BootConfigSetting: { 'ChangeBootOrderByInstanceID': { 'ok': load_wsman_xml( diff --git a/dracclient/tests/wsman_mocks/bios_enumeration-enum-ok.xml b/dracclient/tests/wsman_mocks/bios_enumeration-enum-ok.xml new file mode 100644 index 0000000..6804d46 --- /dev/null +++ b/dracclient/tests/wsman_mocks/bios_enumeration-enum-ok.xml @@ -0,0 +1,1495 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + uuid:659b7e16-501d-4e43-83a6-8ef24472c0ca + uuid:3127d391-2213-1213-8ee7-a36fc6fe83b0 + + + + + + System Memory Testing + MemTest + Disabled + + 306 + BIOS.Setup.1-1 + Memory Settings + MemSettings + BIOS.Setup.1-1:MemTest + false + + Enabled + Disabled + Enabled + Disabled + + + Memory Operating Mode + MemOpMode + OptimizerMode + + 310 + BIOS.Setup.1-1 + Memory Settings + MemSettings + BIOS.Setup.1-1:MemOpMode + true + + OptimizerMode + Optimizer Mode + + + Node Interleaving + NodeInterleave + Disabled + + 312 + BIOS.Setup.1-1 + Memory Settings + MemSettings + BIOS.Setup.1-1:NodeInterleave + true + + Enabled + Disabled + Enabled + Disabled + + + Logical Processor + LogicalProc + Enabled + + 401 + BIOS.Setup.1-1 + Processor Settings + ProcSettings + BIOS.Setup.1-1:LogicalProc + false + + Enabled + Disabled + Enabled + Disabled + + + Alternate RTID (Requestor Transaction ID) Setting + RtidSetting + Disabled + + 407 + BIOS.Setup.1-1 + Processor Settings + ProcSettings + BIOS.Setup.1-1:RtidSetting + false + + Enabled + Disabled + Enabled + Disabled + + + Virtualization Technology + ProcVirtualization + Enabled + + 409 + BIOS.Setup.1-1 + Processor Settings + ProcSettings + BIOS.Setup.1-1:ProcVirtualization + false + + Enabled + Disabled + Enabled + Disabled + + + Adjacent Cache Line Prefetch + ProcAdjCacheLine + Enabled + + 411 + BIOS.Setup.1-1 + Processor Settings + ProcSettings + BIOS.Setup.1-1:ProcAdjCacheLine + false + + Enabled + Disabled + Enabled + Disabled + + + Hardware Prefetcher + ProcHwPrefetcher + Enabled + + 413 + BIOS.Setup.1-1 + Processor Settings + ProcSettings + BIOS.Setup.1-1:ProcHwPrefetcher + false + + Enabled + Disabled + Enabled + Disabled + + + DCU Streamer Prefetcher + DcuStreamerPrefetcher + Enabled + + 415 + BIOS.Setup.1-1 + Processor Settings + ProcSettings + BIOS.Setup.1-1:DcuStreamerPrefetcher + false + + Enabled + Disabled + Enabled + Disabled + + + DCU IP Prefetcher + DcuIpPrefetcher + Enabled + + 417 + BIOS.Setup.1-1 + Processor Settings + ProcSettings + BIOS.Setup.1-1:DcuIpPrefetcher + false + + Enabled + Disabled + Enabled + Disabled + + + Execute Disable + ProcExecuteDisable + Enabled + + 419 + BIOS.Setup.1-1 + Processor Settings + ProcSettings + BIOS.Setup.1-1:ProcExecuteDisable + false + + Enabled + Disabled + Enabled + Disabled + + + Logical Processor Idling + DynamicCoreAllocation + Disabled + + 421 + BIOS.Setup.1-1 + Processor Settings + ProcSettings + BIOS.Setup.1-1:DynamicCoreAllocation + false + + Enabled + Disabled + Enabled + Disabled + + + Number of Cores per Processor + ProcCores + All + + 434 + BIOS.Setup.1-1 + Processor Settings + ProcSettings + BIOS.Setup.1-1:ProcCores + false + + All + 1 + 2 + 4 + 6 + All + 1 + 2 + 4 + 6 + + + Embedded SATA + EmbSata + AhciMode + + 501 + BIOS.Setup.1-1 + SATA Settings + SataSettings + BIOS.Setup.1-1:EmbSata + false + + AtaMode + AhciMode + RaidMode + Off + ATA Mode + AHCI Mode + RAID Mode + Off + + + Port A + SataPortA + Auto + + + AtaMode + + AhciMode + RaidMode + + + AhciMode + RaidMode + + ]]> + 506 + BIOS.Setup.1-1 + SATA Settings + SataSettings + BIOS.Setup.1-1:SataPortA + true + + Auto + Off + Auto + Off + + + Port B + SataPortB + Auto + + + AtaMode + + AhciMode + RaidMode + + + AhciMode + RaidMode + + ]]> + 512 + BIOS.Setup.1-1 + SATA Settings + SataSettings + BIOS.Setup.1-1:SataPortB + true + + Auto + Off + Auto + Off + + + Port C + SataPortC + Auto + + + AtaMode + + AhciMode + RaidMode + + + AhciMode + RaidMode + + ]]> + 518 + BIOS.Setup.1-1 + SATA Settings + SataSettings + BIOS.Setup.1-1:SataPortC + true + + Auto + Off + Auto + Off + + + Port D + SataPortD + Auto + + + AtaMode + + AhciMode + RaidMode + + + AhciMode + RaidMode + + ]]> + 524 + BIOS.Setup.1-1 + SATA Settings + SataSettings + BIOS.Setup.1-1:SataPortD + true + + Auto + Off + Auto + Off + + + Port E + SataPortE + Auto + + + AtaMode + + AhciMode + RaidMode + + + AhciMode + RaidMode + + ]]> + 530 + BIOS.Setup.1-1 + SATA Settings + SataSettings + BIOS.Setup.1-1:SataPortE + true + + Auto + Off + Auto + Off + + + Boot Mode + BootMode + Bios + + 602 + BIOS.Setup.1-1 + Boot Settings + BootSettings + BIOS.Setup.1-1:BootMode + false + + Bios + Uefi + BIOS + UEFI + + + Boot Sequence Retry + BootSeqRetry + Disabled + + 604 + BIOS.Setup.1-1 + Boot Settings + BootSettings + BIOS.Setup.1-1:BootSeqRetry + false + + Enabled + Disabled + Enabled + Disabled + + + UEFI PXE boot protocol + UefiPxeIpVersion + IPv4 + + + Bios + ]]> + 810 + BIOS.Setup.1-1 + UEFI Boot Settings + UefiBootSettings + BIOS.Setup.1-1:UefiPxeIpVersion + true + + IPv4 + IPv6 + IPv4 + IPv6 + + + One-Time Boot Device List + OneTimeBootMode + Disabled + + 900 + BIOS.Setup.1-1 + One-Time Boot + OneTimeBoot + BIOS.Setup.1-1:OneTimeBootMode + false + + Disabled + OneTimeBootSeq + OneTimeHddSeq + OneTimeUefiBootSeq + Disabled + BIOS Boot Sequence Device + BIOS Hard-Disk Drive Sequence Device + UEFI Boot Sequence Device + + + BIOS Boot Sequence Device + OneTimeBootSeqDev + HardDisk.List.1-1 + + + OneTimeBootSeq + ]]> + 901 + BIOS.Setup.1-1 + One-Time Boot + OneTimeBoot + BIOS.Setup.1-1:OneTimeBootSeqDev + true + + HardDisk.List.1-1 + Optical.SATAEmbedded.E-1 + NIC.Embedded.1-1-1 + Hard drive C: + Embedded SATA Port Optical Drive E: HL-DT-ST DVD-ROM DU90N + Embedded NIC 1 Port 1 Partition 1: BRCM MBA Slot 0200 v16.4.3 + + + BIOS Hard-Disk Drive Sequence Device + OneTimeHddSeqDev + RAID.Integrated.1-1 + + + OneTimeHddSeq + ]]> + 902 + BIOS.Setup.1-1 + One-Time Boot + OneTimeBoot + BIOS.Setup.1-1:OneTimeHddSeqDev + true + + RAID.Integrated.1-1 + Integrated RAID Controller 1: PERC H710 Mini(bus 01 dev 00) + + + UEFI Boot Sequence Device + OneTimeUefiBootSeqDev + Optical.SATAEmbedded.E-1 + + + OneTimeUefiBootSeq + ]]> + 903 + BIOS.Setup.1-1 + One-Time Boot + OneTimeBoot + BIOS.Setup.1-1:OneTimeUefiBootSeqDev + true + + Optical.SATAEmbedded.E-1 + NIC.Embedded.1-1-1 + NIC.Embedded.2-1-1 + NIC.Slot.2-1-1 + NIC.Slot.2-2-1 + Unknown.Unknown.6-1 + Embedded SATA Port Optical Drive E: HL-DT-ST DVD-ROM DU90N + Embedded NIC 1 Port 1 Partition 1: EFI Network 1 + Embedded NIC 2 Port 1 Partition 1: EFI Network 2 + NIC in Slot 2 Port 1 Partition 1: EFI Network 3 + NIC in Slot 2 Port 2 Partition 1: EFI Network 4 + Unavailable: Windows Boot Manager + + + Integrated RAID Controller + IntegratedRaid + Enabled + + 1003 + BIOS.Setup.1-1 + Integrated Devices + IntegratedDevices + BIOS.Setup.1-1:IntegratedRaid + false + + Enabled + Disabled + Enabled + Disabled + + + User Accessible USB Ports + UsbPorts + AllOn + + 1005 + BIOS.Setup.1-1 + Integrated Devices + IntegratedDevices + BIOS.Setup.1-1:UsbPorts + false + + AllOn + OnlyBackPortsOn + AllOff + All Ports On + Only Back Ports On + All Ports Off + + + Internal USB Port + InternalUsb + On + + 1007 + BIOS.Setup.1-1 + Integrated Devices + IntegratedDevices + BIOS.Setup.1-1:InternalUsb + false + + On + Off + On + Off + + + Embedded NIC1 and NIC2 + EmbNic1Nic2 + Enabled + + 1016 + BIOS.Setup.1-1 + Integrated Devices + IntegratedDevices + BIOS.Setup.1-1:EmbNic1Nic2 + false + + Enabled + DisabledOs + Enabled + Disabled (OS) + + + OS Watchdog Timer + OsWatchdogTimer + Disabled + + 1026 + BIOS.Setup.1-1 + Integrated Devices + IntegratedDevices + BIOS.Setup.1-1:OsWatchdogTimer + false + + Enabled + Disabled + Enabled + Disabled + + + I/OAT DMA Engine + IoatEngine + Disabled + + 1028 + BIOS.Setup.1-1 + Integrated Devices + IntegratedDevices + BIOS.Setup.1-1:IoatEngine + false + + Enabled + Disabled + Enabled + Disabled + + + Embedded Video Controller + EmbVideo + Enabled + + 1030 + BIOS.Setup.1-1 + Integrated Devices + IntegratedDevices + BIOS.Setup.1-1:EmbVideo + true + + Enabled + Disabled + Enabled + Disabled + + + SR-IOV Global Enable + SriovGlobalEnable + Disabled + + 1032 + BIOS.Setup.1-1 + Integrated Devices + IntegratedDevices + BIOS.Setup.1-1:SriovGlobalEnable + false + + Enabled + Disabled + Enabled + Disabled + + + Memory Mapped I/O above 4GB + MmioAbove4Gb + Enabled + + 1034 + BIOS.Setup.1-1 + Integrated Devices + IntegratedDevices + BIOS.Setup.1-1:MmioAbove4Gb + false + + Enabled + Disabled + Enabled + Disabled + + + Slot 1 + Slot1 + Enabled + + 1102 + BIOS.Setup.1-1 + Slot Disablement + SlotDisablement + BIOS.Setup.1-1:Slot1 + false + + Enabled + Disabled + BootDriverDisabled + Enabled + Disabled + Boot Driver Disabled + + + Slot 2 + Slot2 + Enabled + + 1105 + BIOS.Setup.1-1 + Slot Disablement + SlotDisablement + BIOS.Setup.1-1:Slot2 + false + + Enabled + Disabled + BootDriverDisabled + Enabled + Disabled + Boot Driver Disabled + + + Serial Communication + SerialComm + OnNoConRedir + + 1201 + BIOS.Setup.1-1 + Serial Communication + SerialCommSettings + BIOS.Setup.1-1:SerialComm + false + + OnNoConRedir + OnConRedirCom1 + OnConRedirCom2 + Off + On without Console Redirection + On with Console Redirection via COM1 + On with Console Redirection via COM2 + Off + + + Serial Port Address + SerialPortAddress + Serial1Com2Serial2Com1 + + 1203 + BIOS.Setup.1-1 + Serial Communication + SerialCommSettings + BIOS.Setup.1-1:SerialPortAddress + false + + Serial1Com1Serial2Com2 + Serial1Com2Serial2Com1 + Serial Device1=COM1,Serial Device2=COM2 + Serial Device1=COM2,Serial Device2=COM1 + + + External Serial Connector + ExtSerialConnector + Serial1 + + 1205 + BIOS.Setup.1-1 + Serial Communication + SerialCommSettings + BIOS.Setup.1-1:ExtSerialConnector + false + + Serial1 + Serial2 + RemoteAccDevice + Serial Device 1 + Serial Device 2 + Remote Access Device + + + Failsafe Baud Rate + FailSafeBaud + 115200 + + 1207 + BIOS.Setup.1-1 + Serial Communication + SerialCommSettings + BIOS.Setup.1-1:FailSafeBaud + false + + 115200 + 57600 + 19200 + 9600 + 115200 + 57600 + 19200 + 9600 + + + Remote Terminal Type + ConTermType + Vt100Vt220 + + 1209 + BIOS.Setup.1-1 + Serial Communication + SerialCommSettings + BIOS.Setup.1-1:ConTermType + false + + Vt100Vt220 + Ansi + VT100/VT220 + ANSI + + + Redirection After Boot + RedirAfterBoot + Enabled + + 1211 + BIOS.Setup.1-1 + Serial Communication + SerialCommSettings + BIOS.Setup.1-1:RedirAfterBoot + false + + Enabled + Disabled + Enabled + Disabled + + + System Profile + SysProfile + PerfPerWattOptimizedDapc + + 1301 + BIOS.Setup.1-1 + System Profile Settings + SysProfileSettings + BIOS.Setup.1-1:SysProfile + false + + PerfPerWattOptimizedDapc + PerfPerWattOptimizedOs + PerfOptimized + DenseCfgOptimized + Custom + Performance Per Watt (DAPC) + Performance Per Watt (OS) + Performance + Dense Configuration + Custom + + + CPU Power Management + ProcPwrPerf + SysDbpm + + + Custom + + PerfPerWattOptimizedDapc + DenseCfgOptimized + PerfPerWattOptimizedOs + PerfOptimized + + + PerfOptimized + PerfPerWattOptimizedDapc + PerfPerWattOptimizedOs + DenseCfgOptimized + + + PerfPerWattOptimizedOs + PerfPerWattOptimizedDapc + PerfOptimized + DenseCfgOptimized + + ]]> + 1303 + BIOS.Setup.1-1 + System Profile Settings + SysProfileSettings + BIOS.Setup.1-1:ProcPwrPerf + true + + SysDbpm + MaxPerf + OsDbpm + System DBPM (DAPC) + Maximum Performance + OS DBPM + + + Memory Frequency + MemFrequency + MaxPerf + + + Custom + + Custom + + + Custom + + + Custom + + + Custom + + + Custom + + + Custom + + + Custom + + ]]> + 1310 + BIOS.Setup.1-1 + System Profile Settings + SysProfileSettings + BIOS.Setup.1-1:MemFrequency + true + + MaxPerf + MaxReliability + 1866MHz + 1600MHz + 1333MHz + 1067MHz + 800MHz + Maximum Performance + Maximum Reliability + 1866MHz + 1600MHz + 1333MHz + 1067MHz + 800MHz + + + Turbo Boost + ProcTurboMode + Enabled + + + Custom + + PerfPerWattOptimizedDapc + PerfPerWattOptimizedOs + PerfOptimized + DenseCfgOptimized + + + DenseCfgOptimized + PerfPerWattOptimizedDapc + PerfPerWattOptimizedOs + PerfOptimized + + ]]> + 1312 + BIOS.Setup.1-1 + System Profile Settings + SysProfileSettings + BIOS.Setup.1-1:ProcTurboMode + true + + Enabled + Disabled + Enabled + Disabled + + + C1E + ProcC1E + Enabled + + + Custom + + PerfPerWattOptimizedDapc + PerfPerWattOptimizedOs + DenseCfgOptimized + PerfOptimized + + + PerfOptimized + PerfPerWattOptimizedDapc + PerfPerWattOptimizedOs + DenseCfgOptimized + + ]]> + 1314 + BIOS.Setup.1-1 + System Profile Settings + SysProfileSettings + BIOS.Setup.1-1:ProcC1E + true + + Enabled + Disabled + Enabled + Disabled + + + C States + ProcCStates + Enabled + + + Custom + + PerfPerWattOptimizedDapc + PerfPerWattOptimizedOs + DenseCfgOptimized + PerfOptimized + + + PerfOptimized + PerfPerWattOptimizedDapc + PerfPerWattOptimizedOs + DenseCfgOptimized + + ]]> + 1316 + BIOS.Setup.1-1 + System Profile Settings + SysProfileSettings + BIOS.Setup.1-1:ProcCStates + true + + Enabled + Disabled + Enabled + Disabled + + + Monitor/Mwait + MonitorMwait + Enabled + + + Custom + + Custom + + + Custom + + ]]> + 1318 + BIOS.Setup.1-1 + System Profile Settings + SysProfileSettings + BIOS.Setup.1-1:MonitorMwait + true + + Enabled + Disabled + Enabled + Disabled + + + Memory Patrol Scrub + MemPatrolScrub + Standard + + + Custom + + DenseCfgOptimized + PerfPerWattOptimizedDapc + PerfPerWattOptimizedOs + PerfOptimized + + + PerfOptimized + PerfPerWattOptimizedOs + PerfPerWattOptimizedDapc + DenseCfgOptimized + + + Custom + + ]]> + 1320 + BIOS.Setup.1-1 + System Profile Settings + SysProfileSettings + BIOS.Setup.1-1:MemPatrolScrub + true + + Extended + Standard + Disabled + Extended + Standard + Disabled + + + Memory Refresh Rate + MemRefreshRate + 1x + + + Custom + + PerfPerWattOptimizedDapc + PerfPerWattOptimizedOs + PerfOptimized + DenseCfgOptimized + + + DenseCfgOptimized + PerfPerWattOptimizedDapc + PerfPerWattOptimizedOs + PerfOptimized + + ]]> + 1322 + BIOS.Setup.1-1 + System Profile Settings + SysProfileSettings + BIOS.Setup.1-1:MemRefreshRate + true + + 1x + 2x + 1x + 2x + + + Memory Operating Voltage + MemVolt + AutoVolt + + + Custom + + PerfPerWattOptimizedDapc + PerfPerWattOptimizedOs + PerfOptimized + DenseCfgOptimized + + + DenseCfgOptimized + PerfPerWattOptimizedDapc + PerfPerWattOptimizedOs + PerfOptimized + + ]]> + 1325 + BIOS.Setup.1-1 + System Profile Settings + SysProfileSettings + BIOS.Setup.1-1:MemVolt + true + + AutoVolt + Volt15V + Auto + 1.5V + + + Collaborative CPU Performance Control + CollaborativeCpuPerfCtrl + Disabled + + + Custom + + Custom + + + Custom + + ]]> + 1327 + BIOS.Setup.1-1 + System Profile Settings + SysProfileSettings + BIOS.Setup.1-1:CollaborativeCpuPerfCtrl + true + + Disabled + Enabled + Disabled + Enabled + + + Password Status + PasswordStatus + Unlocked + + 1405 + BIOS.Setup.1-1 + System Security + SysSecurity + BIOS.Setup.1-1:PasswordStatus + false + + Unlocked + Locked + Unlocked + Locked + + + TPM Security + TpmSecurity + Off + + 1408 + BIOS.Setup.1-1 + System Security + SysSecurity + BIOS.Setup.1-1:TpmSecurity + false + + Off + OnPbm + OnNoPbm + Off + On with Pre-boot Measurements + On without Pre-boot Measurements + + + TPM Activation + TpmActivation + NoChange + + + Off + + Off + + + Off + + + Off + + ]]> + 1412 + BIOS.Setup.1-1 + System Security + SysSecurity + BIOS.Setup.1-1:TpmActivation + true + + NoChange + Activate + Deactivate + No Change + Activate + Deactivate + + + TPM Clear + TpmClear + No + + + Off + + Off + + + Off + + ]]> + 1417 + BIOS.Setup.1-1 + System Security + SysSecurity + BIOS.Setup.1-1:TpmClear + true + + No + Yes + No + Yes + + + Intel(R) TXT + IntelTxt + Off + + + Disabled + Deactivate + Yes + OnPbm + + Disabled + Deactivate + Yes + OnPbm + + + Disabled + Deactivate + Yes + OnPbm + + ]]> + 1421 + BIOS.Setup.1-1 + System Security + SysSecurity + BIOS.Setup.1-1:IntelTxt + true + + Off + On + Off + On + + + Power Button + PwrButton + Enabled + + 1423 + BIOS.Setup.1-1 + System Security + SysSecurity + BIOS.Setup.1-1:PwrButton + false + + Enabled + Disabled + Enabled + Disabled + + + NMI Button + NmiButton + Disabled + + 1425 + BIOS.Setup.1-1 + System Security + SysSecurity + BIOS.Setup.1-1:NmiButton + false + + Enabled + Disabled + Enabled + Disabled + + + AC Power Recovery + AcPwrRcvry + Last + + 1429 + BIOS.Setup.1-1 + System Security + SysSecurity + BIOS.Setup.1-1:AcPwrRcvry + false + + Last + On + Off + Last + On + Off + + + AC Power Recovery Delay + AcPwrRcvryDelay + Immediate + + + Off + ]]> + 1430 + BIOS.Setup.1-1 + System Security + SysSecurity + BIOS.Setup.1-1:AcPwrRcvryDelay + false + + Immediate + Random + User + Immediate + Random + User Defined + + + Keyboard NumLock + NumLock + On + + 1506 + BIOS.Setup.1-1 + Miscellaneous Settings + MiscSettings + BIOS.Setup.1-1:NumLock + false + + On + Off + On + Off + + + Report Keyboard Errors + ReportKbdErr + Report + + 1508 + BIOS.Setup.1-1 + Miscellaneous Settings + MiscSettings + BIOS.Setup.1-1:ReportKbdErr + false + + Report + NoReport + Report + Do Not Report + + + F1/F2 Prompt on Error + ErrPrompt + Enabled + + 1510 + BIOS.Setup.1-1 + Miscellaneous Settings + MiscSettings + BIOS.Setup.1-1:ErrPrompt + false + + Enabled + Disabled + Enabled + Disabled + + + + + + + \ No newline at end of file diff --git a/dracclient/tests/wsman_mocks/bios_integer-enum-mutable.xml b/dracclient/tests/wsman_mocks/bios_integer-enum-mutable.xml new file mode 100644 index 0000000..306500b --- /dev/null +++ b/dracclient/tests/wsman_mocks/bios_integer-enum-mutable.xml @@ -0,0 +1,36 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + uuid:382b3463-6ab7-4998-85d5-0ac3f4d3044d + uuid:319dc294-2213-1213-8eeb-a36fc6fe83b0 + + + + + + Number of Cores + Proc1NumCores + 8 + + 446 + BIOS.Setup.1-1 + Processor Settings + ProcSettings + BIOS.Setup.1-1:Proc1NumCores + false + 0 + + 65535 + + + + + + + \ No newline at end of file diff --git a/dracclient/tests/wsman_mocks/bios_integer-enum-ok.xml b/dracclient/tests/wsman_mocks/bios_integer-enum-ok.xml new file mode 100644 index 0000000..ed5f8ce --- /dev/null +++ b/dracclient/tests/wsman_mocks/bios_integer-enum-ok.xml @@ -0,0 +1,56 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + uuid:382b3463-6ab7-4998-85d5-0ac3f4d3044d + uuid:319dc294-2213-1213-8eeb-a36fc6fe83b0 + + + + + + Number of Cores + Proc1NumCores + 8 + + 446 + BIOS.Setup.1-1 + Processor Settings + ProcSettings + BIOS.Setup.1-1:Proc1NumCores + true + 0 + + 65535 + + + User Defined Delay (60s to 240s) + AcPwrRcvryUserDelay + 60 + + + Off + User + ]]> + 1431 + BIOS.Setup.1-1 + System Security + SysSecurity + BIOS.Setup.1-1:AcPwrRcvryUserDelay + true + 60 + + 240 + + + + + + + \ No newline at end of file diff --git a/dracclient/tests/wsman_mocks/bios_service-invoke-set_attributes-error.xml b/dracclient/tests/wsman_mocks/bios_service-invoke-set_attributes-error.xml new file mode 100644 index 0000000..997454b --- /dev/null +++ b/dracclient/tests/wsman_mocks/bios_service-invoke-set_attributes-error.xml @@ -0,0 +1,20 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_BIOSService/SetAttributesResponse + uuid:f06dfc6d-b102-43d8-a61e-722b7ec8b7b2 + uuid:2bfaa9a2-223c-123c-8f55-a36fc6fe83b0 + + + + Invalid AttributeValue for AttributeName ProcVirtualization + ProcVirtualization + BIOS014 + Yes + 2 + Set PendingValue + + + \ No newline at end of file diff --git a/dracclient/tests/wsman_mocks/bios_service-invoke-set_attributes-ok.xml b/dracclient/tests/wsman_mocks/bios_service-invoke-set_attributes-ok.xml new file mode 100644 index 0000000..403d84b --- /dev/null +++ b/dracclient/tests/wsman_mocks/bios_service-invoke-set_attributes-ok.xml @@ -0,0 +1,19 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_BIOSService/SetAttributesResponse + uuid:9ffdced1-8f2e-441c-a42a-e6c56d9859c8 + uuid:d139ff73-223b-123b-8f47-a36fc6fe83b0 + + + + The command was successful. + BIOS001 + Yes + 0 + Set PendingValue + + + \ No newline at end of file diff --git a/dracclient/tests/wsman_mocks/bios_string-enum-colliding.xml b/dracclient/tests/wsman_mocks/bios_string-enum-colliding.xml new file mode 100644 index 0000000..9db9ff2 --- /dev/null +++ b/dracclient/tests/wsman_mocks/bios_string-enum-colliding.xml @@ -0,0 +1,53 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + uuid:1d8b3e77-8919-4459-8f06-2d63284c15c1 + uuid:31707306-2213-1213-8ee9-a36fc6fe83b0 + + + + + + System Memory Testing + MemTest + PowerEdge R320 + + 200 + BIOS.Setup.1-1 + System Information + SysInformation + BIOS.Setup.1-1:SystemModelName + true + 32 + 0 + + + + + Memory Operating Mode + MemOpMode + 2.3.3 + + 201 + BIOS.Setup.1-1 + System Information + SysInformation + BIOS.Setup.1-1:SystemBiosVersion + true + 48 + 0 + + + + + + + + + \ No newline at end of file diff --git a/dracclient/tests/wsman_mocks/bios_string-enum-ok.xml b/dracclient/tests/wsman_mocks/bios_string-enum-ok.xml new file mode 100644 index 0000000..7d7ed2f --- /dev/null +++ b/dracclient/tests/wsman_mocks/bios_string-enum-ok.xml @@ -0,0 +1,581 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + uuid:1d8b3e77-8919-4459-8f06-2d63284c15c1 + uuid:31707306-2213-1213-8ee9-a36fc6fe83b0 + + + + + + System Model Name + SystemModelName + PowerEdge R320 + + 200 + BIOS.Setup.1-1 + System Information + SysInformation + BIOS.Setup.1-1:SystemModelName + true + 32 + 0 + + + + + System BIOS Version + SystemBiosVersion + 2.3.3 + + 201 + BIOS.Setup.1-1 + System Information + SysInformation + BIOS.Setup.1-1:SystemBiosVersion + true + 48 + 0 + + + + + System Service Tag + SystemServiceTag + JLR7Q22 + + 202 + BIOS.Setup.1-1 + System Information + SysInformation + BIOS.Setup.1-1:SystemServiceTag + true + 16 + 0 + + + + + System Manufacturer + SystemManufacturer + Dell Inc. + + 204 + BIOS.Setup.1-1 + System Information + SysInformation + BIOS.Setup.1-1:SystemManufacturer + true + 32 + 0 + + + + + System Manufacturer Contact Information + SysMfrContactInfo + www.dell.com + + 205 + BIOS.Setup.1-1 + System Information + SysInformation + BIOS.Setup.1-1:SysMfrContactInfo + true + 32 + 0 + + + + + System CPLD Version + SystemCpldVersion + 104 + + 206 + BIOS.Setup.1-1 + System Information + SysInformation + BIOS.Setup.1-1:SystemCpldVersion + true + 8 + 0 + + + + + System Memory Size + SysMemSize + 32.0 GB + + 300 + BIOS.Setup.1-1 + Memory Settings + MemSettings + BIOS.Setup.1-1:SysMemSize + true + 20 + 0 + + + + + System Memory Type + SysMemType + ECC DDR3 + + 301 + BIOS.Setup.1-1 + Memory Settings + MemSettings + BIOS.Setup.1-1:SysMemType + true + 16 + 0 + + + + + System Memory Speed + SysMemSpeed + 1600 MHz + + 302 + BIOS.Setup.1-1 + Memory Settings + MemSettings + BIOS.Setup.1-1:SysMemSpeed + true + 16 + 0 + + + + + System Memory Voltage + SysMemVolt + 1.35V + + 303 + BIOS.Setup.1-1 + Memory Settings + MemSettings + BIOS.Setup.1-1:SysMemVolt + true + 8 + 0 + + + + + Video Memory + VideoMem + 16 MB + + 304 + BIOS.Setup.1-1 + Memory Settings + MemSettings + BIOS.Setup.1-1:VideoMem + true + 16 + 0 + + + + + Processor 64-bit Support + Proc64bit + Yes + + 435 + BIOS.Setup.1-1 + Processor Settings + ProcSettings + BIOS.Setup.1-1:Proc64bit + true + 4 + 0 + + + + + Processor Core Speed + ProcCoreSpeed + 1.90 GHz + + 436 + BIOS.Setup.1-1 + Processor Settings + ProcSettings + BIOS.Setup.1-1:ProcCoreSpeed + true + 16 + 0 + + + + + Family-Model-Stepping + Proc1Id + 06-3E-4 + + 442 + BIOS.Setup.1-1 + Processor Settings + ProcSettings + BIOS.Setup.1-1:Proc1Id + true + 8 + 0 + + + + + Brand + Proc1Brand + [Intel(R) Xeon(R) CPU E5-2440 v2 @ 1.90GHz ] + + 443 + BIOS.Setup.1-1 + Processor Settings + ProcSettings + BIOS.Setup.1-1:Proc1Brand + true + 80 + 0 + + + + + Level 2 Cache + Proc1L2Cache + 8x256 KB + + 444 + BIOS.Setup.1-1 + Processor Settings + ProcSettings + BIOS.Setup.1-1:Proc1L2Cache + true + 16 + 0 + + + + + Level 3 Cache + Proc1L3Cache + 20 MB + + 445 + BIOS.Setup.1-1 + Processor Settings + ProcSettings + BIOS.Setup.1-1:Proc1L3Cache + true + 16 + 0 + + + + + Model + SataPortAModel + Unknown + + 507 + BIOS.Setup.1-1 + SATA Settings + SataSettings + BIOS.Setup.1-1:SataPortAModel + true + 40 + 0 + + + + + Drive Type + SataPortADriveType + Unknown Device + + 508 + BIOS.Setup.1-1 + SATA Settings + SataSettings + BIOS.Setup.1-1:SataPortADriveType + true + 20 + 0 + + + + + Capacity + SataPortACapacity + N/A + + 509 + BIOS.Setup.1-1 + SATA Settings + SataSettings + BIOS.Setup.1-1:SataPortACapacity + true + 18 + 0 + + + + + Model + SataPortBModel + Unknown + + 513 + BIOS.Setup.1-1 + SATA Settings + SataSettings + BIOS.Setup.1-1:SataPortBModel + true + 40 + 0 + + + + + Drive Type + SataPortBDriveType + Unknown Device + + 514 + BIOS.Setup.1-1 + SATA Settings + SataSettings + BIOS.Setup.1-1:SataPortBDriveType + true + 20 + 0 + + + + + Capacity + SataPortBCapacity + N/A + + 515 + BIOS.Setup.1-1 + SATA Settings + SataSettings + BIOS.Setup.1-1:SataPortBCapacity + true + 18 + 0 + + + + + Model + SataPortCModel + Unknown + + 519 + BIOS.Setup.1-1 + SATA Settings + SataSettings + BIOS.Setup.1-1:SataPortCModel + true + 40 + 0 + + + + + Drive Type + SataPortCDriveType + Unknown Device + + 520 + BIOS.Setup.1-1 + SATA Settings + SataSettings + BIOS.Setup.1-1:SataPortCDriveType + true + 20 + 0 + + + + + Capacity + SataPortCCapacity + N/A + + 521 + BIOS.Setup.1-1 + SATA Settings + SataSettings + BIOS.Setup.1-1:SataPortCCapacity + true + 18 + 0 + + + + + Model + SataPortDModel + Unknown + + 525 + BIOS.Setup.1-1 + SATA Settings + SataSettings + BIOS.Setup.1-1:SataPortDModel + true + 40 + 0 + + + + + Drive Type + SataPortDDriveType + Unknown Device + + 526 + BIOS.Setup.1-1 + SATA Settings + SataSettings + BIOS.Setup.1-1:SataPortDDriveType + true + 20 + 0 + + + + + Capacity + SataPortDCapacity + N/A + + 527 + BIOS.Setup.1-1 + SATA Settings + SataSettings + BIOS.Setup.1-1:SataPortDCapacity + true + 18 + 0 + + + + + Model + SataPortEModel + HL-DT-ST DVD-ROM DU90N + + 531 + BIOS.Setup.1-1 + SATA Settings + SataSettings + BIOS.Setup.1-1:SataPortEModel + true + 40 + 0 + + + + + Drive Type + SataPortEDriveType + Optical Drive + + 532 + BIOS.Setup.1-1 + SATA Settings + SataSettings + BIOS.Setup.1-1:SataPortEDriveType + true + 20 + 0 + + + + + Capacity + SataPortECapacity + N/A + + 533 + BIOS.Setup.1-1 + SATA Settings + SataSettings + BIOS.Setup.1-1:SataPortECapacity + true + 18 + 0 + + + + + Intel(R) AES-NI + AesNi + Enabled + + 1400 + BIOS.Setup.1-1 + System Security + SysSecurity + BIOS.Setup.1-1:AesNi + true + 20 + 0 + + + + + TPM Status + TpmStatus + Unknown + + 1413 + BIOS.Setup.1-1 + System Security + SysSecurity + BIOS.Setup.1-1:TpmStatus + true + 24 + 0 + + + + + Asset Tag + AssetTag + + + 1504 + BIOS.Setup.1-1 + Miscellaneous Settings + MiscSettings + BIOS.Setup.1-1:AssetTag + false + 30 + 0 + + ^[ -~]{0,30}$ + + + + + + + \ No newline at end of file diff --git a/dracclient/tests/wsman_mocks/bios_string-enum-regexp.xml b/dracclient/tests/wsman_mocks/bios_string-enum-regexp.xml new file mode 100644 index 0000000..71b55b3 --- /dev/null +++ b/dracclient/tests/wsman_mocks/bios_string-enum-regexp.xml @@ -0,0 +1,37 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + uuid:1d8b3e77-8919-4459-8f06-2d63284c15c1 + uuid:31707306-2213-1213-8ee9-a36fc6fe83b0 + + + + + + System Model Name + SystemModelName + PowerEdge R320 + + 200 + BIOS.Setup.1-1 + System Information + SysInformation + BIOS.Setup.1-1:SystemModelName + false + 32 + 0 + + foo + + + + + + + \ No newline at end of file diff --git a/dracclient/utils.py b/dracclient/utils.py index 39ffbf6..f659dd8 100644 --- a/dracclient/utils.py +++ b/dracclient/utils.py @@ -15,6 +15,8 @@ Common functionalities shared between different DRAC modules. """ +NS_XMLSchema_Instance = 'http://www.w3.org/2001/XMLSchema-instance' + # ReturnValue constants RET_SUCCESS = '0' RET_ERROR = '2' @@ -42,7 +44,22 @@ def find_xml(doc, item, namespace, find_all=False): return doc.find(query) -def get_wsman_resource_attr(doc, resource_uri, attr_name): - """Find an attribute of a resource in an ElementTree object""" +def get_wsman_resource_attr(doc, resource_uri, attr_name, nullable=False): + """Find an attribute of a resource in an ElementTree object. - return find_xml(doc, attr_name, resource_uri).text.strip() + :param doc: the element tree object. + :param resource_uri: the resource URI of the namespace. + :param attr_name: the name of the attribute. + :param: nullable: enables checking if the element contains an + XMLSchema-instance namespaced nil attribute that has a + value of True. In this case, it will return None. + :returns: value of the attribute + """ + item = find_xml(doc, attr_name, resource_uri) + + if not nullable: + return item.text.strip() + else: + nil_attr = item.attrib.get('{%s}nil' % NS_XMLSchema_Instance) + if nil_attr != 'true': + return item.text.strip()