def commit_config(task): """Commits pending changes added by set_config :param task: is the ironic task for running the config job. :raises: DracClientError on an error from pywsman library. :raises: DracPendingConfigJobExists if the job is already created. :raises: DracOperationFailed if the client received response with an error message. :raises: DracUnexpectedReturnValue if the client received a response with unexpected return value """ node = task.node management.check_for_config_job(node) management.create_config_job(node)
def commit_config(task): """Commits pending changes added by set_config :param task: is the ironic task for running the config job. :raises: DracClientError on an error from pywsman library. :raises: DracPendingConfigJobExists if the job is already created. :raises: DracOperationFailed if the client received response with an error message. :raises: DracUnexpectedReturnValue if the client received a response with unexpected return value """ node = task.node management.check_for_config_job(node) management.create_config_job(node)
def test__check_for_config_job_not_exist(self, mock_client_pywsman): job_statuses = ["Completed", "Completed with Errors", "Failed"] for job_status in job_statuses: result_xml = test_utils.build_soap_xml( [{'DCIM_LifecycleJob': {'Name': 'BIOS.Setup.1-1', 'JobStatus': job_status, 'InstanceID': 'fake'}}], resource_uris.DCIM_LifecycleJob) mock_xml = test_utils.mock_wsman_root(result_xml) mock_pywsman = mock_client_pywsman.Client.return_value mock_pywsman.enumerate.return_value = mock_xml try: drac_mgmt.check_for_config_job(self.node) except (exception.DracClientError, exception.DracPendingConfigJobExists): self.fail("Failed to detect completed job due to " "\"{}\" job status".format(job_status))
def test__check_for_config_job_not_exist(self, mock_client_pywsman): job_statuses = ["Completed", "Completed with Errors", "Failed"] for job_status in job_statuses: result_xml = test_utils.build_soap_xml( [{'DCIM_LifecycleJob': {'Name': 'BIOS.Setup.1-1', 'JobStatus': job_status, 'InstanceID': 'fake'}}], resource_uris.DCIM_LifecycleJob) mock_xml = test_utils.mock_wsman_root(result_xml) mock_pywsman = mock_client_pywsman.Client.return_value mock_pywsman.enumerate.return_value = mock_xml try: drac_mgmt.check_for_config_job(self.node) except (exception.DracClientError, exception.DracPendingConfigJobExists): self.fail("Failed to detect completed job due to " "\"{}\" job status".format(job_status))
def test__check_for_config_job(self, mock_client_pywsman): result_xml = test_utils.build_soap_xml( [{'DCIM_LifecycleJob': {'Name': 'fake'}}], resource_uris.DCIM_LifecycleJob) mock_xml = test_utils.mock_wsman_root(result_xml) mock_pywsman = mock_client_pywsman.Client.return_value mock_pywsman.enumerate.return_value = mock_xml result = drac_mgmt.check_for_config_job(self.node) self.assertIsNone(result) mock_pywsman.enumerate.assert_called_once_with( mock.ANY, mock.ANY, resource_uris.DCIM_LifecycleJob)
def test__check_for_config_job(self, mock_client_pywsman): result_xml = test_utils.build_soap_xml( [{'DCIM_LifecycleJob': {'Name': 'fake'}}], resource_uris.DCIM_LifecycleJob) mock_xml = test_utils.mock_wsman_root(result_xml) mock_pywsman = mock_client_pywsman.Client.return_value mock_pywsman.enumerate.return_value = mock_xml result = drac_mgmt.check_for_config_job(self.node) self.assertIsNone(result) mock_pywsman.enumerate.assert_called_once_with( mock.ANY, mock.ANY, resource_uris.DCIM_LifecycleJob)
def set_config(task, **kwargs): """Sets the pending_value parameter for each of the values passed in. :param task: an ironic task object. :param kwargs: a dictionary of {'AttributeName': 'NewValue'} :raises: DracOperationFailed if any new values are invalid. :raises: DracOperationFailed if any of the attributes are read-only. :raises: DracOperationFailed if any of the attributes cannot be set for any other reason. :raises: DracClientError on an error from the pywsman library. :returns: A boolean indicating whether commit_config needs to be called to make the changes. """ node = task.node management.check_for_config_job(node) current = get_config(node) unknown_keys = set(kwargs) - set(current) if unknown_keys: LOG.warning(_LW('Ignoring unknown BIOS attributes "%r"'), unknown_keys) candidates = set(kwargs) - unknown_keys read_only_keys = [] unchanged_attribs = [] invalid_attribs_msgs = [] attrib_names = [] for k in candidates: if str(kwargs[k]) == str(current[k]['current_value']): unchanged_attribs.append(k) elif current[k]['read_only']: read_only_keys.append(k) else: if 'possible_values' in current[k]: if str(kwargs[k]) not in current[k]['possible_values']: m = _('Attribute %(attr)s cannot be set to value %(val)s.' ' It must be in %(ok)r') % { 'attr': k, 'val': kwargs[k], 'ok': current[k]['possible_values'] } invalid_attribs_msgs.append(m) continue if ('pcre_regex' in current[k] and current[k]['pcre_regex'] is not None): regex = re.compile(current[k]['pcre_regex']) if regex.search(str(kwargs[k])) is None: # TODO(victor-lowther) # Leave untranslated for now until the unicode # issues that the test suite exposes are straightened out. m = ('Attribute %(attr)s cannot be set to value %(val)s.' ' It must match regex %(re)s.') % { 'attr': k, 'val': kwargs[k], 're': current[k]['pcre_regex'] } invalid_attribs_msgs.append(m) continue if 'lower_bound' in current[k]: lower = current[k]['lower_bound'] upper = current[k]['upper_bound'] val = int(kwargs[k]) if val < lower or val > upper: m = _('Attribute %(attr)s cannot be set to value %(val)d.' ' It must be between %(lower)d and %(upper)d.') % { 'attr': k, 'val': val, 'lower': lower, 'upper': upper } invalid_attribs_msgs.append(m) continue attrib_names.append(k) if unchanged_attribs: LOG.warning(_LW('Ignoring unchanged BIOS settings %r'), unchanged_attribs) if invalid_attribs_msgs or read_only_keys: raise exception.DracOperationFailed( _format_error_msg(invalid_attribs_msgs, read_only_keys)) if not attrib_names: return False client = wsman_client.get_wsman_client(node) selectors = { 'CreationClassName': 'DCIM_BIOSService', 'Name': 'DCIM:BIOSService', 'SystemCreationClassName': 'DCIM_ComputerSystem', 'SystemName': 'DCIM:ComputerSystem' } properties = { 'Target': 'BIOS.Setup.1-1', 'AttributeName': attrib_names, 'AttributeValue': map(lambda k: kwargs[k], attrib_names) } doc = client.wsman_invoke(resource_uris.DCIM_BIOSService, 'SetAttributes', selectors, properties) # Yes, we look for RebootRequired. In this context, that actually means # that we need to create a lifecycle controller config job and then reboot # so that the lifecycle controller can commit the BIOS config changes that # we have proposed. set_results = doc.findall('.//{%s}RebootRequired' % resource_uris.DCIM_BIOSService) return any(str(res.text) == 'Yes' for res in set_results)
def set_config(task, **kwargs): """Sets the pending_value parameter for each of the values passed in. :param task: an ironic task object. :param kwargs: a dictionary of {'AttributeName': 'NewValue'} :raises: DracOperationFailed if any new values are invalid. :raises: DracOperationFailed if any of the attributes are read-only. :raises: DracOperationFailed if any of the attributes cannot be set for any other reason. :raises: DracClientError on an error from the pywsman library. :returns: A boolean indicating whether commit_config needs to be called to make the changes. """ node = task.node management.check_for_config_job(node) current = get_config(node) unknown_keys = set(kwargs) - set(current) if unknown_keys: LOG.warning(_LW('Ignoring unknown BIOS attributes "%r"'), unknown_keys) candidates = set(kwargs) - unknown_keys read_only_keys = [] unchanged_attribs = [] invalid_attribs_msgs = [] attrib_names = [] for k in candidates: if str(kwargs[k]) == str(current[k]['current_value']): unchanged_attribs.append(k) elif current[k]['read_only']: read_only_keys.append(k) else: if 'possible_values' in current[k]: if str(kwargs[k]) not in current[k]['possible_values']: m = _('Attribute %(attr)s cannot be set to value %(val)s.' ' It must be in %(ok)r') % { 'attr': k, 'val': kwargs[k], 'ok': current[k]['possible_values']} invalid_attribs_msgs.append(m) continue if ('pcre_regex' in current[k] and current[k]['pcre_regex'] is not None): regex = re.compile(current[k]['pcre_regex']) if regex.search(str(kwargs[k])) is None: # TODO(victor-lowther) # Leave untranslated for now until the unicode # issues that the test suite exposes are straightened out. m = ('Attribute %(attr)s cannot be set to value %(val)s.' ' It must match regex %(re)s.') % { 'attr': k, 'val': kwargs[k], 're': current[k]['pcre_regex']} invalid_attribs_msgs.append(m) continue if 'lower_bound' in current[k]: lower = current[k]['lower_bound'] upper = current[k]['upper_bound'] val = int(kwargs[k]) if val < lower or val > upper: m = _('Attribute %(attr)s cannot be set to value %(val)d.' ' It must be between %(lower)d and %(upper)d.') % { 'attr': k, 'val': val, 'lower': lower, 'upper': upper} invalid_attribs_msgs.append(m) continue attrib_names.append(k) if unchanged_attribs: LOG.warning(_LW('Ignoring unchanged BIOS settings %r'), unchanged_attribs) if invalid_attribs_msgs or read_only_keys: raise exception.DracOperationFailed( _format_error_msg(invalid_attribs_msgs, read_only_keys)) if not attrib_names: return False client = wsman_client.get_wsman_client(node) selectors = {'CreationClassName': 'DCIM_BIOSService', 'Name': 'DCIM:BIOSService', 'SystemCreationClassName': 'DCIM_ComputerSystem', 'SystemName': 'DCIM:ComputerSystem'} properties = {'Target': 'BIOS.Setup.1-1', 'AttributeName': attrib_names, 'AttributeValue': map(lambda k: kwargs[k], attrib_names)} doc = client.wsman_invoke(resource_uris.DCIM_BIOSService, 'SetAttributes', selectors, properties) # Yes, we look for RebootRequired. In this context, that actually means # that we need to create a lifecycle controller config job and then reboot # so that the lifecycle controller can commit the BIOS config changes that # we have proposed. set_results = doc.findall( './/{%s}RebootRequired' % resource_uris.DCIM_BIOSService) return any(str(res.text) == 'Yes' for res in set_results)