diff --git a/.gitreview b/.gitreview index ff78bb3..aa50766 100644 --- a/.gitreview +++ b/.gitreview @@ -1,4 +1,4 @@ [gerrit] -host=review.openstack.org +host=review.opendev.org port=29418 project=openstack/python-dracclient.git diff --git a/HACKING.rst b/HACKING.rst index cd153f3..29aff6c 100644 --- a/HACKING.rst +++ b/HACKING.rst @@ -1,4 +1,4 @@ python-dracclient Style Commandments ==================================== -Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/ +Read the OpenStack Style Commandments https://docs.openstack.org/hacking/latest/ diff --git a/README.rst b/README.rst index f956341..b906b5e 100644 --- a/README.rst +++ b/README.rst @@ -1,9 +1,18 @@ +======================== +Team and repository tags +======================== + +.. image:: https://governance.openstack.org/tc/badges/python-dracclient.svg + :target: https://governance.openstack.org/tc/reference/tags/index.html + +.. Change things from this point on + python-dracclient ================= Library for managing machines with Dell iDRAC cards. * Free software: Apache license -* Documentation: http://docs.openstack.org/developer/python-dracclient -* Source: http://git.openstack.org/cgit/openstack/python-dracclient -* Bugs: http://bugs.launchpad.net/python-dracclient +* Documentation: https://docs.openstack.org/python-dracclient/latest +* Source: http://opendev.org/openstack/python-dracclient +* Bugs: https://bugs.launchpad.net/python-dracclient diff --git a/doc/requirements.txt b/doc/requirements.txt new file mode 100644 index 0000000..c481145 --- /dev/null +++ b/doc/requirements.txt @@ -0,0 +1,6 @@ +# The order of packages is significant, because pip processes them in the order +# of appearance. Changing the order has an impact on the overall integration +# process, which may cause wedges in the gate later. + +sphinx!=1.6.6,!=1.6.7,!=2.1.0;python_version>='3.4' # BSD +openstackdocstheme # Apache-2.0 diff --git a/doc/source/conf.py b/doc/source/conf.py index dddd322..6665e41 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # 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 @@ -22,7 +21,7 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ 'sphinx.ext.autodoc', - 'oslosphinx' + 'openstackdocstheme' ] # autodoc generation is a bit aggressive and a nuisance when doing heavy @@ -56,6 +55,7 @@ # html_theme_path = ["."] # html_theme = '_theme' # html_static_path = ['static'] +html_theme = 'openstackdocs' # Output file base name for HTML help builder. htmlhelp_basename = '%sdoc' % project @@ -72,3 +72,6 @@ # Example configuration for intersphinx: refer to the Python standard library. #intersphinx_mapping = {'http://docs.python.org/': None} + +# openstackdocstheme options +repository_name = 'openstack/python-dracclient' diff --git a/dracclient/client.py b/dracclient/client.py index 18d308f..413276d 100644 --- a/dracclient/client.py +++ b/dracclient/client.py @@ -16,17 +16,25 @@ """ import logging +import subprocess +import time +from dracclient import constants from dracclient import exceptions from dracclient.resources import bios +from dracclient.resources import idrac_card from dracclient.resources import inventory from dracclient.resources import job from dracclient.resources import lifecycle_controller +from dracclient.resources import nic from dracclient.resources import raid +from dracclient.resources import system from dracclient.resources import uris from dracclient import utils from dracclient import wsman +IDRAC_IS_READY = "0" + LOG = logging.getLogger(__name__) @@ -34,9 +42,16 @@ class DRACClient(object): """Client for managing DRAC nodes""" BIOS_DEVICE_FQDD = 'BIOS.Setup.1-1' - - def __init__(self, host, username, password, port=443, path='/wsman', - protocol='https'): + IDRAC_FQDD = 'iDRAC.Embedded.1' + + def __init__( + self, host, username, password, port=443, path='/wsman', + protocol='https', + ssl_retries=constants.DEFAULT_WSMAN_SSL_ERROR_RETRIES, + ssl_retry_delay=constants.DEFAULT_WSMAN_SSL_ERROR_RETRY_DELAY_SEC, + ready_retries=constants.DEFAULT_IDRAC_IS_READY_RETRIES, + ready_retry_delay=( + constants.DEFAULT_IDRAC_IS_READY_RETRY_DELAY_SEC)): """Creates client object :param host: hostname or IP of the DRAC interface @@ -45,15 +60,27 @@ def __init__(self, host, username, password, port=443, path='/wsman', :param port: port for accessing the DRAC interface :param path: path for accessing the DRAC interface :param protocol: protocol for accessing the DRAC interface + :param ssl_retries: number of resends to attempt on SSL failures + :param ssl_retry_delay: number of seconds to wait between + retries on SSL failures + :param ready_retries: number of times to check if the iDRAC is + ready + :param ready_retry_delay: number of seconds to wait between + checks if the iDRAC is ready """ self.client = WSManClient(host, username, password, port, path, - protocol) + protocol, ssl_retries, ssl_retry_delay, + ready_retries, ready_retry_delay) 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) + self._lifecycle_cfg = lifecycle_controller.LCConfiguration(self.client) + self._idrac_cfg = idrac_card.iDRACCardConfiguration(self.client) self._raid_mgmt = raid.RAIDManagement(self.client) + self._system_cfg = system.SystemConfiguration(self.client) self._inventory_mgmt = inventory.InventoryManagement(self.client) + self._nic_cfg = nic.NICConfiguration(self.client) def get_power_state(self): """Returns the current power state of the node @@ -147,9 +174,13 @@ def set_bios_settings(self, settings): :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. + :returns: a dictionary containing: + - The is_commit_required key with a boolean value indicating + whether a config job must be created for the values to be + applied. + - The is_reboot_required key with a RebootRequired enumerated + value indicating whether the server must be rebooted for the + values to be applied. Possible values are true and false. :raises: WSManRequestFailure on request failures :raises: WSManInvalidResponse when receiving invalid response :raises: DRACOperationFailed on error reported back by the DRAC @@ -159,6 +190,270 @@ def set_bios_settings(self, settings): """ return self._bios_cfg.set_bios_settings(settings) + def list_idrac_settings(self, by_name=False, fqdd_filter=IDRAC_FQDD): + """List the iDRAC configuration settings + + :param by_name: Controls whether returned dictionary uses iDRAC card + attribute name as key. If set to False, instance_id + will be used. If set to True the keys will be of the + form "group_id#name". + :param fqdd_filter: An FQDD used to filter the instances. Note that + this is only used when by_name is True. + :returns: a dictionary with the iDRAC settings using instance_id as the + key except when by_name is True. The attributes are either + iDRACCardEnumerableAttribute, iDRACCardStringAttribute or + iDRACCardIntegerAttribute objects. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface + """ + return self._idrac_cfg.list_idrac_settings(by_name=by_name, + fqdd_filter=fqdd_filter) + + def set_idrac_settings(self, settings, idrac_fqdd=IDRAC_FQDD): + """Sets the iDRAC configuration settings + + 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 may + need to be created and the node may need to be rebooted. + + :param settings: a dictionary containing the proposed values, with + each key being the name of attribute qualified with + the group ID in the form "group_id#name" and the value + being the proposed value. + :param idrac_fqdd: the FQDD of the iDRAC. + :returns: a dictionary containing: + - The is_commit_required key with a boolean value indicating + whether a config job must be created for the values to be + applied. + - The is_reboot_required key with a RebootRequired enumerated + value indicating whether the server must be rebooted for the + values to be applied. Possible values are true and false. + :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 attribute + """ + return self._idrac_cfg.set_idrac_settings(settings, idrac_fqdd) + + def reset_idrac(self, force=False, wait=False, + ready_wait_time=30): + """Resets the iDRAC and optionally block until reset is complete. + + :param force: does a force reset when True and a graceful reset when + False + :param wait: returns immediately after reset if False, or waits + for the iDRAC to return to operational state if True + :param ready_wait_time: the amount of time in seconds to wait after + the reset before starting to check on the iDRAC's status + :returns: True on success, raises exception on failure + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on failure to reset iDRAC + """ + return_value = self._idrac_cfg.reset_idrac(force) + if not wait and return_value: + return return_value + + if not return_value: + raise exceptions.DRACOperationFailed( + drac_messages="Failed to reset iDRAC") + + LOG.debug("iDRAC was reset, waiting for return to operational state") + + state_reached = self._wait_for_host_state( + self.client.host, + alive=False, + ping_count=2, + retries=24) + + if not state_reached: + raise exceptions.DRACOperationFailed( + drac_messages="Timed out waiting for the %s iDRAC to become " + "not pingable" % self.client.host) + + LOG.info("The iDRAC has become not pingable") + + state_reached = self._wait_for_host_state( + self.client.host, + alive=True, + ping_count=3, + retries=24) + + if not state_reached: + raise exceptions.DRACOperationFailed( + drac_messages="Timed out waiting for the %s iDRAC to become " + "pingable" % self.client.host) + + LOG.info("The iDRAC has become pingable") + LOG.info("Waiting for the iDRAC to become ready") + time.sleep(ready_wait_time) + + self.client.wait_until_idrac_is_ready() + + def _ping_host(self, host): + response = subprocess.call( + "ping -c 1 {} 2>&1 1>/dev/null".format(host), shell=True) + return (response == 0) + + def _wait_for_host_state(self, + host, + alive=True, + ping_count=3, + retries=24): + if alive: + ping_type = "pingable" + + else: + ping_type = "not pingable" + + LOG.info("Waiting for the iDRAC to become %s", ping_type) + + response_count = 0 + state_reached = False + + while retries > 0 and not state_reached: + response = self._ping_host(host) + retries -= 1 + if response == alive: + response_count += 1 + LOG.debug("The iDRAC is %s, count=%s", + ping_type, + response_count) + if response_count == ping_count: + LOG.debug("Reached specified ping count") + state_reached = True + else: + response_count = 0 + if alive: + LOG.debug("The iDRAC is still not pingable") + else: + LOG.debug("The iDRAC is still pingable") + time.sleep(10) + + return state_reached + + def commit_pending_idrac_changes( + self, + idrac_fqdd=IDRAC_FQDD, + reboot=False, + start_time='TIME_NOW'): + """Create a config job for applying all pending iDRAC changes. + + :param idrac_fqdd: the FQDD of the iDRAC. + :param reboot: indication of whether to also create a reboot job + :param start_time: start time for job execution in format + yyyymmddhhmmss, the string 'TIME_NOW' which + means execute immediately or None which means + the job will not execute until + schedule_job_execution is called + :returns: id of the created configuration job + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the iDRAC + interface + :raises: DRACUnexpectedReturnValue on return value mismatch + """ + return self._job_mgmt.create_config_job( + resource_uri=uris.DCIM_iDRACCardService, + cim_creation_class_name='DCIM_iDRACCardService', + cim_name='DCIM:iDRACCardService', + target=idrac_fqdd, + reboot=reboot, + start_time=start_time) + + def abandon_pending_idrac_changes(self, idrac_fqdd=IDRAC_FQDD): + """Abandon all pending changes to an iDRAC + + Once a config job has been submitted, it can no longer be abandoned. + + :param idrac_fqdd: the FQDD of the iDRAC. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the iDRAC + interface + :raises: DRACUnexpectedReturnValue on return value mismatch + """ + self._job_mgmt.delete_pending_config( + resource_uri=uris.DCIM_iDRACCardService, + cim_creation_class_name='DCIM_iDRACCardService', + cim_name='DCIM:iDRACCardService', + target=idrac_fqdd) + + def list_lifecycle_settings(self, by_name=False): + """List the Lifecycle Controller configuration settings + + :param by_name: Controls whether returned dictionary uses Lifecycle + attribute name as key. If set to False, instance_id + will be used. + :returns: a dictionary with the Lifecycle Controller settings using its + InstanceID as the key. The attributes are either + LCEnumerableAttribute or LCStringAttribute objects. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface + """ + return self._lifecycle_cfg.list_lifecycle_settings(by_name) + + def is_lifecycle_in_recovery(self): + """Checks if Lifecycle Controller in recovery mode or not + + This method checks the LCStatus value to determine if lifecycle + controller is in recovery mode by invoking GetRemoteServicesAPIStatus + from iDRAC. + + :returns: a boolean indicating if lifecycle controller is in recovery + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface + """ + + return self._lifecycle_cfg.is_lifecycle_in_recovery() + + def set_lifecycle_settings(self, settings): + """Sets lifecycle controller configuration + + 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. + + :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 is_commit_required key with a boolean value indicating + whether a config job must be created for the values to be + applied. + - The is_reboot_required key with a RebootRequired enumerated + value indicating whether the server must be rebooted for the + values to be applied. Possible values are true and false. + :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 Lifecycle attribute + """ + return self._lifecycle_cfg.set_lifecycle_settings(settings) + + def list_system_settings(self): + """List the System configuration settings + + :returns: a dictionary with the System settings using its instance id + as key. The attributes are either SystemEnumerableAttribute, + SystemStringAttribute or SystemIntegerAttribute objects. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface + """ + return self._system_cfg.list_system_settings() + def list_jobs(self, only_unfinished=False): """Returns a list of jobs from the job queue @@ -184,12 +479,40 @@ def get_job(self, job_id): """ return self._job_mgmt.get_job(job_id) - def create_config_job(self, resource_uri, cim_creation_class_name, - cim_name, target, + def delete_jobs(self, job_ids=['JID_CLEARALL']): + """Deletes the given jobs, or all jobs if none specified + + :param job_ids: a list of job ids to delete. Clearing all the + jobs may be accomplished using the keyword JID_CLEARALL + as the job_id, or JID_CLEARALL_FORCE if a job is in + Scheduled state and there is another job for the same + component in Completed or Failed state, + (http://en.community.dell.com/techcenter/extras/m/white_papers/20444501/download) + Deletion of each job id will be attempted, even if there + are errors in deleting any in the list. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the iDRAC + interface. There will be one message for each job_id + that had a failure in the exception. + :raises: DRACUnexpectedReturnValue on non-success + """ + + return self._job_mgmt.delete_jobs(job_ids) + + def create_config_job(self, + resource_uri, + cim_creation_class_name, + cim_name, + target, cim_system_creation_class_name='DCIM_ComputerSystem', cim_system_name='DCIM:ComputerSystem', - reboot=False): - """Creates a config job + reboot=False, + start_time='TIME_NOW', + realtime=False, + wait_for_idrac=True, + method_name='CreateTargetedConfigJob'): + """Creates a configuration job. In CIM (Common Information Model), weak association is used to name an instance of one class in the context of an instance of another class. @@ -205,18 +528,99 @@ def create_config_job(self, resource_uri, cim_creation_class_name, :param cim_system_creation_class_name: creation class name of the scoping system :param cim_system_name: name of the scoping system - :param reboot: indicates whether a RebootJob should also be - created or not + :param reboot: indicates whether or not a RebootJob should also be + created + :param start_time: start time for job execution in format + yyyymmddhhmmss, the string 'TIME_NOW' which + means execute immediately or None which means + the job will not execute until + schedule_job_execution is called + :param realtime: Indicates if reatime mode should be used. + Valid values are True and False. + :param wait_for_idrac: indicates whether or not to wait for the + iDRAC to be ready to accept commands before + issuing the command. + :param method_name: method of CIM object to invoke :returns: id of the created job :raises: WSManRequestFailure on request failures :raises: WSManInvalidResponse when receiving invalid response - :raises: DRACOperationFailed on error reported back by the DRAC + :raises: DRACOperationFailed on error reported back by the iDRAC interface :raises: DRACUnexpectedReturnValue on return value mismatch """ + return self._job_mgmt.create_config_job( - resource_uri, cim_creation_class_name, cim_name, target, - cim_system_creation_class_name, cim_system_name, reboot) + resource_uri=resource_uri, + cim_creation_class_name=cim_creation_class_name, + cim_name=cim_name, + target=target, + cim_system_creation_class_name=cim_system_creation_class_name, + cim_system_name=cim_system_name, + reboot=reboot, + start_time=start_time, + realtime=realtime, + wait_for_idrac=wait_for_idrac, + method_name=method_name) + + def create_nic_config_job( + self, + nic_id, + reboot=False, + start_time='TIME_NOW'): + """Creates config job for applying pending changes to a NIC. + + :param nic_id: id of the network interface controller (NIC) + :param reboot: indication of whether to also create a reboot job + :param start_time: start time for job execution in format + yyyymmddhhmmss; the string 'TIME_NOW' means + immediately and None means unspecified + :returns: id of the created configuration job + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the iDRAC + interface + :raises: DRACUnexpectedReturnValue on return value mismatch + """ + return self._job_mgmt.create_config_job( + resource_uri=uris.DCIM_NICService, + cim_creation_class_name='DCIM_NICService', + cim_name='DCIM:NICService', + target=nic_id, + reboot=reboot, + start_time=start_time) + + def create_reboot_job( + self, + reboot_type=constants.RebootJobType.reboot_forced_shutdown): + """Creates a reboot job. + + :param reboot_type: type of reboot + :returns id of the created job + :raises: InvalidParameterValue on invalid reboot type + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the iDRAC + interface + :raises: DRACUnexpectedReturnValue on return value mismatch + """ + return self._job_mgmt.create_reboot_job(reboot_type) + + def schedule_job_execution(self, job_ids, start_time='TIME_NOW'): + """Schedules jobs for execution in a specified order. + + :param job_ids: list of job identifiers + :param start_time: start time for job execution in format + yyyymmddhhmmss or the string 'TIME_NOW' which + means execute immediately. None is not a + valid option for this request. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the iDRAC + interface, including start_time being in the past or + badly formatted start_time + :raises: DRACUnexpectedReturnValue on return value mismatch + """ + return self._job_mgmt.schedule_job_execution(job_ids, start_time) def delete_pending_config( self, resource_uri, cim_creation_class_name, cim_name, target, @@ -250,23 +654,34 @@ def delete_pending_config( resource_uri, cim_creation_class_name, cim_name, target, cim_system_creation_class_name, cim_system_name) - def commit_pending_bios_changes(self, reboot=False): + def commit_pending_bios_changes( + self, + reboot=False, + start_time='TIME_NOW'): """Applies all pending changes on the BIOS by creating a config job :param reboot: indicates whether a RebootJob should also be created or not + :param start_time: start time for job execution in format + yyyymmddhhmmss, the string 'TIME_NOW' which + means execute immediately or None which means + the job will not execute until + schedule_job_execution is called :returns: id of the created job :raises: WSManRequestFailure on request failures :raises: WSManInvalidResponse when receiving invalid response :raises: DRACOperationFailed on error reported back by the DRAC - interface + interface, including start_time being in the past or + badly formatted start_time :raises: DRACUnexpectedReturnValue on return value mismatch """ 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, - reboot=reboot) + cim_name='DCIM:BIOSService', + target=self.BIOS_DEVICE_FQDD, + reboot=reboot, + start_time=start_time) def abandon_pending_bios_changes(self): """Deletes all pending changes on the BIOS @@ -284,6 +699,37 @@ def abandon_pending_bios_changes(self): cim_creation_class_name='DCIM_BIOSService', cim_name='DCIM:BIOSService', target=self.BIOS_DEVICE_FQDD) + def commit_pending_lifecycle_changes( + self, + reboot=False, + start_time='TIME_NOW'): + """Applies all pending changes on Lifecycle by creating a config job + + :param reboot: indicates whether a RebootJob should also be + created or not + :param start_time: start time for job execution in format + yyyymmddhhmmss, the string 'TIME_NOW' which + means execute immediately or None which means + the job will not execute until + schedule_job_execution is called + :returns: id of the created job + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface, including start_time being in the past or + badly formatted start_time + :raises: DRACUnexpectedReturnValue on return value mismatch + """ + return self._job_mgmt.create_config_job( + resource_uri=uris.DCIM_LCService, + cim_creation_class_name='DCIM_LCService', + cim_name='DCIM:LCService', + target='', + reboot=reboot, + start_time=start_time, + wait_for_idrac=False, + method_name='CreateConfigJob') + def get_lifecycle_controller_version(self): """Returns the Lifecycle controller version @@ -307,6 +753,43 @@ def list_raid_controllers(self): """ return self._raid_mgmt.list_raid_controllers() + def list_raid_settings(self): + """List the RAID configuration settings + + :returns: a dictionary with the RAID settings using InstanceID as the + key. The attributes are either RAIDEnumerableAttribute, + RAIDStringAttribute objects. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface + """ + return self._raid_mgmt.list_raid_settings() + + def set_raid_settings(self, raid_fqdd, settings): + """Sets the RAID configuration + + 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. + :param raid_fqdd: the FQDD of the RAID setting. + :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 is_commit_required key with a boolean value indicating + whether a config job must be created for the values to be + applied. + - The is_reboot_required key with a RebootRequired enumerated + value indicating whether the server must be rebooted for the + values to be applied. Possible values are true and false. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface + """ + return self._raid_mgmt.set_raid_settings(raid_fqdd, settings) + def list_virtual_disks(self): """Returns the list of RAID arrays @@ -341,12 +824,16 @@ def convert_physical_disks(self, raid_controller, physical_disks, :param raid_enable: boolean flag, set to True if the disk is to become part of the RAID. The same flag is applied to all listed disks - :returns: a dictionary containing the commit_required key with a - boolean value indicating whether a config job must be - created for the values to be applied. + :returns: a dictionary containing: + - The is_commit_required key with the value always set to + True indicating that a config job must be created to + complete disk conversion. + - The is_reboot_required key with a RebootRequired enumerated + value indicating whether the server must be rebooted to + complete disk conversion. """ - return self._raid_mgmt.convert_physical_disks( - physical_disks, raid_enable) + return self._raid_mgmt.convert_physical_disks(physical_disks, + raid_enable) def create_virtual_disk(self, raid_controller, physical_disks, raid_level, size_mb, disk_name=None, span_length=None, @@ -362,9 +849,13 @@ def create_virtual_disk(self, raid_controller, physical_disks, raid_level, :param disk_name: name of the virtual disk (optional) :param span_length: number of disks per span (optional) :param span_depth: number of spans in virtual disk (optional) - :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. + :returns: a dictionary containing: + - The is_commit_required key with the value always set to + True indicating that a config job must be created to + complete virtual disk creation. + - The is_reboot_required key with a RebootRequired enumerated + value indicating whether the server must be rebooted to + complete virtual disk creation. :raises: WSManRequestFailure on request failures :raises: WSManInvalidResponse when receiving invalid response :raises: DRACOperationFailed on error reported back by the DRAC @@ -383,9 +874,13 @@ def delete_virtual_disk(self, virtual_disk): be applied, a config job must be created and the node must be rebooted. :param virtual_disk: id of the virtual disk - :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. + :returns: a dictionary containing: + - The is_commit_required key with the value always set to + True indicating that a config job must be created to + complete virtual disk deletion. + - The is_reboot_required key with a RebootRequired enumerated + value indicating whether the server must be rebooted to + complete virtual disk deletion. :raises: WSManRequestFailure on request failures :raises: WSManInvalidResponse when receiving invalid response :raises: DRACOperationFailed on error reported back by the DRAC @@ -394,7 +889,52 @@ def delete_virtual_disk(self, virtual_disk): """ return self._raid_mgmt.delete_virtual_disk(virtual_disk) - def commit_pending_raid_changes(self, raid_controller, reboot=False): + def reset_raid_config(self, raid_controller): + """Delete all the virtual disks and unassign all hot spare physical disks + + The job to reset the RAID controller config will be in pending state. + For the changes to be applied, a config job must be created. + + :param raid_controller: id of the RAID controller + :returns: a dictionary containing: + - The is_commit_required key with the value always set to + True indicating that a config job must be created to + reset configuration. + - The is_reboot_required key with a RebootRequired enumerated + value indicating whether the server must be rebooted to + reset configuration. + :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 + """ + return self._raid_mgmt.reset_raid_config(raid_controller) + + def clear_foreign_config(self, raid_controller): + """Free up foreign drives + + The job to clear foreign config will be in pending state. + For the changes to be applied, a config job must be created. + + :param raid_controller: id of the RAID controller + :returns: a dictionary containing: + - The is_commit_required key with the value always set to + True indicating that a config job must be created to + clear foreign configuration. + - The is_reboot_required key with a RebootRequired enumerated + value indicating whether the server must be rebooted to + clear foreign configuration. + :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 + """ + return self._raid_mgmt.clear_foreign_config(raid_controller) + + def commit_pending_raid_changes(self, raid_controller, reboot=False, + start_time='TIME_NOW', realtime=False): """Applies all pending changes on a RAID controller ...by creating a config job. @@ -402,6 +942,13 @@ def commit_pending_raid_changes(self, raid_controller, reboot=False): :param raid_controller: id of the RAID controller :param reboot: indicates whether a RebootJob should also be created or not + :param start_time: start time for job execution in format + yyyymmddhhmmss, the string 'TIME_NOW' which + means execute immediately or None which means + the job will not execute until + schedule_job_execution is called + :param realtime: Indicates if reatime mode should be used. + Valid values are True and False. :returns: id of the created job :raises: WSManRequestFailure on request failures :raises: WSManInvalidResponse when receiving invalid response @@ -412,7 +959,11 @@ def commit_pending_raid_changes(self, raid_controller, reboot=False): return self._job_mgmt.create_config_job( resource_uri=uris.DCIM_RAIDService, cim_creation_class_name='DCIM_RAIDService', - cim_name='DCIM:RAIDService', target=raid_controller, reboot=reboot) + cim_name='DCIM:RAIDService', + target=raid_controller, + reboot=reboot, + start_time=start_time, + realtime=realtime) def abandon_pending_raid_changes(self, raid_controller): """Deletes all pending changes on a RAID controller @@ -431,6 +982,14 @@ def abandon_pending_raid_changes(self, raid_controller): cim_creation_class_name='DCIM_RAIDService', cim_name='DCIM:RAIDService', target=raid_controller) + def is_realtime_supported(self, raid_controller): + """Find if controller supports realtime or not + + :param raid_controller: ID of RAID controller + :returns: True or False + """ + return self._raid_mgmt.is_realtime_supported(raid_controller) + def list_cpus(self): """Returns the list of CPUs @@ -454,9 +1013,10 @@ def list_memory(self): return self._inventory_mgmt.list_memory() - def list_nics(self): + def list_nics(self, sort=False): """Returns a list of NICs + :param sort: indicates if the list should be sorted or not. :returns: a list of NIC objects :raises: WSManRequestFailure on request failures :raises: WSManInvalidResponse when receiving invalid response @@ -464,14 +1024,249 @@ def list_nics(self): interface """ - return self._inventory_mgmt.list_nics() + return self._inventory_mgmt.list_nics(sort=sort) + + def list_nic_settings(self, nic_id): + """Return the list of attribute settings of a NIC. + + :param nic_id: id of the network interface controller (NIC) + :returns: dictionary containing the NIC settings. The keys are + attribute names. Each value is a + NICEnumerationAttribute, NICIntegerAttribute, or + NICStringAttribute object. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the iDRAC + interface + """ + return self._nic_cfg.list_nic_settings(nic_id) + + def set_nic_settings(self, nic_id, settings): + """Modify one or more settings of a NIC. + + If successful, the pending values of the attributes are set. For + the new values to be applied, a configuration job must be + created and the node must be rebooted. + + :param nic_id: id of the network interface controller (NIC) + :param settings: dictionary containing the proposed values, with + each key being the name of an attribute and the + value being the proposed value + :returns: dictionary containing: + - The is_commit_required key with a boolean value + indicating whether a config job must be created for + the values to be applied. + - The is_reboot_required key with a RebootRequired + enumerated value indicating whether the server must + be rebooted 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 iDRAC + interface + :raises: InvalidParameterValue on invalid NIC attribute + """ + return self._nic_cfg.set_nic_settings(nic_id, settings) + + def get_system(self): + """Return a Systen object. + + :returns: a System object + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + """ + return self._inventory_mgmt.get_system() + + def is_idrac_ready(self): + """Indicates if the iDRAC is ready to accept commands + + Returns a boolean indicating if the iDRAC is ready to accept + commands. + + :returns: Boolean indicating iDRAC readiness + :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 + """ + + return self.client.is_idrac_ready() + + def wait_until_idrac_is_ready(self, retries=None, retry_delay=None): + """Waits until the iDRAC is in a ready state + + :param retries: The number of times to check if the iDRAC is + ready. If None, the value of ready_retries that + was provided when the object was created is + used. + :param retry_delay: The number of seconds to wait between + retries. If None, the value of + ready_retry_delay that was provided + when the object was created is used. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface or timeout + :raises: DRACUnexpectedReturnValue on return value mismatch + """ + + return self.client.wait_until_idrac_is_ready(retries, retry_delay) + + def is_jbod_capable(self, raid_controller_fqdd): + """Find out if raid controller supports jbod + + :param raid_controller_fqdd: The raid controller's fqdd + being checked to see if it is jbod + capable. + :raises: DRACRequestFailed if unable to find any disks in the Ready + or non-RAID states + :raises: DRACOperationFailed on error reported back by the DRAC + and the exception message does not contain + NOT_SUPPORTED_MSG constant + """ + return self._raid_mgmt.is_jbod_capable(raid_controller_fqdd) + + def is_raid_controller(self, raid_controller_fqdd, raid_controllers=None): + """Determine if the given controller is a RAID controller + + Since a BOSS controller is a type of RAID controller, this method will + return True for both BOSS and RAID controllers. + + :param raid_controller_fqdd: The object's fqdd we are testing to see + if it is a raid controller or not. + :param raid_controllers: A list of RAIDControllers used to check for + the presence of BOSS cards. If None, the + iDRAC will be queried for the list of + controllers. + :returns: boolean, True if the device is a RAID controller, + False if not. + """ + return self._raid_mgmt.is_raid_controller(raid_controller_fqdd, + raid_controllers) + + def is_boss_controller(self, raid_controller_fqdd, raid_controllers=None): + """Find out if a RAID controller a BOSS card or not + + :param raid_controller_fqdd: The object's fqdd we are testing to see + if it is a BOSS card or not. + :param raid_controllers: A list of RAIDController to scan for presence + of BOSS card, if None the drac will be queried + for the list of controllers which will then be + scanned. + :returns: boolean, True if the device is a BOSS card, False if not. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface + """ + return self._raid_mgmt.is_boss_controller(raid_controller_fqdd, + raid_controllers) + + def change_physical_disk_state(self, mode, + controllers_to_physical_disk_ids=None): + """Convert disks RAID status + + This method intelligently converts the requested physical disks from + RAID to JBOD or vice versa. It does this by only converting the + disks that are not already in the correct state. + + :param mode: constants.RaidStatus enumeration that indicates the mode + to change the disks to. + :param controllers_to_physical_disk_ids: Dictionary of controllers and + corresponding disk ids to convert to the requested mode. + :returns: a dictionary containing: + - conversion_results, a dictionary that maps controller ids + to the conversion results for that controller. The + conversion results are a dict that contains: + - The is_commit_required key with the value always set to + True indicating that a config job must be created to + complete disk conversion. + - The is_reboot_required key with a RebootRequired + enumerated value indicating whether the server must be + rebooted to complete disk conversion. + :raises: DRACOperationFailed on error reported back by the DRAC and the + exception message does not contain NOT_SUPPORTED_MSG constant. + :raises: Exception on unknown error. + """ + return (self._raid_mgmt + .change_physical_disk_state(mode, + controllers_to_physical_disk_ids)) class WSManClient(wsman.Client): - """Wrapper for wsman.Client with return value checking""" + """Wrapper for wsman.Client that can wait until iDRAC is ready + + Additionally, the Invoke operation offers return value checking. + """ + + def __init__( + self, host, username, password, port=443, path='/wsman', + protocol='https', + ssl_retries=constants.DEFAULT_WSMAN_SSL_ERROR_RETRIES, + ssl_retry_delay=constants.DEFAULT_WSMAN_SSL_ERROR_RETRY_DELAY_SEC, + ready_retries=constants.DEFAULT_IDRAC_IS_READY_RETRIES, + ready_retry_delay=( + constants.DEFAULT_IDRAC_IS_READY_RETRY_DELAY_SEC)): + """Creates client object - def invoke(self, resource_uri, method, selectors=None, properties=None, - expected_return_value=None): + :param host: hostname or IP of the DRAC interface + :param username: username for accessing the DRAC interface + :param password: password for accessing the DRAC interface + :param port: port for accessing the DRAC interface + :param path: path for accessing the DRAC interface + :param protocol: protocol for accessing the DRAC interface + :param ssl_retries: number of resends to attempt on SSL failures + :param ssl_retry_delay: number of seconds to wait between + retries on SSL failures + :param ready_retries: number of times to check if the iDRAC is + ready + :param ready_retry_delay: number of seconds to wait between + checks if the iDRAC is ready + """ + super(WSManClient, self).__init__(host, username, password, + port, path, protocol, ssl_retries, + ssl_retry_delay) + + self._ready_retries = ready_retries + self._ready_retry_delay = ready_retry_delay + + def enumerate(self, resource_uri, optimization=True, max_elems=100, + auto_pull=True, filter_query=None, filter_dialect='cql', + wait_for_idrac=True): + """Executes enumerate operation over WS-Man + + :param resource_uri: URI of resource to enumerate + :param optimization: flag to enable enumeration optimization. If + disabled, the enumeration returns only an + enumeration context. + :param max_elems: maximum number of elements returned by the operation + :param auto_pull: flag to enable automatic pull on the enumeration + context, merging the items returned + :param filter_query: filter query string + :param filter_dialect: filter dialect. Valid options are: 'cql' and + 'wql'. + :param wait_for_idrac: indicates whether or not to wait for the + iDRAC to be ready to accept commands before issuing the + command + :returns: an lxml.etree.Element object of the response received + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + """ + if wait_for_idrac: + self.wait_until_idrac_is_ready() + + return super(WSManClient, self).enumerate(resource_uri, optimization, + max_elems, auto_pull, + filter_query, filter_dialect) + + def invoke(self, + resource_uri, + method, + selectors=None, + properties=None, + expected_return_value=None, + wait_for_idrac=True, + check_return_value=True): """Invokes a remote WS-Man method :param resource_uri: URI of the resource @@ -482,6 +1277,11 @@ def invoke(self, resource_uri, method, selectors=None, properties=None, the DRAC card. For return value codes check the profile documentation of the resource used in the method call. If not set, return value checking is skipped. + :param wait_for_idrac: indicates whether or not to wait for the + iDRAC to be ready to accept commands before issuing the + command + :param check_return_value: indicates if the ReturnValue should be + checked and an exception thrown on an unexpected value :returns: an lxml.etree.Element object of the response received :raises: WSManRequestFailure on request failures :raises: WSManInvalidResponse when receiving invalid response @@ -489,6 +1289,9 @@ def invoke(self, resource_uri, method, selectors=None, properties=None, interface :raises: DRACUnexpectedReturnValue on return value mismatch """ + if wait_for_idrac: + self.wait_until_idrac_is_ready() + if selectors is None: selectors = {} @@ -498,16 +1301,94 @@ def invoke(self, resource_uri, method, selectors=None, properties=None, resp = super(WSManClient, self).invoke(resource_uri, method, selectors, properties) - return_value = utils.find_xml(resp, 'ReturnValue', resource_uri).text - if return_value == utils.RET_ERROR: - message_elems = utils.find_xml(resp, 'Message', resource_uri, True) - messages = [message_elem.text for message_elem in message_elems] - raise exceptions.DRACOperationFailed(drac_messages=messages) - - if (expected_return_value is not None and - return_value != expected_return_value): - raise exceptions.DRACUnexpectedReturnValue( - expected_return_value=expected_return_value, - actual_return_value=return_value) + if check_return_value: + return_value = utils.find_xml(resp, 'ReturnValue', + resource_uri).text + if return_value == utils.RET_ERROR: + message_elems = utils.find_xml(resp, 'Message', + resource_uri, True) + messages = [message_elem.text for message_elem in + message_elems] + raise exceptions.DRACOperationFailed(drac_messages=messages) + + if (expected_return_value is not None + and return_value != expected_return_value): + raise exceptions.DRACUnexpectedReturnValue( + expected_return_value=expected_return_value, + actual_return_value=return_value) return resp + + def is_idrac_ready(self): + """Indicates if the iDRAC is ready to accept commands + + Returns a boolean indicating if the iDRAC is ready to accept + commands. + + :returns: Boolean indicating iDRAC readiness + :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 + """ + + selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'DCIM:ComputerSystem', + 'CreationClassName': 'DCIM_LCService', + 'Name': 'DCIM:LCService'} + + result = self.invoke(uris.DCIM_LCService, + 'GetRemoteServicesAPIStatus', + selectors, + {}, + expected_return_value=utils.RET_SUCCESS, + wait_for_idrac=False) + + lc_status = utils.find_xml(result, + 'LCStatus', + uris.DCIM_LCService).text + + return lc_status == IDRAC_IS_READY + + def wait_until_idrac_is_ready(self, retries=None, retry_delay=None): + """Waits until the iDRAC is in a ready state + + :param retries: The number of times to check if the iDRAC is + ready. If None, the value of ready_retries that + was provided when the object was created is + used. + :param retry_delay: The number of seconds to wait between + retries. If None, the value of + ready_retry_delay that was provided when the + object was created is used. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface or timeout + :raises: DRACUnexpectedReturnValue on return value mismatch + """ + + if retries is None: + retries = self._ready_retries + + if retry_delay is None: + retry_delay = self._ready_retry_delay + + # Try every 10 seconds over 4 minutes for the iDRAC to become ready + while retries > 0: + LOG.debug("Checking to see if the iDRAC is ready") + + if self.is_idrac_ready(): + LOG.debug("The iDRAC is ready") + return + + LOG.debug("The iDRAC is not ready") + retries -= 1 + if retries > 0: + time.sleep(retry_delay) + + if retries == 0: + err_msg = "Timed out waiting for the iDRAC to become ready" + LOG.error(err_msg) + raise exceptions.DRACOperationFailed(drac_messages=err_msg) diff --git a/dracclient/constants.py b/dracclient/constants.py index 5705d76..ecaffa1 100644 --- a/dracclient/constants.py +++ b/dracclient/constants.py @@ -11,6 +11,17 @@ # License for the specific language governing permissions and limitations # under the License. +# iDRAC is ready retry constants +DEFAULT_IDRAC_IS_READY_RETRIES = 96 +DEFAULT_IDRAC_IS_READY_RETRY_DELAY_SEC = 10 + +# Web Services Management (WS-Management and WS-Man) SSL retry on error +# behavior constants +DEFAULT_WSMAN_SSL_ERROR_RETRIES = 3 +DEFAULT_WSMAN_SSL_ERROR_RETRY_DELAY_SEC = 0 + +NOT_SUPPORTED_MSG = " operation is not supported on th" + # power states POWER_ON = 'POWER_ON' POWER_OFF = 'POWER_OFF' @@ -25,3 +36,58 @@ # binary unit constants UNITS_KI = 2 ** 10 + +# Lifecycle Controller status constant +LC_IN_RECOVERY = '4' + + +# Reboot required indicator +# Note: When the iDRAC returns optional for this value, this indicates that +# either a reboot may be performed to complete the operation or a real time +# config job may be created to complete the operation without performing a +# reboot. This library does not currently support creating a real time config +# job, so a reboot must be performed when a value of "optional" is returned. +class RebootRequired(object): + true = 'true' + optional = 'optional' + false = 'false' + + @classmethod + def all(cls): + return [cls.true, cls.optional, cls.false] + + +class RebootJobType(object): + """Enumeration of different reboot job types.""" + + power_cycle = 'power_cycle' + """Hard power off, power on cycle""" + + graceful_reboot = 'graceful_reboot' + """OS level reboot and wait for OS shutdown""" + + reboot_forced_shutdown = 'reboot_forced_shutdown' + """OS level reboot and force power cycle if OS does not shut + down + """ + + @classmethod + def all(cls): + return [cls.power_cycle, + cls.graceful_reboot, + cls.reboot_forced_shutdown] + + +class RaidStatus(object): + """Enumeration of different volume types.""" + + jbod = 'JBOD' + """Just a Bunch of Disks""" + + raid = 'RAID' + """Redundant Array of Independent Disks""" + + @classmethod + def all(cls): + return [cls.jbod, + cls.raid] diff --git a/dracclient/resources/bios.py b/dracclient/resources/bios.py index 263ef65..194d029 100644 --- a/dracclient/resources/bios.py +++ b/dracclient/resources/bios.py @@ -20,7 +20,6 @@ from dracclient.resources import lifecycle_controller from dracclient.resources import uris from dracclient import utils -from dracclient import wsman LOG = logging.getLogger(__name__) @@ -74,8 +73,7 @@ def get_power_state(self): interface """ - filter_query = ('select EnabledState from ' - 'DCIM_ComputerSystem where Name="srv:system"') + filter_query = ('select EnabledState from DCIM_ComputerSystem') doc = self.client.enumerate(uris.DCIM_ComputerSystem, filter_query=filter_query) enabled_state = utils.find_xml(doc, 'EnabledState', @@ -421,7 +419,7 @@ def __init__(self, name, instance_id, current_value, pending_value, 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 + :param upper_bound: maximum value for the BIOS attribute """ super(BIOSIntegerAttribute, self).__init__(name, instance_id, current_value, @@ -464,6 +462,10 @@ def validate(self, new_value): class BIOSConfiguration(object): + NAMESPACES = [(uris.DCIM_BIOSEnumeration, BIOSEnumerableAttribute), + (uris.DCIM_BIOSString, BIOSStringAttribute), + (uris.DCIM_BIOSInteger, BIOSIntegerAttribute)] + def __init__(self, client): """Creates BIOSConfiguration object @@ -485,33 +487,7 @@ def list_bios_settings(self, by_name=True): 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, by_name) - 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, by_name): - result = {} - - doc = self.client.enumerate(resource) - items = doc.find('.//{%s}Items' % wsman.NS_WSMAN) - - for item in items: - attribute = attr_cls.parse(item) - if by_name: - result[attribute.name] = attribute - else: - result[attribute.instance_id] = attribute - - return result + return utils.list_settings(self.client, self.NAMESPACES, by_name) def set_bios_settings(self, new_settings): """Sets the BIOS configuration @@ -523,9 +499,13 @@ def set_bios_settings(self, new_settings): :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. + :returns: a dictionary containing: + - The is_commit_required key with a boolean value indicating + whether a config job must be created for the values to be + applied. + - The is_reboot_required key with a RebootRequired enumerated + value indicating whether the server must be rebooted for the + values to be applied. Possible values are true and false. :raises: WSManRequestFailure on request failures :raises: WSManInvalidResponse when receiving invalid response :raises: DRACOperationFailed on error reported back by the DRAC @@ -534,68 +514,11 @@ def set_bios_settings(self, new_settings): :raises: InvalidParameterValue on invalid BIOS attribute """ - current_settings = self.list_bios_settings(by_name=True) - # BIOS settings are returned as dict indexed by InstanceID. - # However DCIM_BIOSService requires attribute name, not instance id - # so recreate this as a dict indexed by attribute name - # TODO(anish) : Enable this code if/when by_name gets deprecated - # bios_settings = self.list_bios_settings(by_name=False) - # current_settings = dict((value.name, value) - # for key, value in bios_settings.items()) - 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.warning('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) - - return {'commit_required': utils.is_reboot_required( - doc, uris.DCIM_BIOSService)} + return utils.set_settings('BIOS', + self.client, + self.NAMESPACES, + new_settings, + uris.DCIM_BIOSService, + "DCIM_BIOSService", + "DCIM:BIOSService", + 'BIOS.Setup.1-1') diff --git a/dracclient/resources/idrac_card.py b/dracclient/resources/idrac_card.py new file mode 100644 index 0000000..c4c69ca --- /dev/null +++ b/dracclient/resources/idrac_card.py @@ -0,0 +1,353 @@ +# +# 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. + +from dracclient.resources import uris +from dracclient import utils + + +class iDRACCardAttribute(object): + """Generic iDRACCard attribute class""" + + def __init__(self, name, instance_id, current_value, pending_value, + read_only, fqdd, group_id): + """Creates iDRACCardAttribute object + + :param name: name of the iDRACCard attribute + :param instance_id: InstanceID of the iDRACCard attribute + :param current_value: current value of the iDRACCard attribute + :param pending_value: pending value of the iDRACCard attribute, + reflecting an unprocessed change (eg. config job not completed) + :param read_only: indicates whether this iDRACCard attribute can be + changed + :param fqdd: Fully Qualified Device Description of the iDRACCard + Attribute + :param group_id: GroupID of the iDRACCard Attribute + """ + self.name = name + self.instance_id = instance_id + self.current_value = current_value + self.pending_value = pending_value + self.read_only = read_only + self.fqdd = fqdd + self.group_id = group_id + + def __eq__(self, other): + return self.__dict__ == other.__dict__ + + @classmethod + def parse(cls, namespace, idrac_attr_xml): + """Parses XML and creates iDRACCardAttribute object""" + + name = utils.get_wsman_resource_attr( + idrac_attr_xml, namespace, 'AttributeName') + instance_id = utils.get_wsman_resource_attr( + idrac_attr_xml, namespace, 'InstanceID') + current_value = utils.get_wsman_resource_attr( + idrac_attr_xml, namespace, 'CurrentValue', nullable=True) + pending_value = utils.get_wsman_resource_attr( + idrac_attr_xml, namespace, 'PendingValue', nullable=True) + read_only = utils.get_wsman_resource_attr( + idrac_attr_xml, namespace, 'IsReadOnly').lower() + fqdd = utils.get_wsman_resource_attr( + idrac_attr_xml, namespace, 'FQDD') + group_id = utils.get_wsman_resource_attr( + idrac_attr_xml, namespace, 'GroupID') + + return cls(name, instance_id, current_value, pending_value, + (read_only == 'true'), fqdd, group_id) + + +class iDRACCardEnumerableAttribute(iDRACCardAttribute): + """Enumerable iDRACCard attribute class""" + + namespace = uris.DCIM_iDRACCardEnumeration + + def __init__(self, name, instance_id, current_value, pending_value, + read_only, fqdd, group_id, possible_values): + """Creates iDRACCardEnumerableAttribute object + + :param name: name of the iDRACCard attribute + :param instance_id: InstanceID of the iDRACCard attribute + :param current_value: current value of the iDRACCard attribute + :param pending_value: pending value of the iDRACCard attribute, + reflecting an unprocessed change (eg. config job not completed) + :param read_only: indicates whether this iDRACCard attribute can be + changed + :param fqdd: Fully Qualified Device Description of the iDRACCard + Attribute + :param group_id: GroupID of the iDRACCard Attribute + :param possible_values: list containing the allowed values for the + iDRACCard attribute + """ + super(iDRACCardEnumerableAttribute, self).__init__(name, instance_id, + current_value, + pending_value, + read_only, fqdd, + group_id) + self.possible_values = possible_values + + @classmethod + def parse(cls, idrac_attr_xml): + """Parses XML and creates iDRACCardEnumerableAttribute object""" + + idrac_attr = iDRACCardAttribute.parse(cls.namespace, idrac_attr_xml) + possible_values = [attr.text for attr + in utils.find_xml(idrac_attr_xml, 'PossibleValues', + cls.namespace, find_all=True)] + + return cls(idrac_attr.name, idrac_attr.instance_id, + idrac_attr.current_value, idrac_attr.pending_value, + idrac_attr.read_only, idrac_attr.fqdd, idrac_attr.group_id, + 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 iDRACCardStringAttribute(iDRACCardAttribute): + """String iDRACCard attribute class""" + + namespace = uris.DCIM_iDRACCardString + + def __init__(self, name, instance_id, current_value, pending_value, + read_only, fqdd, group_id, min_length, max_length): + """Creates iDRACCardStringAttribute object + + :param name: name of the iDRACCard attribute + :param instance_id: InstanceID of the iDRACCard attribute + :param current_value: current value of the iDRACCard attribute + :param pending_value: pending value of the iDRACCard attribute, + reflecting an unprocessed change (eg. config job not completed) + :param read_only: indicates whether this iDRACCard attribute can be + changed + :param fqdd: Fully Qualified Device Description of the iDRACCard + Attribute + :param group_id: GroupID of the iDRACCard Attribute + :param min_length: minimum length of the string + :param max_length: maximum length of the string + """ + super(iDRACCardStringAttribute, self).__init__(name, instance_id, + current_value, + pending_value, + read_only, fqdd, + group_id) + self.min_length = min_length + self.max_length = max_length + + @classmethod + def parse(cls, idrac_attr_xml): + """Parses XML and creates iDRACCardStringAttribute object""" + + idrac_attr = iDRACCardAttribute.parse(cls.namespace, idrac_attr_xml) + min_length = int(utils.get_wsman_resource_attr( + idrac_attr_xml, cls.namespace, 'MinLength')) + max_length = int(utils.get_wsman_resource_attr( + idrac_attr_xml, cls.namespace, 'MaxLength')) + + return cls(idrac_attr.name, idrac_attr.instance_id, + idrac_attr.current_value, idrac_attr.pending_value, + idrac_attr.read_only, idrac_attr.fqdd, idrac_attr.group_id, + min_length, max_length) + + def validate(self, new_value): + """Validates new value""" + + val_len = len(new_value) + if val_len < self.min_length or val_len > self.max_length: + msg = ("Attribute '%(attr)s' cannot be set to value '%(val)s'." + " It must be between %(lower)d and %(upper)d characters in " + "length.") % { + 'attr': self.name, + 'val': new_value, + 'lower': self.min_length, + 'upper': self.max_length} + return msg + + +class iDRACCardIntegerAttribute(iDRACCardAttribute): + """Integer iDRACCard attribute class""" + + namespace = uris.DCIM_iDRACCardInteger + + def __init__(self, name, instance_id, current_value, pending_value, + read_only, fqdd, group_id, lower_bound, upper_bound): + """Creates iDRACCardIntegerAttribute object + + :param name: name of the iDRACCard attribute + :param instance_id: InstanceID of the iDRACCard attribute + :param current_value: current value of the iDRACCard attribute + :param pending_value: pending value of the iDRACCard attribute, + reflecting an unprocessed change (eg. config job not completed) + :param read_only: indicates whether this iDRACCard attribute can be + changed + :param fqdd: Fully Qualified Device Description of the iDRACCard + Attribute + :param group_id: GroupID of the iDRACCard Attribute + :param lower_bound: minimum value for the iDRACCard attribute + :param upper_bound: maximum value for the iDRACCard attribute + """ + super(iDRACCardIntegerAttribute, self).__init__(name, instance_id, + current_value, + pending_value, + read_only, fqdd, + group_id) + self.lower_bound = lower_bound + self.upper_bound = upper_bound + + @classmethod + def parse(cls, idrac_attr_xml): + """Parses XML and creates iDRACCardIntegerAttribute object""" + + idrac_attr = iDRACCardAttribute.parse(cls.namespace, idrac_attr_xml) + lower_bound = utils.get_wsman_resource_attr( + idrac_attr_xml, cls.namespace, 'LowerBound') + upper_bound = utils.get_wsman_resource_attr( + idrac_attr_xml, cls.namespace, 'UpperBound') + + if idrac_attr.current_value: + idrac_attr.current_value = int(idrac_attr.current_value) + if idrac_attr.pending_value: + idrac_attr.pending_value = int(idrac_attr.pending_value) + + return cls(idrac_attr.name, idrac_attr.instance_id, + idrac_attr.current_value, idrac_attr.pending_value, + idrac_attr.read_only, idrac_attr.fqdd, idrac_attr.group_id, + 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 iDRACCardConfiguration(object): + + NAMESPACES = [(uris.DCIM_iDRACCardEnumeration, + iDRACCardEnumerableAttribute), + (uris.DCIM_iDRACCardString, iDRACCardStringAttribute), + (uris.DCIM_iDRACCardInteger, iDRACCardIntegerAttribute)] + + def __init__(self, client): + """Creates an iDRACCardConfiguration object + + :param client: an instance of WSManClient + """ + self.client = client + + def list_idrac_settings(self, by_name=False, fqdd_filter=None): + """List the iDRACCard configuration settings + + :param by_name: Controls whether returned dictionary uses iDRAC card + attribute name as key. If set to False, instance_id + will be used. If set to True the keys will be of the + form "group_id#name". + :param fqdd_filter: An FQDD used to filter the instances. Note that + this is only used when by_name is True. + :returns: a dictionary with the iDRAC settings using instance_id as the + key except when by_name is True. The attributes are either + iDRACCArdEnumerableAttribute, iDRACCardStringAttribute or + iDRACCardIntegerAttribute objects. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface + """ + + return utils.list_settings(self.client, + self.NAMESPACES, + by_name=by_name, + fqdd_filter=fqdd_filter, + name_formatter=_name_formatter) + + def set_idrac_settings(self, new_settings, idrac_fqdd): + """Set the iDRACCard configuration settings + + 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 may + need to be created and the node may need to be rebooted. + + :param new_settings: a dictionary containing the proposed values, with + each key being the name of attribute qualified + with the group ID in the form "group_id#name" and + the value being the proposed value. + :param idrac_fqdd: the FQDD of the iDRAC. + :returns: a dictionary containing: + - The is_commit_required key with a boolean value indicating + whether a config job must be created for the values to be + applied. + - The is_reboot_required key with a RebootRequired enumerated + value indicating whether the server must be rebooted for the + values to be applied. Possible values are true and false. + :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 attribute + """ + return utils.set_settings('iDRAC Card', + self.client, + self.NAMESPACES, + new_settings, + uris.DCIM_iDRACCardService, + "DCIM_iDRACCardService", + "DCIM:iDRACCardService", + idrac_fqdd, + name_formatter=_name_formatter) + + def reset_idrac(self, force=False): + """Resets the iDRAC + + :param force: does a force reset when True and a graceful reset when + False. + :returns: True on success and False on failure. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + """ + selectors = {'CreationClassName': "DCIM_iDRACCardService", + 'Name': "DCIM:iDRACCardService", + 'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'DCIM:ComputerSystem'} + + properties = {'Force': "1" if force else "0"} + + doc = self.client.invoke(uris.DCIM_iDRACCardService, + 'iDRACReset', + selectors, + properties, + check_return_value=False) + + message_id = utils.find_xml(doc, + 'MessageID', + uris.DCIM_iDRACCardService).text + return "RAC064" == message_id + + +def _name_formatter(attribute): + return "{}#{}".format(attribute.group_id, attribute.name) diff --git a/dracclient/resources/inventory.py b/dracclient/resources/inventory.py index 4ce4eae..b29452a 100644 --- a/dracclient/resources/inventory.py +++ b/dracclient/resources/inventory.py @@ -47,7 +47,7 @@ CPU = collections.namedtuple( 'CPU', ['id', 'cores', 'speed_mhz', 'model', 'status', 'ht_enabled', - 'turbo_enabled', 'vt_enabled', 'arch64']) + 'cpu_count', 'turbo_enabled', 'vt_enabled', 'arch64']) Memory = collections.namedtuple( 'Memory', @@ -57,6 +57,10 @@ 'NIC', ['id', 'mac', 'model', 'speed_mbps', 'duplex', 'media_type']) +System = collections.namedtuple( + 'System', + ['id', 'lcc_version', 'model', 'service_tag', 'uuid']) + class InventoryManagement(object): @@ -99,10 +103,20 @@ def _parse_cpus(self, cpu): allow_missing=True)), turbo_enabled=bool(self._get_cpu_attr(cpu, 'TurboModeEnabled', allow_missing=True)), + cpu_count=self._get_cpu_count( + int(self._get_cpu_attr(cpu, 'NumberOfProcessorCores')), + bool(self._get_cpu_attr(cpu, 'HyperThreadingEnabled', + allow_missing=True))), vt_enabled=bool(self._get_cpu_attr( cpu, 'VirtualizationTechnologyEnabled', allow_missing=True)), arch64=arch64) + def _get_cpu_count(self, cores, ht_enabled): + if ht_enabled: + return int(cores * 2) + else: + return int(cores) + def _get_cpu_attr(self, cpu, attr_name, allow_missing=False): return utils.get_wsman_resource_attr( cpu, uris.DCIM_CPUView, attr_name, allow_missing=allow_missing) @@ -138,7 +152,7 @@ def _get_memory_attr(self, memory, attr_name): return utils.get_wsman_resource_attr(memory, uris.DCIM_MemoryView, attr_name) - def list_nics(self): + def list_nics(self, sort=False): """Returns the list of NICs :returns: a list of NIC objects @@ -151,8 +165,11 @@ def list_nics(self): doc = self.client.enumerate(uris.DCIM_NICView) drac_nics = utils.find_xml(doc, 'DCIM_NICView', uris.DCIM_NICView, find_all=True) + nics = [self._parse_drac_nic(nic) for nic in drac_nics] + if sort: + nics.sort(key=lambda nic: nic.id) - return [self._parse_drac_nic(nic) for nic in drac_nics] + return nics def _parse_drac_nic(self, drac_nic): fqdd = self._get_nic_attr(drac_nic, 'FQDD') @@ -170,3 +187,32 @@ def _parse_drac_nic(self, drac_nic): def _get_nic_attr(self, drac_nic, attr_name): return utils.get_wsman_resource_attr(drac_nic, uris.DCIM_NICView, attr_name) + + def get_system(self): + """Returns a System object + + :returns: a System object + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidRespons when receiving invalid response + """ + doc = self.client.enumerate(uris.DCIM_SystemView) + drac_system = utils.find_xml(doc, + 'DCIM_SystemView', + uris.DCIM_SystemView, + find_all=False) + + return self._parse_drac_system(drac_system) + + def _parse_drac_system(self, drac_system): + return System( + id=self._get_system_attr(drac_system, 'InstanceID'), + uuid=self._get_system_attr(drac_system, 'UUID'), + service_tag=self._get_system_attr(drac_system, 'ServiceTag'), + model=self._get_system_attr(drac_system, 'Model'), + lcc_version=self._get_system_attr(drac_system, + 'LifecycleControllerVersion')) + + def _get_system_attr(self, drac_system, attr_name): + return utils.get_wsman_resource_attr(drac_system, + uris.DCIM_SystemView, + attr_name) diff --git a/dracclient/resources/job.py b/dracclient/resources/job.py index 2961075..5ec3443 100644 --- a/dracclient/resources/job.py +++ b/dracclient/resources/job.py @@ -14,32 +14,24 @@ import collections import logging +from dracclient import constants +import dracclient.exceptions as exceptions from dracclient.resources import uris from dracclient import utils from dracclient import wsman LOG = logging.getLogger(__name__) -JobTuple = collections.namedtuple( +Job = collections.namedtuple( 'Job', ['id', 'name', 'start_time', 'until_time', 'message', 'status', 'percent_complete']) - -class Job(JobTuple): - - def __new__(cls, **kwargs): - if 'state' in kwargs: - LOG.warning('Job.state is deprecated. Use Job.status instead.') - kwargs['status'] = kwargs['state'] - del kwargs['state'] - - return super(Job, cls).__new__(cls, **kwargs) - - @property - def state(self): - LOG.warning('Job.state is deprecated. Use Job.status instead.') - return self.status +REBOOT_TYPES = { + constants.RebootJobType.power_cycle: '1', + constants.RebootJobType.graceful_reboot: '2', + constants.RebootJobType.reboot_forced_shutdown: '3', +} class JobManagement(object): @@ -68,6 +60,7 @@ def list_jobs(self, only_unfinished=False): filter_query = ('select * from DCIM_LifecycleJob ' 'where Name != "CLEARALL" and ' 'JobStatus != "Reboot Completed" and ' + 'JobStatus != "Reboot Failed" and ' 'JobStatus != "Completed" and ' 'JobStatus != "Completed with Errors" and ' 'JobStatus != "Failed"') @@ -107,7 +100,11 @@ def create_config_job(self, resource_uri, cim_creation_class_name, cim_name, target, cim_system_creation_class_name='DCIM_ComputerSystem', cim_system_name='DCIM:ComputerSystem', - reboot=False): + reboot=False, + start_time='TIME_NOW', + realtime=False, + wait_for_idrac=True, + method_name='CreateTargetedConfigJob'): """Creates a config job In CIM (Common Information Model), weak association is used to name an @@ -126,6 +123,18 @@ def create_config_job(self, resource_uri, cim_creation_class_name, :param cim_system_name: name of the scoping system :param reboot: indicates whether a RebootJob should also be created or not + :param start_time: start time for job execution in format + yyyymmddhhmmss; the string 'TIME_NOW' means + immediately and None means the job is registered + but will not start execution until + schedule_job_execution is called with the returned + job id. + :param realtime: Indicates if reatime mode should be used. + Valid values are True and False. Default value is False. + :param wait_for_idrac: indicates whether or not to wait for the + iDRAC to be ready to accept commands before + issuing the command. + :param method_name: method of CIM object to invoke :returns: id of the created job :raises: WSManRequestFailure on request failures :raises: WSManInvalidResponse when receiving invalid response @@ -139,24 +148,142 @@ def create_config_job(self, resource_uri, cim_creation_class_name, 'CreationClassName': cim_creation_class_name, 'Name': cim_name} - properties = {'Target': target, - 'ScheduledStartTime': 'TIME_NOW'} + properties = {'Target': target} + + if realtime: + properties['RealTime'] = '1' - if reboot: + if not realtime and reboot: properties['RebootJobType'] = '3' - doc = self.client.invoke(resource_uri, 'CreateTargetedConfigJob', + if start_time is not None: + properties['ScheduledStartTime'] = start_time + + doc = self.client.invoke(resource_uri, method_name, selectors, properties, + expected_return_value=utils.RET_CREATED, + wait_for_idrac=wait_for_idrac) + return self._get_job_id(doc) + + def create_reboot_job( + self, + reboot_type=constants.RebootJobType.reboot_forced_shutdown): + """Creates a reboot job. + + :param reboot_type: type of reboot + :returns id of the created job + :raises: InvalidParameterValue on invalid reboot type + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the iDRAC + interface + :raises: DRACUnexpectedReturnValue on return value mismatch + """ + + try: + drac_reboot_type = REBOOT_TYPES[reboot_type] + except KeyError: + msg = ("'%(reboot_type)s' is not supported. " + "Supported reboot types: %(supported_reboot_types)r") % { + 'reboot_type': reboot_type, + 'supported_reboot_types': list(REBOOT_TYPES)} + raise exceptions.InvalidParameterValue(reason=msg) + + selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'idrac', + 'CreationClassName': 'DCIM_JobService', + 'Name': 'JobService'} + + properties = {'RebootJobType': drac_reboot_type} + + doc = self.client.invoke(uris.DCIM_JobService, + 'CreateRebootJob', + selectors, + properties, expected_return_value=utils.RET_CREATED) - query = ('.//{%(namespace)s}%(item)s[@%(attribute_name)s=' - '"%(attribute_value)s"]' % - {'namespace': wsman.NS_WSMAN, 'item': 'Selector', - 'attribute_name': 'Name', - 'attribute_value': 'InstanceID'}) + return self._get_job_id(doc) + + def schedule_job_execution(self, job_ids, start_time='TIME_NOW'): + """Schedules jobs for execution in a specified order. + + :param job_ids: list of job identifiers + :param start_time: start time for job execution in format + yyyymmddhhmmss; the string 'TIME_NOW' means + immediately + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the iDRAC + interface + :raises: DRACUnexpectedReturnValue on return value mismatch + """ + + # If the list of job identifiers is empty, there is nothing to do. + if not job_ids: + return + + selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'idrac', + 'CreationClassName': 'DCIM_JobService', + 'Name': 'JobService'} + + properties = {'JobArray': job_ids, + 'StartTimeInterval': start_time} + + self.client.invoke(uris.DCIM_JobService, + 'SetupJobQueue', + selectors, + properties, + expected_return_value=utils.RET_SUCCESS) + + def _get_job_id(self, doc): + query = ( + './/{%(namespace)s}%(item)s[@%(attribute_name)s=' + '"%(attribute_value)s"]' % { + 'namespace': wsman.NS_WSMAN, + 'item': 'Selector', + 'attribute_name': 'Name', + 'attribute_value': 'InstanceID'}) job_id = doc.find(query).text return job_id + def delete_jobs(self, job_ids=['JID_CLEARALL']): + """Deletes the given jobs, or all jobs if none specified + + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the iDRAC + interface + :raises: DRACUnexpectedReturnValue on non-success + """ + + selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'idrac', + 'CreationClassName': 'DCIM_JobService', + 'Name': 'JobService'} + + if job_ids is None: + return + + messages = [] + + for job_id in job_ids: + properties = {'JobID': job_id} + + try: + self.client.invoke( + uris.DCIM_JobService, + 'DeleteJobQueue', + selectors, + properties, + expected_return_value=utils.RET_SUCCESS) + except exceptions.DRACOperationFailed as dof: + for message in dof.args: + messages.append(message + " " + job_id) + + if len(messages): + raise exceptions.DRACOperationFailed(drac_messages=messages) + def delete_pending_config( self, resource_uri, cim_creation_class_name, cim_name, target, cim_system_creation_class_name='DCIM_ComputerSystem', diff --git a/dracclient/resources/lifecycle_controller.py b/dracclient/resources/lifecycle_controller.py index b8a715c..c42bfd1 100644 --- a/dracclient/resources/lifecycle_controller.py +++ b/dracclient/resources/lifecycle_controller.py @@ -11,6 +11,7 @@ # License for the specific language governing permissions and limitations # under the License. +from dracclient import constants from dracclient.resources import uris from dracclient import utils @@ -34,11 +35,230 @@ def get_version(self): interface """ - filter_query = ('select LifecycleControllerVersion ' - 'from DCIM_SystemView') - doc = self.client.enumerate(uris.DCIM_SystemView, - filter_query=filter_query) + doc = self.client.enumerate(uris.DCIM_SystemView, wait_for_idrac=False) lc_version_str = utils.find_xml(doc, 'LifecycleControllerVersion', uris.DCIM_SystemView).text return tuple(map(int, (lc_version_str.split('.')))) + + +class LCAttribute(object): + """Generic LC attribute class""" + + def __init__(self, name, instance_id, current_value, pending_value, + read_only): + """Creates LCAttribute object + + :param name: name of the LC attribute + :param instance_id: InstanceID of the LC attribute + :param current_value: current value of the LC attribute + :param pending_value: pending value of the LC attribute, reflecting + an unprocessed change (eg. config job not completed) + :param read_only: indicates whether this LC attribute can be changed + """ + self.name = name + self.instance_id = instance_id + 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, lifecycle_attr_xml): + """Parses XML and creates LCAttribute object""" + + name = utils.get_wsman_resource_attr( + lifecycle_attr_xml, namespace, 'AttributeName') + instance_id = utils.get_wsman_resource_attr( + lifecycle_attr_xml, namespace, 'InstanceID') + current_value = utils.get_wsman_resource_attr( + lifecycle_attr_xml, namespace, 'CurrentValue', nullable=True) + pending_value = utils.get_wsman_resource_attr( + lifecycle_attr_xml, namespace, 'PendingValue', nullable=True) + read_only = utils.get_wsman_resource_attr( + lifecycle_attr_xml, namespace, 'IsReadOnly') + + return cls(name, instance_id, current_value, pending_value, + (read_only == 'true')) + + +class LCEnumerableAttribute(LCAttribute): + """Enumerable LC attribute class""" + + namespace = uris.DCIM_LCEnumeration + + def __init__(self, name, instance_id, current_value, pending_value, + read_only, possible_values): + """Creates LCEnumerableAttribute object + + :param name: name of the LC attribute + :param current_value: current value of the LC attribute + :param pending_value: pending value of the LC attribute, reflecting + an unprocessed change (eg. config job not completed) + :param read_only: indicates whether this LC attribute can be changed + :param possible_values: list containing the allowed values for the LC + attribute + """ + super(LCEnumerableAttribute, self).__init__(name, instance_id, + current_value, + pending_value, read_only) + self.possible_values = possible_values + + @classmethod + def parse(cls, lifecycle_attr_xml): + """Parses XML and creates LCEnumerableAttribute object""" + + lifecycle_attr = LCAttribute.parse(cls.namespace, lifecycle_attr_xml) + possible_values = [attr.text for attr + in utils.find_xml(lifecycle_attr_xml, + 'PossibleValues', + cls.namespace, find_all=True)] + + return cls(lifecycle_attr.name, lifecycle_attr.instance_id, + lifecycle_attr.current_value, lifecycle_attr.pending_value, + lifecycle_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 LCStringAttribute(LCAttribute): + """String LC attribute class""" + + namespace = uris.DCIM_LCString + + def __init__(self, name, instance_id, current_value, pending_value, + read_only, min_length, max_length): + """Creates LCStringAttribute object + + :param name: name of the LC attribute + :param instance_id: InstanceID of the LC attribute + :param current_value: current value of the LC attribute + :param pending_value: pending value of the LC attribute, reflecting + an unprocessed change (eg. config job not completed) + :param read_only: indicates whether this LC attribute can be changed + :param min_length: minimum length of the string + :param max_length: maximum length of the string + """ + super(LCStringAttribute, self).__init__(name, instance_id, + current_value, pending_value, + read_only) + self.min_length = min_length + self.max_length = max_length + + @classmethod + def parse(cls, lifecycle_attr_xml): + """Parses XML and creates LCStringAttribute object""" + + lifecycle_attr = LCAttribute.parse(cls.namespace, lifecycle_attr_xml) + min_length = int(utils.get_wsman_resource_attr( + lifecycle_attr_xml, cls.namespace, 'MinLength')) + max_length = int(utils.get_wsman_resource_attr( + lifecycle_attr_xml, cls.namespace, 'MaxLength')) + + return cls(lifecycle_attr.name, lifecycle_attr.instance_id, + lifecycle_attr.current_value, lifecycle_attr.pending_value, + lifecycle_attr.read_only, min_length, max_length) + + +class LCConfiguration(object): + + NAMESPACES = [(uris.DCIM_LCEnumeration, LCEnumerableAttribute), + (uris.DCIM_LCString, LCStringAttribute)] + + def __init__(self, client): + """Creates LifecycleControllerManagement object + + :param client: an instance of WSManClient + """ + self.client = client + + def list_lifecycle_settings(self, by_name=False): + """List the LC configuration settings + + :param by_name: Controls whether returned dictionary uses Lifecycle + attribute name or instance_id as key. + :returns: a dictionary with the LC settings using InstanceID as the + key. The attributes are either LCEnumerableAttribute, + LCStringAttribute or LCIntegerAttribute objects. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface + """ + return utils.list_settings(self.client, self.NAMESPACES, by_name) + + def is_lifecycle_in_recovery(self): + """Check if Lifecycle Controller in recovery mode or not + + This method checks the LCStatus value to determine if lifecycle + controller is in recovery mode by invoking GetRemoteServicesAPIStatus + from iDRAC. + + :returns: a boolean indicating if lifecycle controller is in recovery + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface + """ + + selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'DCIM:ComputerSystem', + 'CreationClassName': 'DCIM_LCService', + 'Name': 'DCIM:LCService'} + + doc = self.client.invoke(uris.DCIM_LCService, + 'GetRemoteServicesAPIStatus', + selectors, + {}, + expected_return_value=utils.RET_SUCCESS, + wait_for_idrac=False) + + lc_status = utils.find_xml(doc, + 'LCStatus', + uris.DCIM_LCService).text + + return lc_status == constants.LC_IN_RECOVERY + + def set_lifecycle_settings(self, settings): + """Sets the Lifecycle Controller configuration + + 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. + + :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 is_commit_required key with a boolean value indicating + whether a config job must be created for the values to be + applied. + - The is_reboot_required key with a RebootRequired enumerated + value indicating whether the server must be rebooted for the + values to be applied. Possible values are true and false. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface + """ + + return utils.set_settings('Lifecycle', + self.client, + self.NAMESPACES, + settings, + uris.DCIM_LCService, + "DCIM_LCService", + "DCIM:LCService", + '', + wait_for_idrac=False) diff --git a/dracclient/resources/nic.py b/dracclient/resources/nic.py new file mode 100644 index 0000000..bf8f292 --- /dev/null +++ b/dracclient/resources/nic.py @@ -0,0 +1,378 @@ +# Copyright (c) 2016-2018 Dell Inc. or its subsidiaries. +# +# 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 logging +import re + +import dracclient.utils as utils + +from dracclient.resources import uris + +LOG = logging.getLogger(__name__) + + +class NICAttribute(object): + """Generic NIC attribute class""" + + def __init__(self, name, instance_id, current_value, pending_value, + read_only, fqdd): + """Construct a NICAttribute object. + + :param name: name of the NIC attribute + :param instance_id: opaque and unique identifier of the BIOS attribute + :param current_value: current value of the NIC attribute + :param pending_value: pending value of the NIC attribute, reflecting + an unprocessed change (eg. config job not completed) + :param read_only: indicates whether this NIC attribute can be changed + :param fqdd: Fully Qualified Device Description of the NICCard + Attribute + """ + self.name = name + self.instance_id = instance_id + self.current_value = current_value + self.pending_value = pending_value + self.read_only = read_only + self.fqdd = fqdd + + def __eq__(self, other): + return self.__dict__ == other.__dict__ + + @classmethod + def parse(cls, namespace, nic_attr_xml): + """Parses XML and creates a NICAttribute object.""" + + name = utils.get_wsman_resource_attr(nic_attr_xml, + namespace, + 'AttributeName') + instance_id = utils.get_wsman_resource_attr(nic_attr_xml, + namespace, + 'InstanceID') + current_value = utils.get_wsman_resource_attr(nic_attr_xml, + namespace, + 'CurrentValue', + nullable=True) + pending_value = utils.get_wsman_resource_attr(nic_attr_xml, + namespace, + 'PendingValue', + nullable=True) + read_only = utils.get_wsman_resource_attr(nic_attr_xml, + namespace, + 'IsReadOnly') + + fqdd = utils.get_wsman_resource_attr(nic_attr_xml, + namespace, + 'FQDD') + + return cls(name, instance_id, current_value, pending_value, + (read_only == 'true'), fqdd) + + +class NICEnumerationAttribute(NICAttribute): + """Enumeration NIC attribute class""" + + namespace = uris.DCIM_NICEnumeration + + def __init__(self, + name, + instance_id, + current_value, + pending_value, + read_only, + fqdd, + possible_values): + """Construct a NICEnumerationAttribute object. + + :param name: name of the NIC attribute + :param instance_id: opaque and unique identifier of the BIOS attribute + :param current_value: current value of the NIC attribute + :param pending_value: pending value of the NIC attribute, reflecting + an unprocessed change (eg. config job not completed) + :param read_only: indicates whether this NIC attribute can be changed + :param fqdd: Fully Qualified Device Description of the NICCard + Attribute + :param possible_values: list containing the allowed values for the NIC + attribute + """ + super(NICEnumerationAttribute, self).__init__(name, + instance_id, + current_value, + pending_value, + read_only, + fqdd) + self.possible_values = possible_values + + @classmethod + def parse(cls, nic_attr_xml): + """Parse XML and create a NICEnumerationAttribute object.""" + + nic_attr = NICAttribute.parse(cls.namespace, nic_attr_xml) + possible_values = [attr.text for attr + in utils.find_xml(nic_attr_xml, + 'PossibleValues', + cls.namespace, + find_all=True)] + + return cls(nic_attr.name, + nic_attr.instance_id, + nic_attr.current_value, + nic_attr.pending_value, + nic_attr.read_only, + nic_attr.fqdd, + possible_values) + + def validate(self, value): + """Validate new value.""" + + if str(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': value, + 'possible_values': self.possible_values} + return msg + + return None + + +class NICStringAttribute(NICAttribute): + """String NIC attribute class.""" + + namespace = uris.DCIM_NICString + + def __init__(self, + name, + instance_id, + current_value, + pending_value, + read_only, + fqdd, + min_length, + max_length, + pcre_regex): + """Construct a NICStringAttribute object. + + :param name: name of the NIC attribute + :param instance_id: opaque and unique identifier of the BIOS attribute + :param current_value: current value of the NIC attribute + :param pending_value: pending value of the NIC attribute, reflecting + an unprocessed change (eg. config job not completed) + :param read_only: indicates whether this NIC attribute can be changed + :param fqdd: Fully Qualified Device Description of the NICCard + Attribute + :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(NICStringAttribute, self).__init__(name, + instance_id, + current_value, + pending_value, + read_only, + fqdd) + self.min_length = min_length + self.max_length = max_length + self.pcre_regex = pcre_regex + + @classmethod + def parse(cls, nic_attr_xml): + """Parse XML and create a NICStringAttribute object.""" + + nic_attr = NICAttribute.parse(cls.namespace, nic_attr_xml) + min_length = int(utils.get_wsman_resource_attr(nic_attr_xml, + cls.namespace, + 'MinLength')) + max_length = int(utils.get_wsman_resource_attr(nic_attr_xml, + cls.namespace, + 'MaxLength')) + pcre_regex = utils.get_wsman_resource_attr(nic_attr_xml, + cls.namespace, + 'ValueExpression', + nullable=True) + + return cls(nic_attr.name, + nic_attr.instance_id, + nic_attr.current_value, + nic_attr.pending_value, + nic_attr.read_only, + nic_attr.fqdd, + min_length, + max_length, + pcre_regex) + + def validate(self, value): + """Validate new value.""" + + if self.pcre_regex is not None: + regex = re.compile(self.pcre_regex) + + if regex.search(str(value)) is None: + msg = ("Attribute '%(attr)s' cannot be set to value '%(val)s.'" + " It must match regex '%(re)s'.") % { + 'attr': self.name, + 'val': value, + 're': self.pcre_regex} + return msg + + return None + + +class NICIntegerAttribute(NICAttribute): + """Integer NIC attribute class.""" + + namespace = uris.DCIM_NICInteger + + def __init__(self, + name, + instance_id, + current_value, + pending_value, + read_only, + fqdd, + lower_bound, + upper_bound): + """Construct a NICIntegerAttribute object. + + :param name: name of the NIC attribute + :param instance_id: opaque and unique identifier of the BIOS attribute + :param current_value: current value of the NIC attribute + :param pending_value: pending value of the NIC attribute, reflecting + an unprocessed change (eg. config job not completed) + :param read_only: indicates whether this NIC attribute can be changed + :param fqdd: Fully Qualified Device Description of the NICCard + Attribute + :param lower_bound: minimum value for the NIC attribute + :param upper_bound: maximum value for the NIC attribute + """ + super(NICIntegerAttribute, self).__init__(name, + instance_id, + current_value, + pending_value, + read_only, + fqdd) + self.lower_bound = lower_bound + self.upper_bound = upper_bound + + @classmethod + def parse(cls, nic_attr_xml): + """Parse XML and create a NICIntegerAttribute object.""" + + nic_attr = NICAttribute.parse(cls.namespace, nic_attr_xml) + lower_bound = utils.get_wsman_resource_attr(nic_attr_xml, + cls.namespace, + 'LowerBound') + upper_bound = utils.get_wsman_resource_attr(nic_attr_xml, + cls.namespace, + 'UpperBound') + + if nic_attr.current_value: + nic_attr.current_value = int(nic_attr.current_value) + + if nic_attr.pending_value: + nic_attr.pending_value = int(nic_attr.pending_value) + + return cls(nic_attr.name, + nic_attr.instance_id, + nic_attr.current_value, + nic_attr.pending_value, + nic_attr.read_only, + nic_attr.fqdd, + int(lower_bound), + int(upper_bound)) + + def validate(self, value): + """Validate new value.""" + + val = int(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': value, + 'lower': self.lower_bound, + 'upper': self.upper_bound} + return msg + + return None + + +class NICConfiguration(object): + + NAMESPACES = [(uris.DCIM_NICEnumeration, NICEnumerationAttribute), + (uris.DCIM_NICString, NICStringAttribute), + (uris.DCIM_NICInteger, NICIntegerAttribute)] + + def __init__(self, client): + """Construct a NICConfiguration object. + + :param client: an instance of WSManClient + """ + self.client = client + + def list_nic_settings(self, nic_id): + """Return the list of attribute settings of a NIC. + + :param nic_id: id of the network interface controller (NIC) + :returns: dictionary containing the NIC settings. The keys are + attribute names. Each value is a + NICEnumerationAttribute, NICIntegerAttribute, or + NICStringAttribute object. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the iDRAC + interface + """ + + result = utils.list_settings(self.client, + self.NAMESPACES, + fqdd_filter=nic_id) + + return result + + def set_nic_settings(self, nic_id, new_settings): + """Modify one or more settings of a NIC. + + 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 may + need to be created and the node may need to be rebooted. + + :param nic_id: id of the network interface controller, + :param new_settings: a dictionary containing the proposed values, with + each key being the name of attribute qualified + with the group ID in the form "group_id#name" and + the value being the proposed value. + :returns: a dictionary containing: + - The is_commit_required key with a boolean value indicating + whether a config job must be created for the values to be + applied. + - The is_reboot_required key with a RebootRequired enumerated + value indicating whether the server must be rebooted for the + values to be applied. Possible values are true and false. + :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 attribute + """ + + return utils.set_settings('iDRAC Card', + self.client, + self.NAMESPACES, + new_settings, + uris.DCIM_NICService, + "DCIM_NICService", + "DCIM:NICService", + nic_id) diff --git a/dracclient/resources/raid.py b/dracclient/resources/raid.py index d16501e..3522158 100644 --- a/dracclient/resources/raid.py +++ b/dracclient/resources/raid.py @@ -12,6 +12,7 @@ # under the License. import collections +import copy import logging from dracclient import constants @@ -34,6 +35,11 @@ REVERSE_RAID_LEVELS = dict((v, k) for (k, v) in RAID_LEVELS.items()) +RAID_CONTROLLER_IS_REALTIME = { + '1': True, + '0': False +} + DISK_RAID_STATUS = { '0': 'unknown', '1': 'ready', @@ -66,88 +72,248 @@ '3': 'fibre', '4': 'usb', '5': 'sata', - '6': 'sas' + '6': 'sas', + '7': 'pcie', + '8': 'nvme' } -PhysicalDiskTuple = collections.namedtuple( +PhysicalDisk = collections.namedtuple( 'PhysicalDisk', ['id', 'description', 'controller', 'manufacturer', 'model', 'media_type', 'interface_type', 'size_mb', 'free_size_mb', 'serial_number', - 'firmware_version', 'status', 'raid_status']) - - -class PhysicalDisk(PhysicalDiskTuple): - - def __new__(cls, **kwargs): - if 'state' in kwargs: - LOG.warning('PhysicalDisk.state is deprecated. ' - 'Use PhysicalDisk.status instead.') - kwargs['status'] = kwargs['state'] - del kwargs['state'] - - if 'raid_state' in kwargs: - LOG.warning('PhysicalDisk.raid_state is deprecated. ' - 'Use PhysicalDisk.raid_status instead.') - kwargs['raid_status'] = kwargs['raid_state'] - del kwargs['raid_state'] - - return super(PhysicalDisk, cls).__new__(cls, **kwargs) - - @property - def state(self): - LOG.warning('PhysicalDisk.state is deprecated. ' - 'Use PhysicalDisk.status instead.') - return self.status - - @property - def raid_state(self): - LOG.warning('PhysicalDisk.raid_state is deprecated. ' - 'Use PhysicalDisk.raid_status instead.') - return self.raid_status + 'firmware_version', 'status', 'raid_status', 'sas_address', + 'device_protocol', 'bus']) RAIDController = collections.namedtuple( 'RAIDController', ['id', 'description', 'manufacturer', 'model', - 'primary_status', 'firmware_version']) + 'primary_status', 'firmware_version', 'bus', + 'supports_realtime']) -VirtualDiskTuple = collections.namedtuple( +VirtualDisk = collections.namedtuple( 'VirtualDisk', ['id', 'name', 'description', 'controller', 'raid_level', 'size_mb', 'status', 'raid_status', 'span_depth', 'span_length', - 'pending_operations']) + 'pending_operations', 'physical_disks']) +NO_FOREIGN_DRIVES = ["STOR058", "STOR018"] -class VirtualDisk(VirtualDiskTuple): - def __new__(cls, **kwargs): - if 'state' in kwargs: - LOG.warning('VirtualDisk.state is deprecated. ' - 'Use VirtualDisk.status instead.') - kwargs['status'] = kwargs['state'] - del kwargs['state'] +class RAIDAttribute(object): + """Generic RAID attribute class""" - if 'raid_state' in kwargs: - LOG.warning('VirtualDisk.raid_state is deprecated. ' - 'Use VirtualDisk.raid_status instead.') - kwargs['raid_status'] = kwargs['raid_state'] - del kwargs['raid_state'] + def __init__(self, name, instance_id, current_value, pending_value, + read_only, fqdd): + """Creates RAIDAttribute object - return super(VirtualDisk, cls).__new__(cls, **kwargs) - - @property - def state(self): - LOG.warning('VirtualDisk.state is deprecated. ' - 'Use VirtualDisk.status instead.') - return self.status + :param name: name of the RAID attribute + :param instance_id: InstanceID of the RAID attribute + :param current_value: list containing the current values of the + RAID attribute + :param pending_value: pending value of the RAID attribute, reflecting + an unprocessed change (eg. config job not completed) + :param read_only: indicates whether this RAID attribute can be changed + :param fqdd: Fully Qualified Device Description of the RAID Attribute + """ - @property - def raid_state(self): - LOG.warning('VirtualDisk.raid_state is deprecated. ' - 'Use VirtualDisk.raid_status instead.') - return self.raid_status + self.name = name + self.instance_id = instance_id + self.current_value = current_value + self.pending_value = pending_value + self.read_only = read_only + self.fqdd = fqdd + + def __eq__(self, other): + return self.__dict__ == other.__dict__ + + @classmethod + def parse(cls, namespace, raid_attr_xml): + """Parses XML and creates RAIDAttribute object""" + + name = utils.get_wsman_resource_attr( + raid_attr_xml, namespace, 'AttributeName') + instance_id = utils.get_wsman_resource_attr( + raid_attr_xml, namespace, 'InstanceID') + current_value = [attr.text for attr in + utils.find_xml(raid_attr_xml, 'CurrentValue', + namespace, find_all=True)] + pending_value = utils.get_wsman_resource_attr( + raid_attr_xml, namespace, 'PendingValue', nullable=True) + read_only = utils.get_wsman_resource_attr( + raid_attr_xml, namespace, 'IsReadOnly') + fqdd = utils.get_wsman_resource_attr( + raid_attr_xml, namespace, 'FQDD') + + return cls(name, instance_id, current_value, pending_value, + (read_only == 'true'), fqdd) + + +class RAIDEnumerableAttribute(RAIDAttribute): + """Enumerable RAID attribute class""" + + namespace = uris.DCIM_RAIDEnumeration + + def __init__(self, name, instance_id, current_value, pending_value, + read_only, fqdd, possible_values): + """Creates RAIDEnumerableAttribute object + + :param name: name of the RAID attribute + :param instance_id: InstanceID of the RAID attribute + :param current_value: list containing the current values of the + RAID attribute + :param pending_value: pending value of the RAID attribute, reflecting + an unprocessed change (eg. config job not completed) + :param read_only: indicates whether this RAID attribute can be changed + :param fqdd: Fully Qualified Device Description of the RAID + Attribute + :param possible_values: list containing the allowed values for the RAID + attribute + """ + super(RAIDEnumerableAttribute, self).__init__(name, instance_id, + current_value, + pending_value, + read_only, fqdd) + + self.possible_values = possible_values + + @classmethod + def parse(cls, raid_attr_xml): + """Parses XML and creates RAIDEnumerableAttribute object""" + + raid_attr = RAIDAttribute.parse(cls.namespace, raid_attr_xml) + possible_values = [attr.text for attr + in utils.find_xml(raid_attr_xml, + 'PossibleValues', + cls.namespace, find_all=True)] + + return cls(raid_attr.name, raid_attr.instance_id, + raid_attr.current_value, raid_attr.pending_value, + raid_attr.read_only, raid_attr.fqdd, 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 RAIDStringAttribute(RAIDAttribute): + """String RAID attribute class""" + + namespace = uris.DCIM_RAIDString + + def __init__(self, name, instance_id, current_value, pending_value, + read_only, fqdd, min_length, max_length): + """Creates RAIDStringAttribute object + + :param name: name of the RAID attribute + :param instance_id: InstanceID of the RAID attribute + :param current_value: list containing the current values of the + RAID attribute + :param pending_value: pending value of the RAID attribute, reflecting + an unprocessed change (eg. config job not completed) + :param read_only: indicates whether this RAID attribute can be changed + :param fqdd: Fully Qualified Device Description of the RAID + Attribute + :param min_length: minimum length of the string + :param max_length: maximum length of the string + """ + super(RAIDStringAttribute, self).__init__(name, instance_id, + current_value, pending_value, + read_only, fqdd) + self.min_length = min_length + self.max_length = max_length + + @classmethod + def parse(cls, raid_attr_xml): + """Parses XML and creates RAIDStringAttribute object""" + + raid_attr = RAIDAttribute.parse(cls.namespace, raid_attr_xml) + min_length = int(utils.get_wsman_resource_attr( + raid_attr_xml, cls.namespace, 'MinLength')) + max_length = int(utils.get_wsman_resource_attr( + raid_attr_xml, cls.namespace, 'MaxLength')) + + return cls(raid_attr.name, raid_attr.instance_id, + raid_attr.current_value, raid_attr.pending_value, + raid_attr.read_only, raid_attr.fqdd, + min_length, max_length) + + +class RAIDIntegerAttribute(RAIDAttribute): + """Integer RAID attribute class""" + + namespace = uris.DCIM_RAIDInteger + + def __init__(self, name, instance_id, current_value, pending_value, + read_only, fqdd, lower_bound, upper_bound): + """Creates RAIDIntegerAttribute object + + :param name: name of the RAID attribute + :param instance_id: InstanceID of the RAID attribute + :param current_value: list containing the current value of the + RAID attribute + :param pending_value: pending value of the RAID attribute, + reflecting an unprocessed change + (eg. config job not completed) + :param read_only: indicates whether this RAID attribute can be + changed + :param fqdd: Fully Qualified Device Description of the RAID + Attribute + :param lower_bound: minimum value for the RAID attribute + :param upper_bound: maximum value for the RAID attribute + """ + super(RAIDIntegerAttribute, self).__init__(name, instance_id, + current_value, + pending_value, + read_only, fqdd) + self.lower_bound = lower_bound + self.upper_bound = upper_bound + + @classmethod + def parse(cls, raid_attr_xml): + """Parses XML and creates RAIDIntegerAttribute object""" + + raid_attr = RAIDAttribute.parse(cls.namespace, raid_attr_xml) + lower_bound = utils.get_wsman_resource_attr( + raid_attr_xml, cls.namespace, 'LowerBound') + upper_bound = utils.get_wsman_resource_attr( + raid_attr_xml, cls.namespace, 'UpperBound') + + if raid_attr.current_value: + raid_attr.current_value = int(raid_attr.current_value[0]) + if raid_attr.pending_value: + raid_attr.pending_value = int(raid_attr.pending_value) + + return cls(raid_attr.name, raid_attr.instance_id, + raid_attr.current_value, raid_attr.pending_value, + raid_attr.read_only, raid_attr.fqdd, + 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 RAIDManagement(object): + NAMESPACES = [(uris.DCIM_RAIDEnumeration, RAIDEnumerableAttribute), + (uris.DCIM_RAIDString, RAIDStringAttribute), + (uris.DCIM_RAIDInteger, RAIDIntegerAttribute)] + def __init__(self, client): """Creates RAIDManagement object @@ -155,6 +321,54 @@ def __init__(self, client): """ self.client = client + def list_raid_settings(self): + """List the RAID configuration settings + + :returns: a dictionary with the RAID settings using InstanceID as the + key. The attributes are either RAIDEnumerableAttribute, + RAIDStringAttribute objects. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface + """ + + return utils.list_settings(self.client, self.NAMESPACES, + by_name=False) + + def set_raid_settings(self, raid_fqdd, new_settings): + """Sets the RAID configuration + + 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. + :param raid_fqdd: the FQDD of the RAID setting. + :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 is_commit_required key with a boolean value indicating + whether a config job must be created for the values to be + applied. + - The is_reboot_required key with a RebootRequired enumerated + value indicating whether the server must be rebooted for the + values to be applied. Possible values are true and false. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface + """ + + return utils.set_settings('RAID', + self.client, + self.NAMESPACES, + new_settings, + uris.DCIM_RAIDService, + "DCIM_RAIDService", + "DCIM:RAIDService", + raid_fqdd, + by_name=False) + def list_raid_controllers(self): """Returns the list of RAID controllers @@ -187,7 +401,11 @@ def _parse_drac_raid_controller(self, drac_controller): self._get_raid_controller_attr(drac_controller, 'PrimaryStatus')], firmware_version=self._get_raid_controller_attr( - drac_controller, 'ControllerFirmwareVersion')) + drac_controller, 'ControllerFirmwareVersion'), + bus=self._get_raid_controller_attr(drac_controller, 'Bus').upper(), + supports_realtime=RAID_CONTROLLER_IS_REALTIME[ + self._get_raid_controller_attr( + drac_controller, 'RealtimeCapability')]) def _get_raid_controller_attr(self, drac_controller, attr_name): return utils.get_wsman_resource_attr( @@ -218,7 +436,12 @@ def _parse_drac_virtual_disk(self, drac_disk): drac_raid_level = self._get_virtual_disk_attr(drac_disk, 'RAIDTypes') size_b = self._get_virtual_disk_attr(drac_disk, 'SizeInBytes') drac_status = self._get_virtual_disk_attr(drac_disk, 'PrimaryStatus') - drac_raid_status = self._get_virtual_disk_attr(drac_disk, 'RAIDStatus') + drac_raid_status = self._get_virtual_disk_attr( + drac_disk, 'RAIDStatus', allow_missing=True) + if drac_raid_status is None: + drac_raid_status = self._get_virtual_disk_attr( + drac_disk, 'RaidStatus') + drac_pending_operations = self._get_virtual_disk_attr( drac_disk, 'PendingOperations') @@ -231,7 +454,7 @@ def _parse_drac_virtual_disk(self, drac_disk): nullable=True), controller=fqdd.split(':')[-1], raid_level=REVERSE_RAID_LEVELS[drac_raid_level], - size_mb=int(size_b) / 2 ** 20, + size_mb=int(size_b) // 2 ** 20, status=constants.PRIMARY_STATUS[drac_status], raid_status=DISK_RAID_STATUS[drac_raid_status], span_depth=int(self._get_virtual_disk_attr(drac_disk, @@ -239,12 +462,19 @@ def _parse_drac_virtual_disk(self, drac_disk): span_length=int(self._get_virtual_disk_attr(drac_disk, 'SpanLength')), pending_operations=( - VIRTUAL_DISK_PENDING_OPERATIONS[drac_pending_operations])) + VIRTUAL_DISK_PENDING_OPERATIONS[drac_pending_operations]), + physical_disks=self._get_virtual_disk_attrs(drac_disk, + 'PhysicalDiskIDs')) - def _get_virtual_disk_attr(self, drac_disk, attr_name, nullable=False): + def _get_virtual_disk_attr( + self, drac_disk, attr_name, nullable=False, allow_missing=False): return utils.get_wsman_resource_attr( drac_disk, uris.DCIM_VirtualDiskView, attr_name, - nullable=nullable) + nullable=nullable, allow_missing=allow_missing) + + def _get_virtual_disk_attrs(self, drac_disk, attr_name): + return utils.get_all_wsman_resource_attrs( + drac_disk, uris.DCIM_VirtualDiskView, attr_name, nullable=False) def list_physical_disks(self): """Returns the list of physical disks @@ -261,44 +491,80 @@ def list_physical_disks(self): drac_physical_disks = utils.find_xml(doc, 'DCIM_PhysicalDiskView', uris.DCIM_PhysicalDiskView, find_all=True) + physical_disks = [self._parse_drac_physical_disk(disk) + for disk in drac_physical_disks] + + drac_pcie_disks = utils.find_xml(doc, 'DCIM_PCIeSSDView', + uris.DCIM_PCIeSSDView, + find_all=True) + pcie_disks = [self._parse_drac_physical_disk(disk, + uris.DCIM_PCIeSSDView) for disk in drac_pcie_disks] + + return physical_disks + pcie_disks - return [self._parse_drac_physical_disk(disk) - for disk in drac_physical_disks] + def _parse_drac_physical_disk(self, + drac_disk, + uri=uris.DCIM_PhysicalDiskView): + fqdd = self._get_physical_disk_attr(drac_disk, 'FQDD', uri) + size_b = self._get_physical_disk_attr(drac_disk, 'SizeInBytes', uri) - def _parse_drac_physical_disk(self, drac_disk): - fqdd = self._get_physical_disk_attr(drac_disk, 'FQDD') - size_b = self._get_physical_disk_attr(drac_disk, 'SizeInBytes') free_size_b = self._get_physical_disk_attr(drac_disk, - 'FreeSizeInBytes') - drac_status = self._get_physical_disk_attr(drac_disk, 'PrimaryStatus') + 'FreeSizeInBytes', uri) + if free_size_b is not None: + free_size_mb = int(free_size_b) // 2 ** 20 + else: + free_size_mb = None + + drac_status = self._get_physical_disk_attr(drac_disk, 'PrimaryStatus', + uri) drac_raid_status = self._get_physical_disk_attr(drac_disk, - 'RaidStatus') - drac_media_type = self._get_physical_disk_attr(drac_disk, 'MediaType') + 'RaidStatus', uri) + if drac_raid_status is not None: + raid_status = DISK_RAID_STATUS[drac_raid_status] + else: + raid_status = None + drac_media_type = self._get_physical_disk_attr(drac_disk, 'MediaType', + uri) drac_bus_protocol = self._get_physical_disk_attr(drac_disk, - 'BusProtocol') + 'BusProtocol', uri) + bus = self._get_physical_disk_attr(drac_disk, + 'Bus', uri, allow_missing=True) + + if bus is not None: + bus = bus.upper() return PhysicalDisk( id=fqdd, description=self._get_physical_disk_attr(drac_disk, - 'DeviceDescription'), + 'DeviceDescription', + uri), controller=fqdd.split(':')[-1], manufacturer=self._get_physical_disk_attr(drac_disk, - 'Manufacturer'), - model=self._get_physical_disk_attr(drac_disk, 'Model'), + 'Manufacturer', uri), + model=self._get_physical_disk_attr(drac_disk, 'Model', uri), media_type=PHYSICAL_DISK_MEDIA_TYPE[drac_media_type], interface_type=PHYSICAL_DISK_BUS_PROTOCOL[drac_bus_protocol], - size_mb=int(size_b) / 2 ** 20, - free_size_mb=int(free_size_b) / 2 ** 20, + size_mb=int(size_b) // 2 ** 20, + free_size_mb=free_size_mb, serial_number=self._get_physical_disk_attr(drac_disk, - 'SerialNumber'), + 'SerialNumber', uri), firmware_version=self._get_physical_disk_attr(drac_disk, - 'Revision'), + 'Revision', uri), status=constants.PRIMARY_STATUS[drac_status], - raid_status=DISK_RAID_STATUS[drac_raid_status]) - - def _get_physical_disk_attr(self, drac_disk, attr_name): + raid_status=raid_status, + sas_address=self._get_physical_disk_attr(drac_disk, 'SASAddress', + uri, allow_missing=True), + device_protocol=self._get_physical_disk_attr(drac_disk, + 'DeviceProtocol', + uri, + allow_missing=True), + bus=bus) + + def _get_physical_disk_attr(self, drac_disk, attr_name, uri, + allow_missing=False): return utils.get_wsman_resource_attr( - drac_disk, uris.DCIM_PhysicalDiskView, attr_name, nullable=True) + drac_disk, uri, attr_name, nullable=True, + allow_missing=allow_missing) def convert_physical_disks(self, physical_disks, raid_enable): """Converts a list of physical disks into or out of RAID mode. @@ -306,13 +572,17 @@ def convert_physical_disks(self, physical_disks, raid_enable): Disks can be enabled or disabled for RAID mode. :param physical_disks: list of FQDD ID strings of the physical disks - to update + to update :param raid_enable: boolean flag, set to True if the disk is to - become part of the RAID. The same flag is applied to all - listed disks - :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. + become part of the RAID. The same flag is applied + to all listed disks + :returns: a dictionary containing: + - The is_commit_required key with the value always set to + True indicating that a config job must be created to + complete disk conversion. + - The is_reboot_required key with a RebootRequired enumerated + value indicating whether the server must be rebooted to + complete disk conversion. """ invocation = 'ConvertToRAID' if raid_enable else 'ConvertToNonRAID' @@ -327,8 +597,8 @@ def convert_physical_disks(self, physical_disks, raid_enable): selectors, properties, expected_return_value=utils.RET_SUCCESS) - return {'commit_required': - utils.is_reboot_required(doc, uris.DCIM_RAIDService)} + return utils.build_return_dict(doc, uris.DCIM_RAIDService, + is_commit_required_value=True) def create_virtual_disk(self, raid_controller, physical_disks, raid_level, size_mb, disk_name=None, span_length=None, @@ -345,9 +615,13 @@ def create_virtual_disk(self, raid_controller, physical_disks, raid_level, :param disk_name: name of the virtual disk (optional) :param span_length: number of disks per span (optional) :param span_depth: number of spans in virtual disk (optional) - :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. + :returns: a dictionary containing: + - The is_commit_required key with the value always set to + True indicating that a config job must be created to + complete virtual disk creation. + - The is_reboot_required key with a RebootRequired enumerated + value indicating whether the server must be rebooted to + complete virtual disk creation. :raises: WSManRequestFailure on request failures :raises: WSManInvalidResponse when receiving invalid response :raises: DRACOperationFailed on error reported back by the DRAC @@ -369,10 +643,7 @@ def create_virtual_disk(self, raid_controller, physical_disks, raid_level, error_msgs.append("'physical_disks' is not supplied") # size validation - if not size_mb: - error_msgs.append("'size_mb' is not supplied") - else: - utils.validate_integer_value(size_mb, 'size_mb', error_msgs) + utils.validate_integer_value(size_mb, 'size_mb', error_msgs) virtual_disk_prop_names.append('Size') virtual_disk_prop_values.append(str(size_mb)) @@ -418,8 +689,8 @@ def create_virtual_disk(self, raid_controller, physical_disks, raid_level, selectors, properties, expected_return_value=utils.RET_SUCCESS) - return {'commit_required': utils.is_reboot_required( - doc, uris.DCIM_RAIDService)} + return utils.build_return_dict(doc, uris.DCIM_RAIDService, + is_commit_required_value=True) def delete_virtual_disk(self, virtual_disk): """Deletes a virtual disk @@ -428,9 +699,13 @@ def delete_virtual_disk(self, virtual_disk): be applied, a config job must be created and the node must be rebooted. :param virtual_disk: id of the virtual disk - :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. + :returns: a dictionary containing: + - The is_commit_required key with the value always set to + True indicating that a config job must be created to + complete virtual disk deletion. + - The is_reboot_required key with a RebootRequired enumerated + value indicating whether the server must be rebooted to + complete virtual disk deletion. :raises: WSManRequestFailure on request failures :raises: WSManInvalidResponse when receiving invalid response :raises: DRACOperationFailed on error reported back by the DRAC @@ -448,5 +723,382 @@ def delete_virtual_disk(self, virtual_disk): selectors, properties, expected_return_value=utils.RET_SUCCESS) - return {'commit_required': utils.is_reboot_required( - doc, uris.DCIM_RAIDService)} + return utils.build_return_dict(doc, uris.DCIM_RAIDService, + is_commit_required_value=True) + + def is_jbod_capable(self, raid_controller_fqdd): + """Find out if raid controller supports jbod + + :param raid_controller_fqdd: The raid controller's fqdd + being being checked to see if it is jbod + capable. + :raises: DRACRequestFailed if unable to find any disks in the Ready + or non-RAID states + :raises: DRACOperationFailed on error reported back by the DRAC + and the exception message does not contain + NOT_SUPPORTED_MSG constant + """ + is_jbod_capable = False + + # Grab all the disks associated with the RAID controller + all_physical_disks = self.list_physical_disks() + physical_disks = [physical_disk for physical_disk in all_physical_disks + if physical_disk.controller == raid_controller_fqdd] + + # If there is a disk in the Non-RAID state, then the controller is JBOD + # capable + ready_disk = None + for physical_disk in physical_disks: + if physical_disk.raid_status == 'non-RAID': + is_jbod_capable = True + break + elif not ready_disk and physical_disk.raid_status == 'ready': + ready_disk = physical_disk + + if not is_jbod_capable: + if not ready_disk: + msg = "Unable to find a disk in the Ready state" + raise exceptions.DRACRequestFailed(msg) + + # Try moving a disk in the Ready state to JBOD mode + try: + self.convert_physical_disks([ready_disk.id], False) + is_jbod_capable = True + + # Flip the disk back to the Ready state. This results in the + # pending value being reset to nothing, so it effectively + # undoes the last command and makes the check non-destructive + self.convert_physical_disks([ready_disk.id], True) + except exceptions.DRACOperationFailed as ex: + # Fix for python 3, Exception.message no longer + # a valid attribute, str(ex) works for both 2.7 + # and 3.x + if constants.NOT_SUPPORTED_MSG in str(ex): + pass + else: + raise + + return is_jbod_capable + + def is_raid_controller(self, raid_controller_fqdd, raid_controllers=None): + """Find out if object's fqdd is for a raid controller or not + + :param raid_controller_fqdd: The object's fqdd we are testing to see + if it is a raid controller or not. + :param raid_controllers: A list of RAIDControllers used to check for + the presence of BOSS cards. If None, the + iDRAC will be queried for the list of + controllers. + :returns: boolean, True if the device is a RAID controller, + False if not. + """ + return raid_controller_fqdd.startswith('RAID.') or \ + self.is_boss_controller(raid_controller_fqdd, raid_controllers) + + def is_boss_controller(self, raid_controller_fqdd, raid_controllers=None): + """Find out if a RAID controller a BOSS card or not + + :param raid_controller_fqdd: The object's fqdd we are testing to see + if it is a BOSS card or not. + :param raid_controllers: A list of RAIDController to scan for presence + of BOSS card, if None the drac will be queried + for the list of controllers which will then be + scanned. + :returns: boolean, True if the device is a BOSS card, False if not. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface + """ + if raid_controllers is None: + raid_controllers = self.list_raid_controllers() + boss_raid_controllers = [ + c.id for c in raid_controllers if c.model.startswith('BOSS')] + return raid_controller_fqdd in boss_raid_controllers + + def _check_disks_status(self, mode, physical_disks, + controllers_to_physical_disk_ids): + """Find disks that failed, need to be configured, or need no change. + + Inspect all the controllers drives and: + - See if there are any disks in a failed or unknown state and raise + a ValueException where appropriate. + - If a controller has disks that still need to be configured add + them to the controllers_to_physical_disk_ids dict for the + appropriate controller. + - If a disk is already in the appropriate state, do nothing, this + function should behave in an idempotent manner. + + :param mode: constants.RaidStatus enumeration used to + determine what raid status to check for. + :param physical_disks: all physical disks + :param controllers_to_physical_disk_ids: Dictionary of controllers and + corresponding disk ids to convert to the requested mode. + :returns: a dictionary mapping controller FQDDs to the list of + physical disks that need to be converted for that controller. + :raises: ValueError: Exception message will list failed drives and + drives whose state cannot be changed at this time, drive + state is not "ready" or "non-RAID". + """ + controllers_to_physical_disk_ids = copy.deepcopy( + controllers_to_physical_disk_ids) + + p_disk_id_to_status = {} + for physical_disk in physical_disks: + p_disk_id_to_status[physical_disk.id] = physical_disk.raid_status + failed_disks = [] + bad_disks = [] + + jbod = constants.RaidStatus.jbod + raid = constants.RaidStatus.raid + for controller, physical_disk_ids \ + in controllers_to_physical_disk_ids.items(): + final_physical_disk_ids = [] + for physical_disk_id in physical_disk_ids: + raid_status = p_disk_id_to_status[physical_disk_id] + LOG.debug("RAID status for disk id: %s is: %s", + physical_disk_id, raid_status) + if ((mode == jbod and raid_status == "non-RAID") or + (mode == raid and raid_status == "ready")): + # This means the disk is already in the desired state, + # so skip it + continue + elif ((mode == jbod and raid_status == "ready") or + (mode == raid and raid_status == "non-RAID")): + # This disk is moving from a state we expect to RAID or + # JBOD, so keep it + final_physical_disk_ids.append(physical_disk_id) + elif raid_status == "failed": + failed_disks.append(physical_disk_id) + else: + # This disk is in one of many states that we don't know + # what to do with, so pitch it + bad_disks.append("{} ({})".format(physical_disk_id, + raid_status)) + + controllers_to_physical_disk_ids[controller] = ( + final_physical_disk_ids) + + if failed_disks or bad_disks: + error_msg = "" + + if failed_disks: + error_msg += ("The following drives have failed: " + "{failed_disks}. Manually check the status" + " of all drives and replace as necessary, then" + " try again.").format( + failed_disks=" ".join(failed_disks)) + + if bad_disks: + if failed_disks: + error_msg += "\n" + error_msg += ("Unable to change the state of the following " + "drives because their status is not ready " + "or non-RAID: {}. Bring up the RAID " + "controller GUI on this node and change the " + "drives' status to ready or non-RAID.").format( + ", ".join(bad_disks)) + + raise ValueError(error_msg) + + return controllers_to_physical_disk_ids + + def change_physical_disk_state(self, mode, + controllers_to_physical_disk_ids=None): + """Convert disks RAID status + + This method intelligently converts the requested physical disks from + RAID to JBOD or vice versa. It does this by only converting the + disks that are not already in the correct state. + + :param mode: constants.RaidStatus enumeration that indicates the mode + to change the disks to. + :param controllers_to_physical_disk_ids: Dictionary of controllers and + corresponding disk ids to convert to the requested mode. + :returns: a dictionary containing: + - conversion_results, a dictionary that maps controller ids + to the conversion results for that controller. The + conversion results are a dict that contains: + - The is_commit_required key with the value always set to + True indicating that a config job must be created to + complete disk conversion. + - The is_reboot_required key with a RebootRequired + enumerated value indicating whether the server must be + rebooted to complete disk conversion. + :raises: DRACOperationFailed on error reported back by the DRAC and the + exception message does not contain NOT_SUPPORTED_MSG constant. + :raises: Exception on unknown error. + """ + physical_disks = self.list_physical_disks() + + raid = constants.RaidStatus.raid + + if not controllers_to_physical_disk_ids: + controllers_to_physical_disk_ids = collections.defaultdict(list) + + all_controllers = self.list_raid_controllers() + for physical_d in physical_disks: + # Weed out disks that are not attached to a RAID controller + if self.is_raid_controller(physical_d.controller, + all_controllers): + physical_disk_ids = controllers_to_physical_disk_ids[ + physical_d.controller] + + physical_disk_ids.append(physical_d.id) + + '''Modify controllers_to_physical_disk_ids dict by inspecting desired + status vs current status of each controller's disks. + Raise exception if there are any failed drives or + drives not in status 'ready' or 'non-RAID' + ''' + final_ctls_to_phys_disk_ids = self._check_disks_status( + mode, physical_disks, controllers_to_physical_disk_ids) + + controllers_to_results = {} + for controller, physical_disk_ids \ + in final_ctls_to_phys_disk_ids.items(): + if physical_disk_ids: + LOG.debug("Converting the following disks to {} on RAID " + "controller {}: {}".format( + mode, controller, str(physical_disk_ids))) + try: + conversion_results = \ + self.convert_physical_disks(physical_disk_ids, + mode == raid) + except exceptions.DRACOperationFailed as ex: + if constants.NOT_SUPPORTED_MSG in str(ex): + LOG.debug("Controller {} does not support " + "JBOD mode".format(controller)) + controllers_to_results[controller] = \ + utils.build_return_dict( + doc=None, + resource_uri=None, + is_commit_required_value=False, + is_reboot_required_value=constants. + RebootRequired.false) + else: + raise + else: + controllers_to_results[controller] = conversion_results + else: + controllers_to_results[controller] = \ + utils.build_return_dict( + doc=None, + resource_uri=None, + is_commit_required_value=False, + is_reboot_required_value=constants. + RebootRequired.false) + + return {'conversion_results': controllers_to_results} + + def is_realtime_supported(self, raid_controller_fqdd): + """Find if controller supports realtime or not + + :param raid_controller_fqdd: ID of RAID controller + :returns: True or False + """ + drac_raid_controllers = self.list_raid_controllers() + realtime_controller = [cnt.id for cnt in drac_raid_controllers + if cnt.supports_realtime] + + if raid_controller_fqdd in realtime_controller: + return True + + return False + + def reset_raid_config(self, raid_controller): + """Delete all virtual disk and unassign all hotspares + + The job to reset the RAID controller config will be in pending state. + For the changes to be applied, a config job must be created. + + :param raid_controller: id of the RAID controller + :returns: a dictionary containing: + - The is_commit_required key with the value always set to + True indicating that a config job must be created to + reset configuration. + - The is_reboot_required key with a RebootRequired enumerated + value indicating whether the server must be rebooted to + reset configuration. + :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 + """ + + selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem', + 'CreationClassName': 'DCIM_RAIDService', + 'SystemName': 'DCIM:ComputerSystem', + 'Name': 'DCIM:RAIDService'} + properties = {'Target': raid_controller} + + doc = self.client.invoke(uris.DCIM_RAIDService, 'ResetConfig', + selectors, properties, + expected_return_value=utils.RET_SUCCESS) + + return utils.build_return_dict(doc, uris.DCIM_RAIDService, + is_commit_required_value=True) + + def clear_foreign_config(self, raid_controller): + """Free up foreign drives + + The job to clear foreign config will be in pending state. + For the changes to be applied, a config job must be created. + + :param raid_controller: id of the RAID controller + :returns: a dictionary containing: + - The is_commit_required key with the value always set to + True indicating that a config job must be created to + clear foreign configuration. + - The is_reboot_required key with a RebootRequired enumerated + value indicating whether the server must be rebooted to + clear foreign configuration. + :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 + """ + + selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem', + 'CreationClassName': 'DCIM_RAIDService', + 'SystemName': 'DCIM:ComputerSystem', + 'Name': 'DCIM:RAIDService'} + properties = {'Target': raid_controller} + + doc = self.client.invoke(uris.DCIM_RAIDService, 'ClearForeignConfig', + selectors, properties, + check_return_value=False) + + is_commit_required_value = True + is_reboot_required_value = None + + ret_value = utils.find_xml(doc, + 'ReturnValue', + uris.DCIM_RAIDService).text + + if ret_value == utils.RET_ERROR: + message_id = utils.find_xml(doc, + 'MessageID', + uris.DCIM_RAIDService).text + + # A MessageID 'STOR018'/'STOR058' indicates no foreign drive was + # detected. Return a value which informs the caller nothing + # further needs to be done. + no_foreign_drives_detected = any( + stor_id == message_id for stor_id in NO_FOREIGN_DRIVES) + if no_foreign_drives_detected: + is_commit_required_value = False + is_reboot_required_value = constants.RebootRequired.false + else: + message = utils.find_xml(doc, + 'Message', + uris.DCIM_RAIDService).text + raise exceptions.DRACOperationFailed( + drac_messages=message) + + return utils.build_return_dict( + doc, uris.DCIM_RAIDService, + is_commit_required_value=is_commit_required_value, + is_reboot_required_value=is_reboot_required_value) diff --git a/dracclient/resources/system.py b/dracclient/resources/system.py new file mode 100644 index 0000000..1069cc3 --- /dev/null +++ b/dracclient/resources/system.py @@ -0,0 +1,279 @@ +# +# 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. + +from dracclient.resources import uris +from dracclient import utils +from dracclient import wsman + + +class SystemConfiguration(object): + + def __init__(self, client): + """Creates SystemManagement object + + :param client: an instance of WSManClient + """ + self.client = client + + def list_system_settings(self): + """List the System configuration settings + + :returns: a dictionary with the System settings using its name as the + key. The attributes are either SystemEnumerableAttribute, + SystemStringAttribute or SystemIntegerAttribute 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_SystemEnumeration, SystemEnumerableAttribute), + (uris.DCIM_SystemString, SystemStringAttribute), + (uris.DCIM_SystemInteger, SystemIntegerAttribute)] + for (namespace, attr_cls) in namespaces: + attribs = self._get_config(namespace, attr_cls) + 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) + + if items is not None: + for item in items: + attribute = attr_cls.parse(item) + result[attribute.instance_id] = attribute + return result + + +class SystemAttribute(object): + """Generic System attribute class""" + + def __init__(self, name, instance_id, current_value, pending_value, + read_only, fqdd, group_id): + """Creates SystemAttribute object + + :param name: name of the System attribute + :param instance_id: InstanceID of the System attribute + :param current_value: current value of the System attribute + :param pending_value: pending value of the System attribute, reflecting + an unprocessed change (eg. config job not completed) + :param read_only: indicates whether this System attribute can be + changed + :param fqdd: Fully Qualified Device Description of the System attribute + :param group_id: GroupID of System attribute + """ + self.name = name + self.instance_id = instance_id + self.current_value = current_value + self.pending_value = pending_value + self.read_only = read_only + self.fqdd = fqdd + self.group_id = group_id + + def __eq__(self, other): + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + return not self.__eq__(other) + + @classmethod + def parse(cls, namespace, system_attr_xml): + """Parses XML and creates SystemAttribute object""" + + name = utils.get_wsman_resource_attr( + system_attr_xml, namespace, 'AttributeName') + instance_id = utils.get_wsman_resource_attr( + system_attr_xml, namespace, 'InstanceID') + current_value = utils.get_wsman_resource_attr( + system_attr_xml, namespace, 'CurrentValue', nullable=True) + pending_value = utils.get_wsman_resource_attr( + system_attr_xml, namespace, 'PendingValue', nullable=True) + read_only = utils.get_wsman_resource_attr( + system_attr_xml, namespace, 'IsReadOnly') + fqdd = utils.get_wsman_resource_attr( + system_attr_xml, namespace, 'FQDD') + group_id = utils.get_wsman_resource_attr( + system_attr_xml, namespace, 'GroupID') + + return cls(name, instance_id, current_value, pending_value, + (read_only == 'true'), fqdd, group_id) + + +class SystemEnumerableAttribute(SystemAttribute): + """Enumerable System attribute class""" + + namespace = uris.DCIM_SystemEnumeration + + def __init__(self, name, instance_id, current_value, pending_value, + read_only, fqdd, group_id, possible_values): + """Creates SystemEnumerableAttribute object + + :param name: name of the System attribute + :param instance_id: InstanceID of the System attribute + :param current_value: current value of the System attribute + :param pending_value: pending value of the System attribute, reflecting + an unprocessed change (eg. config job not completed) + :param read_only: indicates whether this System attribute can be + changed + :param fqdd: Fully Qualified Device Description of the System attribute + :param group_id: GroupID of System attribute + :param possible_values: list containing the allowed values for the + System attribute + """ + super(SystemEnumerableAttribute, self).__init__(name, instance_id, + current_value, + pending_value, + read_only, fqdd, + group_id) + self.possible_values = possible_values + + @classmethod + def parse(cls, system_attr_xml): + """Parses XML and creates SystemEnumerableAttribute object""" + + system_attr = SystemAttribute.parse( + cls.namespace, system_attr_xml) + possible_values = [attr.text for attr + in utils.find_xml(system_attr_xml, 'PossibleValues', + cls.namespace, find_all=True)] + + return cls(system_attr.name, system_attr.instance_id, + system_attr.current_value, system_attr.pending_value, + system_attr.read_only, system_attr.fqdd, + system_attr.group_id, 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 SystemStringAttribute(SystemAttribute): + """String System attribute class""" + + namespace = uris.DCIM_SystemString + + def __init__(self, name, instance_id, current_value, pending_value, + read_only, fqdd, group_id, min_length, max_length): + """Creates SystemStringAttribute object + + :param name: name of the System attribute + :param instance_id: InstanceID of the System attribute + :param current_value: current value of the System attribute + :param pending_value: pending value of the System attribute, reflecting + an unprocessed change (eg. config job not completed) + :param read_only: indicates whether this System attribute can be + changed + :param fqdd: Fully Qualified Device Description of the System attribute + :param group_id: GroupID of System attribute + :param min_length: minimum length of the string + :param max_length: maximum length of the string + """ + super(SystemStringAttribute, self).__init__(name, instance_id, + current_value, + pending_value, read_only, + fqdd, group_id) + self.min_length = min_length + self.max_length = max_length + + @classmethod + def parse(cls, system_attr_xml): + """Parses XML and creates SystemStringAttribute object""" + + system_attr = SystemAttribute.parse( + cls.namespace, system_attr_xml) + min_length = int(utils.get_wsman_resource_attr( + system_attr_xml, cls.namespace, 'MinLength')) + max_length = int(utils.get_wsman_resource_attr( + system_attr_xml, cls.namespace, 'MaxLength')) + + return cls(system_attr.name, system_attr.instance_id, + system_attr.current_value, system_attr.pending_value, + system_attr.read_only, system_attr.fqdd, + system_attr.group_id, min_length, max_length) + + +class SystemIntegerAttribute(SystemAttribute): + """Integer System attribute class""" + + namespace = uris.DCIM_SystemInteger + + def __init__(self, name, instance_id, current_value, pending_value, + read_only, fqdd, group_id, lower_bound, upper_bound): + """Creates SystemIntegerAttribute object + + :param name: name of the System attribute + :param instance_id: InstanceID of the System attribute + :param current_value: current value of the System attribute + :param pending_value: pending value of the System attribute, reflecting + an unprocessed change (eg. config job not completed) + :param read_only: indicates whether this System attribute can be + changed + :param fqdd: Fully Qualified Device Description of the System attribute + :param group_id: GroupID of System attribute + :param lower_bound: minimum value for the System attribute + :param upper_bound: maximum value for the BOIS attribute + """ + super(SystemIntegerAttribute, self).__init__(name, instance_id, + current_value, + pending_value, read_only, + fqdd, group_id) + self.lower_bound = lower_bound + self.upper_bound = upper_bound + + @classmethod + def parse(cls, system_attr_xml): + """Parses XML and creates SystemIntegerAttribute object""" + + system_attr = SystemAttribute.parse(cls.namespace, system_attr_xml) + lower_bound = utils.get_wsman_resource_attr( + system_attr_xml, cls.namespace, 'LowerBound', nullable=True) + upper_bound = utils.get_wsman_resource_attr( + system_attr_xml, cls.namespace, 'UpperBound', nullable=True) + + if system_attr.current_value: + system_attr.current_value = int(system_attr.current_value) + if system_attr.pending_value: + system_attr.pending_value = int(system_attr.pending_value) + + if lower_bound: + lower_bound = int(lower_bound) + if upper_bound: + upper_bound = int(upper_bound) + return cls(system_attr.name, system_attr.instance_id, + system_attr.current_value, system_attr.pending_value, + system_attr.read_only, system_attr.fqdd, + system_attr.group_id, lower_bound, 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 diff --git a/dracclient/resources/uris.py b/dracclient/resources/uris.py index b1dea17..218d85d 100644 --- a/dracclient/resources/uris.py +++ b/dracclient/resources/uris.py @@ -43,21 +43,79 @@ DCIM_CPUView = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' 'DCIM_CPUView') +DCIM_iDRACCardEnumeration = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/' + '2/DCIM_iDRACCardEnumeration') + +DCIM_iDRACCardInteger = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' + 'DCIM_iDRACCardInteger') + +DCIM_iDRACCardService = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' + 'DCIM_iDRACCardService') + +DCIM_iDRACCardString = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' + 'DCIM_iDRACCardString') + +DCIM_JobService = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' + 'DCIM_JobService') + +DCIM_LCEnumeration = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' + 'DCIM_LCEnumeration') + +DCIM_LCService = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' + 'DCIM_LCService') + +DCIM_LCString = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' + 'DCIM_LCString') + DCIM_LifecycleJob = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' 'DCIM_LifecycleJob') DCIM_MemoryView = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' 'DCIM_MemoryView') +DCIM_NICEnumeration = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' + 'DCIM_NICEnumeration') + +DCIM_NICInteger = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' + 'DCIM_NICInteger') + +DCIM_NICService = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' + 'DCIM_NICService') + +DCIM_NICString = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' + 'DCIM_NICString') + DCIM_NICView = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' 'DCIM_NICView') +DCIM_PCIeSSDView = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' + 'DCIM_PCIeSSDView') + DCIM_PhysicalDiskView = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' 'DCIM_PhysicalDiskView') +DCIM_RAIDEnumeration = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' + 'DCIM_RAIDEnumeration') + +DCIM_RAIDInteger = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' + 'DCIM_RAIDInteger') + DCIM_RAIDService = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' 'DCIM_RAIDService') + +DCIM_RAIDString = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' + 'DCIM_RAIDString') + +DCIM_SystemEnumeration = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' + 'DCIM_SystemEnumeration') + +DCIM_SystemInteger = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' + 'DCIM_SystemInteger') + +DCIM_SystemString = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' + 'DCIM_SystemString') + DCIM_SystemView = ('http://schemas.dell.com/wbem/wscim/1/cim-schema/2/' 'DCIM_SystemView') diff --git a/dracclient/tests/test_bios.py b/dracclient/tests/test_bios.py index 6aead8b..0cc4c25 100644 --- a/dracclient/tests/test_bios.py +++ b/dracclient/tests/test_bios.py @@ -12,12 +12,13 @@ # under the License. import re +from unittest import mock import lxml.etree -import mock import requests_mock import dracclient.client +from dracclient import constants from dracclient import exceptions from dracclient.resources import bios import dracclient.resources.job @@ -29,6 +30,8 @@ @requests_mock.Mocker() +@mock.patch.object(dracclient.client.WSManClient, 'wait_until_idrac_is_ready', + spec_set=True, autospec=True) class ClientPowerManagementTestCase(base.BaseTest): def setUp(self): @@ -36,14 +39,16 @@ def setUp(self): self.drac_client = dracclient.client.DRACClient( **test_utils.FAKE_ENDPOINT) - def test_get_power_state(self, mock_requests): + def test_get_power_state(self, mock_requests, + mock_wait_until_idrac_is_ready): mock_requests.post( 'https://1.2.3.4:443/wsman', text=test_utils.BIOSEnumerations[uris.DCIM_ComputerSystem]['ok']) self.assertEqual('POWER_ON', self.drac_client.get_power_state()) - def test_set_power_state(self, mock_requests): + def test_set_power_state(self, mock_requests, + mock_wait_until_idrac_is_ready): mock_requests.post( 'https://1.2.3.4:443/wsman', text=test_utils.BIOSInvocations[ @@ -51,7 +56,8 @@ def test_set_power_state(self, mock_requests): self.assertIsNone(self.drac_client.set_power_state('POWER_ON')) - def test_set_power_state_fail(self, mock_requests): + def test_set_power_state_fail(self, mock_requests, + mock_wait_until_idrac_is_ready): mock_requests.post( 'https://1.2.3.4:443/wsman', text=test_utils.BIOSInvocations[ @@ -60,11 +66,15 @@ def test_set_power_state_fail(self, mock_requests): self.assertRaises(exceptions.DRACOperationFailed, self.drac_client.set_power_state, 'POWER_ON') - def test_set_power_state_invalid_target_state(self, mock_requests): + def test_set_power_state_invalid_target_state( + self, mock_requests, mock_wait_until_idrac_is_ready): self.assertRaises(exceptions.InvalidParameterValue, self.drac_client.set_power_state, 'foo') +@requests_mock.Mocker() +@mock.patch.object(dracclient.client.WSManClient, 'wait_until_idrac_is_ready', + spec_set=True, autospec=True) class ClientBootManagementTestCase(base.BaseTest): def setUp(self): @@ -72,8 +82,8 @@ def setUp(self): self.drac_client = dracclient.client.DRACClient( **test_utils.FAKE_ENDPOINT) - @requests_mock.Mocker() - def test_list_boot_modes(self, mock_requests): + def test_list_boot_modes(self, mock_requests, + mock_wait_until_idrac_is_ready): expected_boot_mode = bios.BootMode(id='IPL', name='BootSeq', is_current=True, is_next=True) mock_requests.post( @@ -86,8 +96,8 @@ def test_list_boot_modes(self, mock_requests): self.assertEqual(5, len(boot_modes)) self.assertIn(expected_boot_mode, boot_modes) - @requests_mock.Mocker() - def test_list_boot_devices(self, mock_requests): + def test_list_boot_devices(self, mock_requests, + mock_wait_until_idrac_is_ready): expected_boot_device = bios.BootDevice( id=('IPL:BIOS.Setup.1-1#BootSeq#NIC.Embedded.1-1-1#' 'fbeeb18f19fd4e768c941e66af4fc424'), @@ -116,11 +126,11 @@ def test_list_boot_devices(self, mock_requests): self.assertEqual( 2, boot_devices['IPL'][2].pending_assigned_sequence) - @requests_mock.Mocker() @mock.patch.object(lifecycle_controller.LifecycleControllerManagement, 'get_version', spec_set=True, autospec=True) def test_list_boot_devices_11g(self, mock_requests, - mock_get_lifecycle_controller_version): + mock_get_lifecycle_controller_version, + mock_wait_until_idrac_is_ready): expected_boot_device = bios.BootDevice( id=('IPL:NIC.Embedded.1-1:082927b7c62a9f52ef0d65a33416d76c'), boot_mode='IPL', @@ -150,8 +160,8 @@ def test_list_boot_devices_11g(self, mock_requests, self.assertEqual( 2, boot_devices['IPL'][2].pending_assigned_sequence) - @requests_mock.Mocker() - def test_change_boot_device_order(self, mock_requests): + def test_change_boot_device_order(self, mock_requests, + mock_wait_until_idrac_is_ready): mock_requests.post( 'https://1.2.3.4:443/wsman', text=test_utils.BIOSInvocations[ @@ -163,7 +173,8 @@ def test_change_boot_device_order(self, mock_requests): @mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True, autospec=True) - def test_change_boot_device_order_list(self, mock_invoke): + def test_change_boot_device_order_list(self, mock_requests, mock_invoke, + mock_wait_until_idrac_is_ready): expected_selectors = {'InstanceID': 'IPL'} expected_properties = {'source': ['foo', 'bar', 'baz']} mock_invoke.return_value = lxml.etree.fromstring( @@ -178,8 +189,8 @@ def test_change_boot_device_order_list(self, mock_invoke): 'ChangeBootOrderByInstanceID', expected_selectors, expected_properties, expected_return_value=utils.RET_SUCCESS) - @requests_mock.Mocker() - def test_change_boot_device_order_error(self, mock_requests): + def test_change_boot_device_order_error(self, mock_requests, + mock_wait_until_idrac_is_ready): mock_requests.post( 'https://1.2.3.4:443/wsman', text=test_utils.BIOSInvocations[ @@ -191,6 +202,9 @@ def test_change_boot_device_order_error(self, mock_requests): self.drac_client.change_boot_device_order, 'IPL', 'foo') +@requests_mock.Mocker() +@mock.patch.object(dracclient.client.WSManClient, 'wait_until_idrac_is_ready', + spec_set=True, autospec=True) class ClientBIOSConfigurationTestCase(base.BaseTest): def setUp(self): @@ -198,8 +212,8 @@ def setUp(self): self.drac_client = dracclient.client.DRACClient( **test_utils.FAKE_ENDPOINT) - @requests_mock.Mocker() - def test_list_bios_settings_by_instance_id(self, mock_requests): + def test_list_bios_settings_by_instance_id(self, mock_requests, + mock_wait_until_idrac_is_ready): expected_enum_attr = bios.BIOSEnumerableAttribute( name='MemTest', instance_id='BIOS.Setup.1-1:MemTest', @@ -248,8 +262,8 @@ def test_list_bios_settings_by_instance_id(self, mock_requests): self.assertEqual(expected_integer_attr, bios_settings[ 'BIOS.Setup.1-1:Proc1NumCores']) - @requests_mock.Mocker() - def test_list_bios_settings_by_name(self, mock_requests): + def test_list_bios_settings_by_name(self, mock_requests, + mock_wait_until_idrac_is_ready): expected_enum_attr = bios.BIOSEnumerableAttribute( name='MemTest', instance_id='BIOS.Setup.1-1:MemTest', @@ -296,9 +310,8 @@ def test_list_bios_settings_by_name(self, mock_requests): self.assertIn('Proc1NumCores', bios_settings) self.assertEqual(expected_integer_attr, bios_settings['Proc1NumCores']) - @requests_mock.Mocker() def test_list_bios_settings_by_name_with_colliding_attrs( - self, mock_requests): + self, mock_requests, mock_wait_until_idrac_is_ready): mock_requests.post('https://1.2.3.4:443/wsman', [ {'text': test_utils.BIOSEnumerations[ uris.DCIM_BIOSEnumeration]['ok']}, @@ -310,10 +323,10 @@ def test_list_bios_settings_by_name_with_colliding_attrs( self.assertRaises(exceptions.DRACOperationFailed, self.drac_client.list_bios_settings, by_name=True) - @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): + def test_set_bios_settings(self, mock_requests, mock_invoke, + mock_wait_until_idrac_is_ready): expected_selectors = {'CreationClassName': 'DCIM_BIOSService', 'SystemName': 'DCIM:ComputerSystem', 'Name': 'DCIM:BIOSService', @@ -333,15 +346,19 @@ def test_set_bios_settings(self, mock_requests, mock_invoke): 'SetAttributes']['ok']) result = self.drac_client.set_bios_settings( - {'ProcVirtualization': 'Disabled'}) + {'ProcVirtualization': 'Disabled', + 'DynamicCoreAllocation': 'Disabled'}) - self.assertEqual({'commit_required': True}, result) + self.assertEqual({'is_commit_required': True, + 'is_reboot_required': constants.RebootRequired.true}, + result) mock_invoke.assert_called_once_with( mock.ANY, uris.DCIM_BIOSService, 'SetAttributes', - expected_selectors, expected_properties) + expected_selectors, expected_properties, + wait_for_idrac=True) - @requests_mock.Mocker() - def test_set_bios_settings_error(self, mock_requests): + def test_set_bios_settings_error(self, mock_requests, + mock_wait_until_idrac_is_ready): mock_requests.post('https://1.2.3.4:443/wsman', [ {'text': test_utils.BIOSEnumerations[ uris.DCIM_BIOSEnumeration]['ok']}, @@ -356,8 +373,8 @@ def test_set_bios_settings_error(self, mock_requests): self.drac_client.set_bios_settings, {'ProcVirtualization': 'Disabled'}) - @requests_mock.Mocker() - def test_set_bios_settings_with_unknown_attr(self, mock_requests): + def test_set_bios_settings_with_unknown_attr( + self, mock_requests, mock_wait_until_idrac_is_ready): mock_requests.post('https://1.2.3.4:443/wsman', [ {'text': test_utils.BIOSEnumerations[ uris.DCIM_BIOSEnumeration]['ok']}, @@ -369,8 +386,8 @@ def test_set_bios_settings_with_unknown_attr(self, mock_requests): 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): + def test_set_bios_settings_with_unchanged_attr( + self, mock_requests, mock_wait_until_idrac_is_ready): mock_requests.post('https://1.2.3.4:443/wsman', [ {'text': test_utils.BIOSEnumerations[ uris.DCIM_BIOSEnumeration]['ok']}, @@ -382,10 +399,13 @@ def test_set_bios_settings_with_unchanged_attr(self, mock_requests): result = self.drac_client.set_bios_settings( {'ProcVirtualization': 'Enabled'}) - self.assertEqual({'commit_required': False}, result) + self.assertEqual({'is_commit_required': False, + 'is_reboot_required': + constants.RebootRequired.false}, + result) - @requests_mock.Mocker() - def test_set_bios_settings_with_readonly_attr(self, mock_requests): + def test_set_bios_settings_with_readonly_attr( + self, mock_requests, mock_wait_until_idrac_is_ready): expected_message = ("Cannot set read-only BIOS attributes: " "['Proc1NumCores'].") mock_requests.post('https://1.2.3.4:443/wsman', [ @@ -400,8 +420,8 @@ def test_set_bios_settings_with_readonly_attr(self, mock_requests): 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): + def test_set_bios_settings_with_incorrect_enum_value( + self, mock_requests, mock_wait_until_idrac_is_ready): 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', [ @@ -416,8 +436,8 @@ def test_set_bios_settings_with_incorrect_enum_value(self, mock_requests): 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): + def test_set_bios_settings_with_incorrect_regexp( + self, mock_requests, mock_wait_until_idrac_is_ready): 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', [ @@ -432,8 +452,8 @@ def test_set_bios_settings_with_incorrect_regexp(self, mock_requests): 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): + def test_set_bios_settings_with_out_of_bounds_value( + self, mock_requests, mock_wait_until_idrac_is_ready): 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', [ @@ -464,7 +484,8 @@ def test_commit_pending_bios_changes(self, mock_create_config_job): 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=False) + cim_name='DCIM:BIOSService', target='BIOS.Setup.1-1', + reboot=False, start_time='TIME_NOW') @mock.patch.object(dracclient.resources.job.JobManagement, 'create_config_job', spec_set=True, autospec=True) @@ -475,7 +496,38 @@ def test_commit_pending_bios_changes_with_reboot(self, 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) + cim_name='DCIM:BIOSService', target='BIOS.Setup.1-1', + reboot=True, start_time='TIME_NOW') + + @mock.patch.object(dracclient.resources.job.JobManagement, + 'create_config_job', spec_set=True, autospec=True) + def test_commit_pending_bios_changes_with_time( + self, mock_create_config_job): + timestamp = '20140924140201' + self.drac_client.commit_pending_bios_changes( + start_time=timestamp) + + 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=False, start_time=timestamp) + + @mock.patch.object(dracclient.resources.job.JobManagement, + 'create_config_job', spec_set=True, autospec=True) + def test_commit_pending_bios_changes_with_reboot_and_time( + self, + mock_create_config_job): + timestamp = '20140924140201' + self.drac_client.commit_pending_bios_changes( + reboot=True, + start_time=timestamp) + + 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, start_time=timestamp) @mock.patch.object(dracclient.resources.job.JobManagement, 'delete_pending_config', spec_set=True, autospec=True) diff --git a/dracclient/tests/test_client.py b/dracclient/tests/test_client.py index e9395c8..5e0801b 100644 --- a/dracclient/tests/test_client.py +++ b/dracclient/tests/test_client.py @@ -11,10 +11,14 @@ # License for the specific language governing permissions and limitations # under the License. +from unittest import mock + import requests_mock import dracclient.client +from dracclient import constants from dracclient import exceptions +from dracclient.resources import uris from dracclient.tests import base from dracclient.tests import utils as test_utils @@ -22,15 +26,35 @@ @requests_mock.Mocker() class WSManClientTestCase(base.BaseTest): - def test_enumerate(self, mock_requests): + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_enumerate(self, mock_requests, mock_wait_until_idrac_is_ready): mock_requests.post('https://1.2.3.4:443/wsman', text='yay!') client = dracclient.client.WSManClient(**test_utils.FAKE_ENDPOINT) resp = client.enumerate('http://resource') + mock_wait_until_idrac_is_ready.assert_called_once_with(client) + self.assertEqual('yay!', resp.text) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_enumerate_without_wait_for_idrac( + self, mock_requests, mock_wait_until_idrac_is_ready): + mock_requests.post('https://1.2.3.4:443/wsman', + text='yay!') + + client = dracclient.client.WSManClient(**test_utils.FAKE_ENDPOINT) + resp = client.enumerate('http://resource', wait_for_idrac=False) + self.assertFalse(mock_wait_until_idrac_is_ready.called) self.assertEqual('yay!', resp.text) - def test_invoke(self, mock_requests): + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_invoke(self, mock_requests, mock_wait_until_idrac_is_ready): xml = """ 42 @@ -41,6 +65,25 @@ def test_invoke(self, mock_requests): client = dracclient.client.WSManClient(**test_utils.FAKE_ENDPOINT) resp = client.invoke('http://resource', 'Foo') + mock_wait_until_idrac_is_ready.assert_called_once_with(client) + self.assertEqual('yay!', resp.find('result').text) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_invoke_without_wait_for_idrac( + self, mock_requests, mock_wait_until_idrac_is_ready): + xml = """ + + 42 + yay! + +""" # noqa + mock_requests.post('https://1.2.3.4:443/wsman', text=xml) + + client = dracclient.client.WSManClient(**test_utils.FAKE_ENDPOINT) + resp = client.invoke('http://resource', 'Foo', wait_for_idrac=False) + self.assertFalse(mock_wait_until_idrac_is_ready.called) self.assertEqual('yay!', resp.find('result').text) def test_invoke_with_expected_return_value(self, mock_requests): @@ -54,7 +97,7 @@ def test_invoke_with_expected_return_value(self, mock_requests): client = dracclient.client.WSManClient(**test_utils.FAKE_ENDPOINT) resp = client.invoke('http://resource', 'Foo', - expected_return_value='42') + expected_return_value='42', wait_for_idrac=False) self.assertEqual('yay!', resp.find('result').text) def test_invoke_with_error_return_value(self, mock_requests): @@ -68,7 +111,21 @@ def test_invoke_with_error_return_value(self, mock_requests): client = dracclient.client.WSManClient(**test_utils.FAKE_ENDPOINT) self.assertRaises(exceptions.DRACOperationFailed, client.invoke, - 'http://resource', 'Foo') + 'http://resource', 'Foo', wait_for_idrac=False) + + def test_invoke_with_unchecked_return_value(self, mock_requests): + xml = """ + + 2 + yay! + +""" # noqa + mock_requests.post('https://1.2.3.4:443/wsman', text=xml) + + client = dracclient.client.WSManClient(**test_utils.FAKE_ENDPOINT) + resp = client.invoke('http://resource', 'Foo', + wait_for_idrac=False, check_return_value=False) + self.assertEqual('yay!', resp.find('result').text) def test_invoke_with_unexpected_return_value(self, mock_requests): xml = """ @@ -82,4 +139,101 @@ def test_invoke_with_unexpected_return_value(self, mock_requests): client = dracclient.client.WSManClient(**test_utils.FAKE_ENDPOINT) self.assertRaises(exceptions.DRACUnexpectedReturnValue, client.invoke, 'http://resource', 'Foo', - expected_return_value='4242') + expected_return_value='4242', wait_for_idrac=False) + + def test_is_idrac_ready_ready(self, mock_requests): + expected_text = test_utils.LifecycleControllerInvocations[ + uris.DCIM_LCService]['GetRemoteServicesAPIStatus']['is_ready'] + mock_requests.post('https://1.2.3.4:443/wsman', + text=expected_text) + + client = dracclient.client.WSManClient(**test_utils.FAKE_ENDPOINT) + self.assertTrue(client.is_idrac_ready()) + + def test_is_idrac_ready_not_ready(self, mock_requests): + expected_text = test_utils.LifecycleControllerInvocations[ + uris.DCIM_LCService]['GetRemoteServicesAPIStatus']['is_not_ready'] + mock_requests.post('https://1.2.3.4:443/wsman', + text=expected_text) + + client = dracclient.client.WSManClient(**test_utils.FAKE_ENDPOINT) + self.assertFalse(client.is_idrac_ready()) + + @mock.patch.object(dracclient.client.WSManClient, 'is_idrac_ready', + autospec=True) + @mock.patch('time.sleep', autospec=True) + def test_wait_until_idrac_is_ready_with_none_arguments( + self, mock_requests, mock_ts, mock_is_idrac_ready): + ready_retries = 2 + ready_retry_delay = 1 + + side_effect = (ready_retries - 1) * [False] + side_effect.append(True) + mock_is_idrac_ready.side_effect = side_effect + + fake_endpoint = test_utils.FAKE_ENDPOINT.copy() + fake_endpoint['ready_retries'] = ready_retries + fake_endpoint['ready_retry_delay'] = ready_retry_delay + + client = dracclient.client.WSManClient(**fake_endpoint) + client.wait_until_idrac_is_ready(retries=None, retry_delay=None) + + self.assertEqual(mock_is_idrac_ready.call_count, ready_retries) + self.assertEqual(mock_ts.call_count, ready_retries - 1) + mock_ts.assert_called_with(ready_retry_delay) + + @mock.patch.object(dracclient.client.WSManClient, 'is_idrac_ready', + autospec=True) + @mock.patch('time.sleep', autospec=True) + def test_wait_until_idrac_is_ready_with_non_none_arguments( + self, mock_requests, mock_ts, mock_is_idrac_ready): + retries = 2 + self.assertNotEqual(retries, constants.DEFAULT_IDRAC_IS_READY_RETRIES) + + retry_delay = 1 + self.assertNotEqual( + retry_delay, constants.DEFAULT_IDRAC_IS_READY_RETRY_DELAY_SEC) + + side_effect = (retries - 1) * [False] + side_effect.append(True) + mock_is_idrac_ready.side_effect = side_effect + + fake_endpoint = test_utils.FAKE_ENDPOINT.copy() + fake_endpoint['ready_retries'] = ( + constants.DEFAULT_IDRAC_IS_READY_RETRIES) + fake_endpoint['ready_retry_delay'] = ( + constants.DEFAULT_IDRAC_IS_READY_RETRY_DELAY_SEC) + + client = dracclient.client.WSManClient(**fake_endpoint) + client.wait_until_idrac_is_ready(retries, retry_delay) + + self.assertEqual(mock_is_idrac_ready.call_count, retries) + self.assertEqual(mock_ts.call_count, retries - 1) + mock_ts.assert_called_with(retry_delay) + + def test_wait_until_idrac_is_ready_ready(self, mock_requests): + expected_text = test_utils.LifecycleControllerInvocations[ + uris.DCIM_LCService]['GetRemoteServicesAPIStatus']['is_ready'] + mock_requests.post('https://1.2.3.4:443/wsman', + text=expected_text) + + client = dracclient.client.WSManClient(**test_utils.FAKE_ENDPOINT) + + try: + client.wait_until_idrac_is_ready() + except exceptions.DRACOperationFailed: + self.fail('wait_until_idrac_is_ready() timed out when it should ' + 'not have!') + + @mock.patch('time.sleep', autospec=True) + def test_wait_until_idrac_is_ready_timeout(self, + mock_requests, + mock_ts): + expected_text = test_utils.LifecycleControllerInvocations[ + uris.DCIM_LCService]['GetRemoteServicesAPIStatus']['is_not_ready'] + mock_requests.post('https://1.2.3.4:443/wsman', + text=expected_text) + + client = dracclient.client.WSManClient(**test_utils.FAKE_ENDPOINT) + self.assertRaises(exceptions.DRACOperationFailed, + client.wait_until_idrac_is_ready) diff --git a/dracclient/tests/test_idrac_card.py b/dracclient/tests/test_idrac_card.py new file mode 100644 index 0000000..d3db623 --- /dev/null +++ b/dracclient/tests/test_idrac_card.py @@ -0,0 +1,640 @@ +# +# 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 lxml.etree +import re +from unittest import mock + +import requests_mock + +import dracclient.client +from dracclient import constants +from dracclient import exceptions +from dracclient.resources import idrac_card +from dracclient.resources import job +from dracclient.resources import uris +from dracclient.tests import base +from dracclient.tests import utils as test_utils + + +@requests_mock.Mocker() +@mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) +class ClientiDRACCardConfigurationTestCase(base.BaseTest): + + def setUp(self): + super(ClientiDRACCardConfigurationTestCase, self).setUp() + self.drac_client = dracclient.client.DRACClient( + **test_utils.FAKE_ENDPOINT) + + def test_list_idrac_settings_by_instance_id( + self, mock_requests, mock_wait_until_idrac_is_ready): + expected_enum_attr = idrac_card.iDRACCardEnumerableAttribute( + name='Type', + instance_id='iDRAC.Embedded.1#Info.1#Type', + read_only=True, + current_value='13G Monolithic', + pending_value=None, + fqdd='iDRAC.Embedded.1', + group_id='Info.1', + possible_values=['12G/13G', '12G Monolithic', '12G Modular', + '13G Monolithic', '13G Modular', '12G DCS', + '13G DCS']) + expected_string_attr = idrac_card.iDRACCardStringAttribute( + name='Version', + instance_id='iDRAC.Embedded.1#Info.1#Version', + read_only=True, + current_value='2.40.40.40', + pending_value=None, + fqdd='iDRAC.Embedded.1', + group_id='Info.1', + min_length=0, + max_length=63) + expected_integer_attr = idrac_card.iDRACCardIntegerAttribute( + name='Port', + instance_id='iDRAC.Embedded.1#SSH.1#Port', + read_only=False, + current_value=22, + pending_value=None, + fqdd='iDRAC.Embedded.1', + group_id='SSH.1', + lower_bound=1, + upper_bound=65535) + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.iDracCardEnumerations[ + uris.DCIM_iDRACCardEnumeration]['ok']}, + {'text': test_utils.iDracCardEnumerations[ + uris.DCIM_iDRACCardString]['ok']}, + {'text': test_utils.iDracCardEnumerations[ + uris.DCIM_iDRACCardInteger]['ok']}]) + + idrac_settings = self.drac_client.list_idrac_settings() + + self.assertEqual(631, len(idrac_settings)) + # enumerable attribute + self.assertIn('iDRAC.Embedded.1#Info.1#Type', idrac_settings) + self.assertEqual(expected_enum_attr, idrac_settings[ + 'iDRAC.Embedded.1#Info.1#Type']) + # string attribute + self.assertIn('iDRAC.Embedded.1#Info.1#Version', idrac_settings) + self.assertEqual(expected_string_attr, + idrac_settings['iDRAC.Embedded.1#Info.1#Version']) + # integer attribute + self.assertIn('iDRAC.Embedded.1#SSH.1#Port', idrac_settings) + self.assertEqual(expected_integer_attr, idrac_settings[ + 'iDRAC.Embedded.1#SSH.1#Port']) + + def test_list_idrac_settings_by_name( + self, mock_requests, mock_wait_until_idrac_is_ready): + expected_enum_attr = idrac_card.iDRACCardEnumerableAttribute( + name='Type', + instance_id='iDRAC.Embedded.1#Info.1#Type', + read_only=True, + current_value='13G Monolithic', + pending_value=None, + fqdd='iDRAC.Embedded.1', + group_id='Info.1', + possible_values=['12G/13G', '12G Monolithic', '12G Modular', + '13G Monolithic', '13G Modular', '12G DCS', + '13G DCS']) + expected_string_attr = idrac_card.iDRACCardStringAttribute( + name='Version', + instance_id='iDRAC.Embedded.1#Info.1#Version', + read_only=True, + current_value='2.40.40.40', + pending_value=None, + fqdd='iDRAC.Embedded.1', + group_id='Info.1', + min_length=0, + max_length=63) + expected_integer_attr = idrac_card.iDRACCardIntegerAttribute( + name='Port', + instance_id='iDRAC.Embedded.1#SSH.1#Port', + read_only=False, + current_value=22, + pending_value=None, + fqdd='iDRAC.Embedded.1', + group_id='SSH.1', + lower_bound=1, + upper_bound=65535) + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.iDracCardEnumerations[ + uris.DCIM_iDRACCardEnumeration]['ok']}, + {'text': test_utils.iDracCardEnumerations[ + uris.DCIM_iDRACCardString]['ok']}, + {'text': test_utils.iDracCardEnumerations[ + uris.DCIM_iDRACCardInteger]['ok']}]) + + idrac_settings = self.drac_client.list_idrac_settings(by_name=True) + + self.assertEqual(630, len(idrac_settings)) + + # enumerable attribute + self.assertIn('Info.1#Type', idrac_settings) + self.assertEqual(expected_enum_attr, idrac_settings[ + 'Info.1#Type']) + # string attribute + self.assertIn('Info.1#Version', idrac_settings) + self.assertEqual(expected_string_attr, + idrac_settings['Info.1#Version']) + # integer attribute + self.assertIn('SSH.1#Port', idrac_settings) + self.assertEqual(expected_integer_attr, idrac_settings[ + 'SSH.1#Port']) + + def test_list_multi_idrac_settings_by_name( + self, mock_requests, mock_wait_until_idrac_is_ready): + expected_enum_attr = idrac_card.iDRACCardEnumerableAttribute( + name='Type', + instance_id='iDRAC.Embedded.2#Info.1#Type', + read_only=True, + current_value='13G Monolithic', + pending_value=None, + fqdd='iDRAC.Embedded.2', + group_id='Info.1', + possible_values=['12G/13G', '12G Monolithic', '12G Modular', + '13G Monolithic', '13G Modular', '12G DCS', + '13G DCS']) + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.iDracCardEnumerations[ + uris.DCIM_iDRACCardEnumeration]['ok']}, + {'text': test_utils.iDracCardEnumerations[ + uris.DCIM_iDRACCardString]['ok']}, + {'text': test_utils.iDracCardEnumerations[ + uris.DCIM_iDRACCardInteger]['ok']}]) + + idrac_settings = self.drac_client.list_idrac_settings( + by_name=True, fqdd_filter='iDRAC.Embedded.2') + + self.assertEqual(1, len(idrac_settings)) + + # enumerable attribute + self.assertIn('Info.1#Type', idrac_settings) + self.assertEqual(expected_enum_attr, idrac_settings[ + 'Info.1#Type']) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', + spec_set=True, autospec=True) + def test_set_idrac_settings( + self, mock_requests, mock_invoke, mock_wait_until_idrac_is_ready): + expected_selectors = {'CreationClassName': 'DCIM_iDRACCardService', + 'SystemName': 'DCIM:ComputerSystem', + 'Name': 'DCIM:iDRACCardService', + 'SystemCreationClassName': 'DCIM_ComputerSystem'} + expected_properties = {'Target': 'iDRAC.Embedded.1', + 'AttributeName': ['LDAP.1#GroupAttributeIsDN'], + 'AttributeValue': ['Disabled']} + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.iDracCardEnumerations[ + uris.DCIM_iDRACCardEnumeration]['ok']}, + {'text': test_utils.iDracCardEnumerations[ + uris.DCIM_iDRACCardString]['ok']}, + {'text': test_utils.iDracCardEnumerations[ + uris.DCIM_iDRACCardInteger]['ok']}]) + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.iDracCardInvocations[uris.DCIM_iDRACCardService][ + 'SetAttributes']['ok']) + + result = self.drac_client.set_idrac_settings( + {'LDAP.1#GroupAttributeIsDN': 'Disabled'}) + + self.assertEqual({'is_commit_required': True, + 'is_reboot_required': + constants.RebootRequired.false}, + result) + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_iDRACCardService, 'SetAttributes', + expected_selectors, expected_properties, + wait_for_idrac=True) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', + spec_set=True, autospec=True) + def test_set_idrac_settings_with_valid_length_string( + self, mock_requests, mock_invoke, mock_wait_until_idrac_is_ready): + expected_selectors = {'CreationClassName': 'DCIM_iDRACCardService', + 'SystemName': 'DCIM:ComputerSystem', + 'Name': 'DCIM:iDRACCardService', + 'SystemCreationClassName': 'DCIM_ComputerSystem'} + expected_properties = {'Target': 'iDRAC.Embedded.1', + 'AttributeName': ['Users.16#Password'], + 'AttributeValue': ['12345678901234567890']} + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.iDracCardEnumerations[ + uris.DCIM_iDRACCardEnumeration]['ok']}, + {'text': test_utils.iDracCardEnumerations[ + uris.DCIM_iDRACCardString]['ok']}, + {'text': test_utils.iDracCardEnumerations[ + uris.DCIM_iDRACCardInteger]['ok']}]) + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.iDracCardInvocations[uris.DCIM_iDRACCardService][ + 'SetAttributes']['ok']) + result = self.drac_client.set_idrac_settings( + {'Users.16#Password': '12345678901234567890'}) + self.assertEqual({'is_commit_required': True, + 'is_reboot_required': + constants.RebootRequired.false}, + result) + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_iDRACCardService, 'SetAttributes', + expected_selectors, expected_properties, + wait_for_idrac=True) + + def test_set_idrac_settings_with_too_long_string( + self, mock_requests, mock_wait_until_idrac_is_ready): + expected_message = ("Attribute 'Password' cannot be set to " + "value '123456789012345678901'. It must be " + "between 0 and 20 characters in length.") + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.iDracCardEnumerations[ + uris.DCIM_iDRACCardEnumeration]['ok']}, + {'text': test_utils.iDracCardEnumerations[ + uris.DCIM_iDRACCardString]['ok']}, + {'text': test_utils.iDracCardEnumerations[ + uris.DCIM_iDRACCardInteger]['ok']}]) + self.assertRaisesRegexp( + exceptions.DRACOperationFailed, re.escape(expected_message), + self.drac_client.set_idrac_settings, + {'Users.16#Password': '123456789012345678901'}) + + +class ClientiDRACCardChangesTestCase(base.BaseTest): + + def setUp(self): + super(ClientiDRACCardChangesTestCase, self).setUp() + self.drac_client = dracclient.client.DRACClient( + **test_utils.FAKE_ENDPOINT) + + @mock.patch.object(job.JobManagement, 'create_config_job', spec_set=True, + autospec=True) + def test_commit_pending_idrac_changes(self, mock_create_config_job): + self.drac_client.commit_pending_idrac_changes() + + mock_create_config_job.assert_called_once_with( + mock.ANY, + resource_uri=uris.DCIM_iDRACCardService, + cim_creation_class_name='DCIM_iDRACCardService', + cim_name='DCIM:iDRACCardService', + target=dracclient.client.DRACClient.IDRAC_FQDD, + reboot=False, start_time='TIME_NOW') + + @mock.patch.object(job.JobManagement, 'create_config_job', spec_set=True, + autospec=True) + def test_commit_pending_idrac_changes_with_reboot( + self, mock_create_config_job): + + self.drac_client.commit_pending_idrac_changes( + reboot=True) + + mock_create_config_job.assert_called_once_with( + mock.ANY, + resource_uri=uris.DCIM_iDRACCardService, + cim_creation_class_name='DCIM_iDRACCardService', + cim_name='DCIM:iDRACCardService', + target=dracclient.client.DRACClient.IDRAC_FQDD, + reboot=True, start_time='TIME_NOW') + + @mock.patch.object(job.JobManagement, 'create_config_job', spec_set=True, + autospec=True) + def test_commit_pending_idrac_changes_with_time( + self, mock_create_config_job): + timestamp = '20140924120101' + self.drac_client.commit_pending_idrac_changes( + start_time=timestamp) + + mock_create_config_job.assert_called_once_with( + mock.ANY, + resource_uri=uris.DCIM_iDRACCardService, + cim_creation_class_name='DCIM_iDRACCardService', + cim_name='DCIM:iDRACCardService', + target=dracclient.client.DRACClient.IDRAC_FQDD, + reboot=False, start_time=timestamp) + + @mock.patch.object(job.JobManagement, 'create_config_job', spec_set=True, + autospec=True) + def test_commit_pending_idrac_changes_with_reboot_and_time( + self, mock_create_config_job): + + timestamp = '20140924120101' + self.drac_client.commit_pending_idrac_changes( + reboot=True, + start_time=timestamp) + + mock_create_config_job.assert_called_once_with( + mock.ANY, + resource_uri=uris.DCIM_iDRACCardService, + cim_creation_class_name='DCIM_iDRACCardService', + cim_name='DCIM:iDRACCardService', + target=dracclient.client.DRACClient.IDRAC_FQDD, + reboot=True, start_time=timestamp) + + @mock.patch.object(job.JobManagement, 'delete_pending_config', + spec_set=True, autospec=True) + def test_abandon_pending_idrac_changes(self, mock_delete_pending_config): + self.drac_client.abandon_pending_idrac_changes() + + mock_delete_pending_config.assert_called_once_with( + mock.ANY, + resource_uri=uris.DCIM_iDRACCardService, + cim_creation_class_name='DCIM_iDRACCardService', + cim_name='DCIM:iDRACCardService', + target=dracclient.client.DRACClient.IDRAC_FQDD) + + +class ClientiDRACCardResetTestCase(base.BaseTest): + + def setUp(self): + super(ClientiDRACCardResetTestCase, self).setUp() + self.drac_client = dracclient.client.DRACClient( + **test_utils.FAKE_ENDPOINT) + + @mock.patch('dracclient.client.subprocess.call') + def test_ping_host(self, mock_os_system): + mock_os_system.return_value = 0 + response = self.drac_client._ping_host('127.0.0.1') + self.assertEqual(mock_os_system.call_count, 1) + self.assertEqual(True, response) + + @mock.patch('dracclient.client.subprocess.call') + def test_ping_host_not_pingable(self, mock_os_system): + mock_os_system.return_value = 1 + response = self.drac_client._ping_host('127.0.0.1') + self.assertEqual(mock_os_system.call_count, 1) + self.assertEqual(False, response) + + @mock.patch('dracclient.client.subprocess.call') + def test_ping_host_name_not_known(self, mock_os_system): + mock_os_system.return_value = 2 + response = self.drac_client._ping_host('127.0.0.1') + self.assertEqual(mock_os_system.call_count, 1) + self.assertEqual(False, response) + + @mock.patch('time.sleep') + @mock.patch('dracclient.client.DRACClient._ping_host') + def test_wait_for_host_alive(self, mock_ping_host, mock_sleep): + total_calls = 5 + ping_count = 3 + mock_ping_host.return_value = True + mock_sleep.return_value = None + response = self.drac_client._wait_for_host_state( + 'hostname', + alive=True, + ping_count=ping_count, + retries=total_calls) + self.assertEqual(True, response) + self.assertEqual(mock_sleep.call_count, ping_count) + self.assertEqual(mock_ping_host.call_count, ping_count) + + @mock.patch('time.sleep') + @mock.patch('dracclient.client.DRACClient._ping_host') + def test_wait_for_host_alive_fail(self, mock_ping_host, mock_sleep): + total_calls = 5 + ping_count = 3 + mock_ping_host.return_value = False + mock_sleep.return_value = None + response = self.drac_client._wait_for_host_state( + 'hostname', + alive=True, + ping_count=ping_count, + retries=total_calls) + self.assertEqual(False, response) + self.assertEqual(mock_sleep.call_count, total_calls) + self.assertEqual(mock_ping_host.call_count, total_calls) + + @mock.patch('time.sleep') + @mock.patch('dracclient.client.DRACClient._ping_host') + def test_wait_for_host_dead(self, mock_ping_host, mock_sleep): + total_calls = 5 + ping_count = 3 + mock_ping_host.return_value = False + mock_sleep.return_value = None + response = self.drac_client._wait_for_host_state( + 'hostname', + alive=False, + ping_count=ping_count, + retries=total_calls) + self.assertEqual(True, response) + self.assertEqual(mock_sleep.call_count, ping_count) + self.assertEqual(mock_ping_host.call_count, ping_count) + + @mock.patch('time.sleep') + @mock.patch('dracclient.client.DRACClient._ping_host') + def test_wait_for_host_dead_fail(self, mock_ping_host, mock_sleep): + total_calls = 5 + ping_count = 3 + mock_ping_host.return_value = True + mock_sleep.return_value = None + response = self.drac_client._wait_for_host_state( + 'hostname', + alive=False, + ping_count=ping_count, + retries=total_calls) + self.assertEqual(False, response) + self.assertEqual(mock_sleep.call_count, total_calls) + self.assertEqual(mock_ping_host.call_count, total_calls) + + @mock.patch('time.sleep') + @mock.patch('dracclient.client.DRACClient._ping_host') + def test_wait_for_host_alive_with_intermittent( + self, mock_ping_host, mock_sleep): + total_calls = 6 + ping_count = 3 + mock_ping_host.side_effect = [True, True, False, True, True, True] + mock_sleep.return_value = None + response = self.drac_client._wait_for_host_state( + 'hostname', + alive=True, + ping_count=ping_count, + retries=total_calls) + self.assertEqual(True, response) + self.assertEqual(mock_sleep.call_count, total_calls) + + @mock.patch('time.sleep') + @mock.patch('dracclient.client.DRACClient._ping_host') + def test_wait_for_host_dead_with_intermittent( + self, mock_ping_host, mock_sleep): + total_calls = 6 + ping_count = 3 + mock_ping_host.side_effect = [False, False, True, False, False, False] + mock_sleep.return_value = None + response = self.drac_client._wait_for_host_state( + 'hostname', + alive=False, + ping_count=ping_count, + retries=total_calls) + self.assertEqual(True, response) + self.assertEqual(mock_sleep.call_count, total_calls) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True, + autospec=True) + def test_reset_idrac(self, mock_invoke): + expected_selectors = { + 'CreationClassName': "DCIM_iDRACCardService", + 'Name': "DCIM:iDRACCardService", + 'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'DCIM:ComputerSystem'} + expected_properties = {'Force': '0'} + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.iDracCardInvocations[uris.DCIM_iDRACCardService][ + 'iDRACReset']['ok']) + + result = self.drac_client.reset_idrac() + + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_iDRACCardService, 'iDRACReset', + expected_selectors, expected_properties, + check_return_value=False) + self.assertTrue(result) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True, + autospec=True) + def test_reset_idrac_force(self, mock_invoke): + expected_selectors = { + 'CreationClassName': "DCIM_iDRACCardService", + 'Name': "DCIM:iDRACCardService", + 'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'DCIM:ComputerSystem'} + expected_properties = {'Force': '1'} + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.iDracCardInvocations[uris.DCIM_iDRACCardService][ + 'iDRACReset']['ok']) + + result = self.drac_client.reset_idrac(force=True) + + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_iDRACCardService, 'iDRACReset', + expected_selectors, expected_properties, + check_return_value=False) + self.assertTrue(result) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True, + autospec=True) + def test_reset_idrac_bad_result(self, mock_invoke): + expected_selectors = { + 'CreationClassName': "DCIM_iDRACCardService", + 'Name': "DCIM:iDRACCardService", + 'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'DCIM:ComputerSystem'} + expected_properties = {'Force': '0'} + expected_message = ("Failed to reset iDRAC") + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.iDracCardInvocations[uris.DCIM_iDRACCardService][ + 'iDRACReset']['error']) + + self.assertRaisesRegexp( + exceptions.DRACOperationFailed, re.escape(expected_message), + self.drac_client.reset_idrac) + + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_iDRACCardService, 'iDRACReset', + expected_selectors, expected_properties, + check_return_value=False) + + @mock.patch('time.sleep') + @mock.patch('dracclient.client.WSManClient.wait_until_idrac_is_ready') + @mock.patch('dracclient.client.DRACClient._wait_for_host_state') + @mock.patch( + 'dracclient.client.idrac_card.iDRACCardConfiguration.reset_idrac') + def test_reset_idrac_wait( + self, + mock_reset_idrac, + mock_wait_for_host_state, + mock_wait_until_idrac_is_ready, + mock_sleep): + mock_reset_idrac.return_value = True + mock_wait_for_host_state.side_effect = [True, True] + mock_wait_until_idrac_is_ready.return_value = True + mock_sleep.return_value = None + + self.drac_client.reset_idrac(wait=True) + + mock_reset_idrac.assert_called_once() + self.assertEqual(mock_wait_for_host_state.call_count, 2) + mock_wait_until_idrac_is_ready.assert_called_once() + + @mock.patch('time.sleep') + @mock.patch('dracclient.client.WSManClient.wait_until_idrac_is_ready') + @mock.patch('dracclient.client.DRACClient._wait_for_host_state') + @mock.patch( + 'dracclient.client.idrac_card.iDRACCardConfiguration.reset_idrac') + def test_reset_idrac_wait_failed_reset( + self, + mock_reset_idrac, + mock_wait_for_host_state, + mock_wait_until_idrac_is_ready, + mock_sleep): + mock_reset_idrac.return_value = False + mock_wait_for_host_state.side_effect = [True, True] + mock_wait_until_idrac_is_ready.return_value = False + mock_sleep.return_value = None + expected_message = ("Failed to reset iDRAC") + + self.assertRaisesRegexp( + exceptions.DRACOperationFailed, re.escape(expected_message), + self.drac_client.reset_idrac, wait=True) + + mock_reset_idrac.assert_called_once() + mock_wait_for_host_state.assert_not_called() + mock_wait_until_idrac_is_ready.assert_not_called() + + @mock.patch('time.sleep') + @mock.patch('dracclient.client.WSManClient.wait_until_idrac_is_ready') + @mock.patch('dracclient.client.DRACClient._wait_for_host_state') + @mock.patch( + 'dracclient.client.idrac_card.iDRACCardConfiguration.reset_idrac') + def test_reset_idrac_fail_wait_not_pingable( + self, + mock_reset_idrac, + mock_wait_for_host_state, + mock_wait_until_idrac_is_ready, + mock_sleep): + mock_reset_idrac.return_value = True + mock_wait_for_host_state.side_effect = [False, True] + mock_wait_until_idrac_is_ready.return_value = True + mock_sleep.return_value = None + expected_message = ( + "Timed out waiting for the 1.2.3.4 iDRAC to become not pingable") + + self.assertRaisesRegexp( + exceptions.DRACOperationFailed, re.escape(expected_message), + self.drac_client.reset_idrac, wait=True) + + mock_reset_idrac.assert_called_once() + mock_wait_for_host_state.assert_called_once() + mock_wait_until_idrac_is_ready.assert_not_called() + + @mock.patch('time.sleep') + @mock.patch('dracclient.client.WSManClient.wait_until_idrac_is_ready') + @mock.patch('dracclient.client.DRACClient._wait_for_host_state') + @mock.patch( + 'dracclient.client.idrac_card.iDRACCardConfiguration.reset_idrac') + def test_reset_idrac_fail_wait_pingable( + self, + mock_reset_idrac, + mock_wait_for_host_state, + mock_wait_until_idrac_is_ready, + mock_sleep): + mock_reset_idrac.return_value = True + mock_wait_for_host_state.side_effect = [True, False] + mock_wait_until_idrac_is_ready.return_value = True + mock_sleep.return_value = None + expected_message = ( + "Timed out waiting for the 1.2.3.4 iDRAC to become pingable") + + self.assertRaisesRegexp( + exceptions.DRACOperationFailed, re.escape(expected_message), + self.drac_client.reset_idrac, wait=True) + + mock_reset_idrac.assert_called_once() + self.assertEqual(mock_wait_for_host_state.call_count, 2) + mock_wait_until_idrac_is_ready.assert_not_called() diff --git a/dracclient/tests/test_inventory.py b/dracclient/tests/test_inventory.py index a167da6..378a114 100644 --- a/dracclient/tests/test_inventory.py +++ b/dracclient/tests/test_inventory.py @@ -11,6 +11,8 @@ # License for the specific language governing permissions and limitations # under the License. +from unittest import mock + import requests_mock import dracclient.client @@ -22,6 +24,8 @@ @requests_mock.Mocker() +@mock.patch.object(dracclient.client.WSManClient, 'wait_until_idrac_is_ready', + spec_set=True, autospec=True) class ClientInventoryManagementTestCase(base.BaseTest): def setUp(self): @@ -29,7 +33,7 @@ def setUp(self): self.drac_client = dracclient.client.DRACClient( **test_utils.FAKE_ENDPOINT) - def test_list_cpus(self, mock_requests): + def test_list_cpus(self, mock_requests, mock_wait_until_idrac_is_ready): expected_cpu = [inventory.CPU( id='CPU.Socket.1', cores=6, @@ -37,6 +41,7 @@ def test_list_cpus(self, mock_requests): model='Intel(R) Xeon(R) CPU E5-2620 v3 @ 2.40GHz', status='ok', ht_enabled=True, + cpu_count=12, turbo_enabled=True, vt_enabled=True, arch64=True)] @@ -49,7 +54,8 @@ def test_list_cpus(self, mock_requests): expected_cpu, self.drac_client.list_cpus()) - def test_list_cpus_with_missing_flags(self, mock_requests): + def test_list_cpus_with_missing_flags(self, mock_requests, + mock_wait_until_idrac_is_ready): expected_cpu = [inventory.CPU( id='CPU.Socket.1', cores=8, @@ -57,6 +63,7 @@ def test_list_cpus_with_missing_flags(self, mock_requests): model='Intel(R) Xeon(R) CPU E5-2440 v2 @ 1.90GHz', status='ok', ht_enabled=False, + cpu_count=8, turbo_enabled=False, vt_enabled=False, arch64=False)] @@ -70,7 +77,7 @@ def test_list_cpus_with_missing_flags(self, mock_requests): expected_cpu, self.drac_client.list_cpus()) - def test_list_memory(self, mock_requests): + def test_list_memory(self, mock_requests, mock_wait_until_idrac_is_ready): expected_memory = [inventory.Memory( id='DIMM.Socket.A1', size_mb=16384, @@ -87,7 +94,7 @@ def test_list_memory(self, mock_requests): expected_memory, self.drac_client.list_memory()) - def test_list_nics(self, mock_requests): + def test_list_nics(self, mock_requests, mock_wait_until_idrac_is_ready): expected_nics = [ inventory.NIC( id='NIC.Embedded.1-1-1', @@ -125,3 +132,18 @@ def test_list_nics(self, mock_requests): self.assertEqual( expected_nics, self.drac_client.list_nics()) + + def test_get_system(self, mock_requests, mock_wait_until_idrac_is_ready): + expected_system = inventory.System( + id='System.Embedded.1', + uuid='ebd4edd3-dfd7-4c7d-a2c8-562b3c23b811', + service_tag='A1B2C3D', + model='PowerEdge R630', + lcc_version='2.1.0') + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.LifecycleControllerEnumerations[ + uris.DCIM_SystemView]['ok']) + self.assertEqual( + expected_system, + self.drac_client.get_system()) diff --git a/dracclient/tests/test_job.py b/dracclient/tests/test_job.py index 751b0b9..38add78 100644 --- a/dracclient/tests/test_job.py +++ b/dracclient/tests/test_job.py @@ -11,8 +11,10 @@ # License for the specific language governing permissions and limitations # under the License. +import datetime import lxml.etree -import mock +from unittest import mock + import requests_mock import dracclient.client @@ -32,7 +34,10 @@ def setUp(self): **test_utils.FAKE_ENDPOINT) @requests_mock.Mocker() - def test_list_jobs(self, mock_requests): + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_list_jobs(self, mock_requests, mock_wait_until_idrac_is_ready): mock_requests.post( 'https://1.2.3.4:443/wsman', text=test_utils.JobEnumerations[uris.DCIM_LifecycleJob]['ok']) @@ -47,6 +52,7 @@ def test_list_jobs_only_unfinished(self, mock_enumerate): expected_filter_query = ('select * from DCIM_LifecycleJob ' 'where Name != "CLEARALL" and ' 'JobStatus != "Reboot Completed" and ' + 'JobStatus != "Reboot Failed" and ' 'JobStatus != "Completed" and ' 'JobStatus != "Completed with Errors" and ' 'JobStatus != "Failed"') @@ -98,18 +104,173 @@ def test_get_job_not_found(self, mock_enumerate): filter_query=expected_filter_query) self.assertIsNone(job) + @mock.patch.object(dracclient.client.WSManClient, 'invoke', + spec_set=True, autospec=True) + def test_delete_jobs_all(self, mock_invoke): + expected_selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'idrac', + 'CreationClassName': 'DCIM_JobService', + 'Name': 'JobService'} + expected_properties = {'JobID': 'JID_CLEARALL'} + + self.drac_client.delete_jobs() + + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_JobService, 'DeleteJobQueue', + expected_selectors, expected_properties, + expected_return_value=utils.RET_SUCCESS) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', + spec_set=True, autospec=True) + def test_delete_jobs_force(self, mock_invoke): + expected_selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'idrac', + 'CreationClassName': 'DCIM_JobService', + 'Name': 'JobService'} + expected_properties = {'JobID': 'JID_CLEARALL_FORCE'} + + self.drac_client.delete_jobs(['JID_CLEARALL_FORCE']) + + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_JobService, 'DeleteJobQueue', + expected_selectors, expected_properties, + expected_return_value=utils.RET_SUCCESS) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', + spec_set=True, autospec=True) + def test_delete_jobs_one(self, mock_invoke): + expected_selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'idrac', + 'CreationClassName': 'DCIM_JobService', + 'Name': 'JobService'} + expected_properties = {'JobID': 'JID_442507917525'} + + self.drac_client.delete_jobs(['JID_442507917525']) + + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_JobService, 'DeleteJobQueue', + expected_selectors, expected_properties, + expected_return_value=utils.RET_SUCCESS) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', + spec_set=True, autospec=True) + def test_delete_jobs_multi(self, mock_invoke): + expected_selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'idrac', + 'CreationClassName': 'DCIM_JobService', + 'Name': 'JobService'} + + self.drac_client.delete_jobs(['JID_442507917525', + 'JID_442507917526']) + + calls_expected = [ + mock.call(mock.ANY, + uris.DCIM_JobService, + 'DeleteJobQueue', + expected_selectors, + {'JobID': 'JID_442507917525'}, + expected_return_value=utils.RET_SUCCESS), + mock.call(mock.ANY, + uris.DCIM_JobService, + 'DeleteJobQueue', + expected_selectors, + {'JobID': 'JID_442507917526'}, + expected_return_value=utils.RET_SUCCESS)] + mock_invoke.assert_has_calls(calls_expected) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', + spec_set=True, autospec=True) + def test_delete_jobs_none(self, mock_invoke): + self.drac_client.delete_jobs(None) + self.assertFalse(mock_invoke.called) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', + spec_set=True, autospec=True) + def test_delete_jobs_empty_list(self, mock_invoke): + self.drac_client.delete_jobs([]) + self.assertFalse(mock_invoke.called) + + @requests_mock.Mocker() + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_delete_job_not_found( + self, mock_requests, + mock_wait_until_idrac_is_ready): + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.JobService[uris.DCIM_JobService][ + 'DeleteJobQueue']['error']) + self.assertRaises( + exceptions.DRACOperationFailed, + self.drac_client.delete_jobs, + ['JID_1234']) + + @requests_mock.Mocker() + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_delete_some_jobs_not_found( + self, mock_requests, + mock_wait_until_idrac_is_ready): + mock_requests.post( + 'https://1.2.3.4:443/wsman', + [{'text': test_utils.JobService[uris.DCIM_JobService][ + 'DeleteJobQueue']['error']}, + {'text': test_utils.JobService[uris.DCIM_JobService][ + 'DeleteJobQueue']['ok']}]) + + self.assertRaises( + exceptions.DRACOperationFailed, + self.drac_client.delete_jobs, + ['JID_1234', 'JID_442507917525']) + + self.assertEqual(mock_requests.call_count, 2) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', + spec_set=True, autospec=True) + def test_create_config_job_for_lifecycle(self, mock_invoke): + cim_creation_class_name = 'DCIM_LCService' + cim_name = 'DCIM:LCService' + target = '' + + expected_selectors = {'CreationClassName': cim_creation_class_name, + 'Name': cim_name, + 'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'DCIM:ComputerSystem'} + expected_properties = {'Target': target, + 'ScheduledStartTime': 'TIME_NOW'} + + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.JobInvocations[uris.DCIM_LCService][ + 'CreateConfigJob']['ok']) + + job_id = self.drac_client.create_config_job( + uris.DCIM_LCService, cim_creation_class_name, cim_name, target, + start_time='TIME_NOW', + wait_for_idrac=False, method_name='CreateConfigJob') + + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_LCService, 'CreateConfigJob', + expected_selectors, expected_properties, + expected_return_value=utils.RET_CREATED, + wait_for_idrac=False) + self.assertEqual('JID_442507917525', job_id) + @mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True, autospec=True) def test_create_config_job(self, mock_invoke): cim_creation_class_name = 'DCIM_BIOSService' cim_name = 'DCIM:BIOSService' target = 'BIOS.Setup.1-1' + wait_for_idrac = True expected_selectors = {'CreationClassName': cim_creation_class_name, 'Name': cim_name, 'SystemCreationClassName': 'DCIM_ComputerSystem', 'SystemName': 'DCIM:ComputerSystem'} expected_properties = {'Target': target, 'ScheduledStartTime': 'TIME_NOW'} + mock_invoke.return_value = lxml.etree.fromstring( test_utils.JobInvocations[uris.DCIM_BIOSService][ 'CreateTargetedConfigJob']['ok']) @@ -120,11 +281,73 @@ def test_create_config_job(self, mock_invoke): mock_invoke.assert_called_once_with( mock.ANY, uris.DCIM_BIOSService, 'CreateTargetedConfigJob', expected_selectors, expected_properties, - expected_return_value=utils.RET_CREATED) + expected_return_value=utils.RET_CREATED, + wait_for_idrac=wait_for_idrac) + self.assertEqual('JID_442507917525', job_id) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', + spec_set=True, autospec=True) + def test_create_config_job_with_start_time(self, mock_invoke): + cim_creation_class_name = 'DCIM_BIOSService' + cim_name = 'DCIM:BIOSService' + target = 'BIOS.Setup.1-1' + start_time = "20140924120105" + wait_for_idrac = True + expected_selectors = {'CreationClassName': cim_creation_class_name, + 'Name': cim_name, + 'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'DCIM:ComputerSystem'} + expected_properties = {'Target': target, + 'ScheduledStartTime': start_time} + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.JobInvocations[uris.DCIM_BIOSService][ + 'CreateTargetedConfigJob']['ok']) + + job_id = self.drac_client.create_config_job( + uris.DCIM_BIOSService, cim_creation_class_name, cim_name, target, + start_time=start_time) + + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_BIOSService, 'CreateTargetedConfigJob', + expected_selectors, expected_properties, + expected_return_value=utils.RET_CREATED, + wait_for_idrac=wait_for_idrac) + self.assertEqual('JID_442507917525', job_id) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', + spec_set=True, autospec=True) + def test_create_config_job_with_no_start_time(self, mock_invoke): + cim_creation_class_name = 'DCIM_BIOSService' + cim_name = 'DCIM:BIOSService' + target = 'BIOS.Setup.1-1' + start_time = None + wait_for_idrac = True + expected_selectors = {'CreationClassName': cim_creation_class_name, + 'Name': cim_name, + 'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'DCIM:ComputerSystem'} + expected_properties = {'Target': target} + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.JobInvocations[uris.DCIM_BIOSService][ + 'CreateTargetedConfigJob']['ok']) + + job_id = self.drac_client.create_config_job( + uris.DCIM_BIOSService, cim_creation_class_name, cim_name, target, + start_time=start_time) + + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_BIOSService, 'CreateTargetedConfigJob', + expected_selectors, expected_properties, + expected_return_value=utils.RET_CREATED, + wait_for_idrac=wait_for_idrac) self.assertEqual('JID_442507917525', job_id) @requests_mock.Mocker() - def test_create_config_job_failed(self, mock_requests): + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_create_config_job_failed(self, mock_requests, + mock_wait_until_idrac_is_ready): cim_creation_class_name = 'DCIM_BIOSService' cim_name = 'DCIM:BIOSService' target = 'BIOS.Setup.1-1' @@ -137,12 +360,32 @@ def test_create_config_job_failed(self, mock_requests): exceptions.DRACOperationFailed, self.drac_client.create_config_job, uris.DCIM_BIOSService, cim_creation_class_name, cim_name, target) + @requests_mock.Mocker() + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_create_config_job_for_lifecycle_failed( + self, mock_requests, + mock_wait_until_idrac_is_ready): + cim_creation_class_name = 'DCIM_LCService' + cim_name = 'DCIM:LCService' + target = '' + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.JobInvocations[uris.DCIM_LCService][ + 'CreateConfigJob']['error']) + + self.assertRaises( + exceptions.DRACOperationFailed, self.drac_client.create_config_job, + uris.DCIM_LCService, cim_creation_class_name, cim_name, target) + @mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True, autospec=True) def test_create_config_job_with_reboot(self, mock_invoke): cim_creation_class_name = 'DCIM_BIOSService' cim_name = 'DCIM:BIOSService' target = 'BIOS.Setup.1-1' + wait_for_idrac = True expected_selectors = {'CreationClassName': cim_creation_class_name, 'Name': cim_name, 'SystemCreationClassName': 'DCIM_ComputerSystem', @@ -156,14 +399,65 @@ def test_create_config_job_with_reboot(self, mock_invoke): job_id = self.drac_client.create_config_job( uris.DCIM_BIOSService, cim_creation_class_name, cim_name, target, - reboot=True) + reboot=True, realtime=False) mock_invoke.assert_called_once_with( mock.ANY, uris.DCIM_BIOSService, 'CreateTargetedConfigJob', expected_selectors, expected_properties, - expected_return_value=utils.RET_CREATED) + expected_return_value=utils.RET_CREATED, + wait_for_idrac=wait_for_idrac) + self.assertEqual('JID_442507917525', job_id) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True, + autospec=True) + def test_create_config_job_with_realtime(self, mock_invoke): + cim_creation_class_name = 'DCIM_BIOSService' + cim_name = 'DCIM:BIOSService' + target = 'BIOS.Setup.1-1' + wait_for_idrac = True + expected_selectors = {'CreationClassName': cim_creation_class_name, + 'Name': cim_name, + 'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'DCIM:ComputerSystem'} + expected_properties = {'Target': target, + 'ScheduledStartTime': 'TIME_NOW', + 'RealTime': '1'} + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.JobInvocations[uris.DCIM_BIOSService][ + 'CreateTargetedConfigJob']['ok']) + + job_id = self.drac_client.create_config_job( + uris.DCIM_BIOSService, cim_creation_class_name, cim_name, target, + reboot=False, realtime=True) + + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_BIOSService, 'CreateTargetedConfigJob', + expected_selectors, expected_properties, + expected_return_value=utils.RET_CREATED, + wait_for_idrac=wait_for_idrac) self.assertEqual('JID_442507917525', job_id) + @mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True, + autospec=True) + def test_create_reboot_job(self, mock_invoke): + expected_selectors = { + 'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'idrac', + 'CreationClassName': 'DCIM_JobService', + 'Name': 'JobService'} + expected_properties = {'RebootJobType': '3'} + self.drac_client.create_reboot_job() + + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_JobService, 'CreateRebootJob', + expected_selectors, expected_properties, + expected_return_value=utils.RET_CREATED) + + def test_create_reboot_job_bad_type(self): + self.assertRaises( + exceptions.InvalidParameterValue, + self.drac_client.create_reboot_job, 'BAD REBOOT TYPE') + @mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True, autospec=True) def test_delete_pending_config(self, mock_invoke): @@ -188,7 +482,11 @@ def test_delete_pending_config(self, mock_invoke): expected_return_value=utils.RET_SUCCESS) @requests_mock.Mocker() - def test_delete_pending_config_failed(self, mock_requests): + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_delete_pending_config_failed(self, mock_requests, + mock_wait_until_idrac_is_ready): cim_creation_class_name = 'DCIM_BIOSService' cim_name = 'DCIM:BIOSService' target = 'BIOS.Setup.1-1' @@ -201,3 +499,75 @@ def test_delete_pending_config_failed(self, mock_requests): exceptions.DRACOperationFailed, self.drac_client.delete_pending_config, uris.DCIM_BIOSService, cim_creation_class_name, cim_name, target) + + +class ClientJobScheduleTestCase(base.BaseTest): + def setUp(self): + super(ClientJobScheduleTestCase, self).setUp() + self.drac_client = dracclient.client.DRACClient( + **test_utils.FAKE_ENDPOINT) + + def _test_schedule_job_execution(self, + mock_invoke, + job_ids, + start_time, + expected_properties): + expected_selectors = { + 'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'idrac', + 'CreationClassName': 'DCIM_JobService', + 'Name': 'JobService'} + + if start_time is None: + self.drac_client.schedule_job_execution(job_ids) + else: + self.drac_client.schedule_job_execution(job_ids, start_time) + + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_JobService, 'SetupJobQueue', + expected_selectors, expected_properties, + expected_return_value=utils.RET_SUCCESS) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True, + autospec=True) + def test_schedule_job_execution_one_job(self, mock_invoke): + job_ids = ['JID_442507917525'] + expected_properties = {'StartTimeInterval': 'TIME_NOW', + 'JobArray': job_ids} + + self._test_schedule_job_execution(mock_invoke, job_ids, None, + expected_properties) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True, + autospec=True) + def test_schedule_job_execution_multi_job(self, mock_invoke): + job_ids = ['JID_442507917525', 'JID_442507917526'] + expected_properties = {'StartTimeInterval': 'TIME_NOW', + 'JobArray': job_ids} + self._test_schedule_job_execution(mock_invoke, job_ids, None, + expected_properties) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True, + autospec=True) + def test_schedule_job_execution_one_job_with_time(self, mock_invoke): + job_ids = ['JID_442507917525'] + timestamp = datetime.datetime.today().strftime('%Y%m%d%H%M%S') + expected_properties = {'StartTimeInterval': timestamp, + 'JobArray': job_ids} + self._test_schedule_job_execution(mock_invoke, job_ids, timestamp, + expected_properties) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True, + autospec=True) + def test_schedule_job_execution_multi_job_with_time(self, mock_invoke): + job_ids = ['JID_442507917525', 'JID_442507917526'] + timestamp = datetime.datetime.today().strftime('%Y%m%d%H%M%S') + expected_properties = {'StartTimeInterval': timestamp, + 'JobArray': job_ids} + self._test_schedule_job_execution(mock_invoke, job_ids, timestamp, + expected_properties) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke') + def test_schedule_job_execution_no_jobs(self, mock_invoke): + self.drac_client.schedule_job_execution(job_ids=[]) + mock_invoke.assert_not_called() diff --git a/dracclient/tests/test_lifecycle_controller.py b/dracclient/tests/test_lifecycle_controller.py index e53802a..136c201 100644 --- a/dracclient/tests/test_lifecycle_controller.py +++ b/dracclient/tests/test_lifecycle_controller.py @@ -11,12 +11,21 @@ # License for the specific language governing permissions and limitations # under the License. +import lxml.etree +import re +from unittest import mock + import requests_mock import dracclient.client +from dracclient import constants +from dracclient import exceptions +import dracclient.resources.job +from dracclient.resources import lifecycle_controller from dracclient.resources import uris from dracclient.tests import base from dracclient.tests import utils as test_utils +from dracclient import utils class ClientLifecycleControllerManagementTestCase(base.BaseTest): @@ -36,3 +45,256 @@ def test_get_lifecycle_controller_version(self, mock_requests): version = self.drac_client.get_lifecycle_controller_version() self.assertEqual((2, 1, 0), version) + + +@requests_mock.Mocker() +class ClientLCConfigurationTestCase(base.BaseTest): + + def setUp(self): + super(ClientLCConfigurationTestCase, self).setUp() + self.drac_client = dracclient.client.DRACClient( + **test_utils.FAKE_ENDPOINT) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_list_lifecycle_settings_by_instance_id( + self, mock_requests, + mock_wait_until_idrac_is_ready): + expected_enum_attr = lifecycle_controller.LCEnumerableAttribute( + name='Lifecycle Controller State', + instance_id='LifecycleController.Embedded.1#LCAttributes.1#LifecycleControllerState', # noqa + read_only=False, + current_value='Enabled', + pending_value=None, + possible_values=['Disabled', 'Enabled', 'Recovery']) + expected_string_attr = lifecycle_controller.LCStringAttribute( + name='SYSID', + instance_id='LifecycleController.Embedded.1#LCAttributes.1#SystemID', # noqa + read_only=True, + current_value='639', + pending_value=None, + min_length=0, + max_length=3) + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.LifecycleControllerEnumerations[ + uris.DCIM_LCEnumeration]['ok']}, + {'text': test_utils.LifecycleControllerEnumerations[ + uris.DCIM_LCString]['ok']}]) + + lifecycle_settings = self.drac_client.list_lifecycle_settings( + by_name=False) + + self.assertEqual(14, len(lifecycle_settings)) + # enumerable attribute + self.assertIn( + 'LifecycleController.Embedded.1#LCAttributes.1#LifecycleControllerState', # noqa + lifecycle_settings) + self.assertEqual(expected_enum_attr, lifecycle_settings[ + 'LifecycleController.Embedded.1#LCAttributes.1#LifecycleControllerState']) # noqa + # string attribute + self.assertIn( + 'LifecycleController.Embedded.1#LCAttributes.1#SystemID', + lifecycle_settings) + self.assertEqual(expected_string_attr, + lifecycle_settings['LifecycleController.Embedded.1#LCAttributes.1#SystemID']) # noqa + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_list_lifecycle_settings_by_name( + self, mock_requests, + mock_wait_until_idrac_is_ready): + expected_enum_attr = lifecycle_controller.LCEnumerableAttribute( + name='Lifecycle Controller State', + instance_id='LifecycleController.Embedded.1#LCAttributes.1#LifecycleControllerState', # noqa + read_only=False, + current_value='Enabled', + pending_value=None, + possible_values=['Disabled', 'Enabled', 'Recovery']) + expected_string_attr = lifecycle_controller.LCStringAttribute( + name='SYSID', + instance_id='LifecycleController.Embedded.1#LCAttributes.1#SystemID', # noqa + read_only=True, + current_value='639', + pending_value=None, + min_length=0, + max_length=3) + + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.LifecycleControllerEnumerations[ + uris.DCIM_LCEnumeration]['ok']}, + {'text': test_utils.LifecycleControllerEnumerations[ + uris.DCIM_LCString]['ok']}]) + + lifecycle_settings = self.drac_client.list_lifecycle_settings( + by_name=True) + + self.assertEqual(14, len(lifecycle_settings)) + # enumerable attribute + self.assertIn( + 'Lifecycle Controller State', + lifecycle_settings) + self.assertEqual(expected_enum_attr, lifecycle_settings[ + 'Lifecycle Controller State']) + # string attribute + self.assertIn( + 'SYSID', + lifecycle_settings) + self.assertEqual(expected_string_attr, + lifecycle_settings['SYSID']) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', + spec_set=True, autospec=True) + def test_is_lifecycle_in_recovery(self, mock_requests, + mock_invoke): + expected_selectors = {'CreationClassName': 'DCIM_LCService', + 'SystemName': 'DCIM:ComputerSystem', + 'Name': 'DCIM:LCService', + 'SystemCreationClassName': 'DCIM_ComputerSystem'} + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.LifecycleControllerInvocations[uris.DCIM_LCService][ + 'GetRemoteServicesAPIStatus']['is_recovery']) + result = self.drac_client.is_lifecycle_in_recovery() + + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_LCService, 'GetRemoteServicesAPIStatus', + expected_selectors, {}, + expected_return_value=utils.RET_SUCCESS, + wait_for_idrac=False) + + self.assertEqual(True, result) + + @mock.patch.object(dracclient.client.WSManClient, + 'invoke', spec_set=True, + autospec=True) + def test_set_lifecycle_settings(self, mock_requests, + mock_invoke): + + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.LifecycleControllerEnumerations[ + uris.DCIM_LCEnumeration]['ok']}, + {'text': test_utils.LifecycleControllerEnumerations[ + uris.DCIM_LCString]['ok']}]) + + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.LifecycleControllerInvocations[uris.DCIM_LCService][ + 'SetAttributes']['ok']) + + result = self.drac_client.set_lifecycle_settings( + {'Collect System Inventory on Restart': 'Disabled'}) + + self.assertEqual({'is_commit_required': True, + 'is_reboot_required': constants.RebootRequired.false + }, + result) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_set_lifecycle_settings_with_unknown_attr( + self, mock_requests, mock_wait_until_idrac_is_ready): + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.LifecycleControllerEnumerations[ + uris.DCIM_LCEnumeration]['ok']}, + {'text': test_utils.LifecycleControllerEnumerations[ + uris.DCIM_LCString]['ok']}, + {'text': test_utils.LifecycleControllerInvocations[ + uris.DCIM_LCService]['SetAttributes']['error']}]) + + self.assertRaises(exceptions.InvalidParameterValue, + self.drac_client.set_lifecycle_settings, + {'foo': 'bar'}) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_set_lifecycle_settings_with_unchanged_attr( + self, mock_requests, mock_wait_until_idrac_is_ready): + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.LifecycleControllerEnumerations[ + uris.DCIM_LCEnumeration]['ok']}, + {'text': test_utils.LifecycleControllerEnumerations[ + uris.DCIM_LCString]['ok']}]) + + result = self.drac_client.set_lifecycle_settings( + {'Lifecycle Controller State': 'Enabled'}) + + self.assertEqual({'is_commit_required': False, + 'is_reboot_required': + constants.RebootRequired.false}, + result) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_set_lifecycle_settings_with_readonly_attr( + self, mock_requests, mock_wait_until_idrac_is_ready): + expected_message = ("Cannot set read-only Lifecycle attributes: " + "['Licensed'].") + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.LifecycleControllerEnumerations[ + uris.DCIM_LCEnumeration]['ok']}, + {'text': test_utils.LifecycleControllerEnumerations[ + uris.DCIM_LCString]['ok']}]) + + self.assertRaisesRegexp( + exceptions.DRACOperationFailed, re.escape(expected_message), + self.drac_client.set_lifecycle_settings, {'Licensed': 'yes'}) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_set_lifecycle_settings_with_incorrect_enum_value( + self, mock_requests, mock_wait_until_idrac_is_ready): + expected_message = ("Attribute 'Lifecycle Controller State' cannot " + "be set to value 'foo'. It must be in " + "['Disabled', 'Enabled', 'Recovery'].") + + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.LifecycleControllerEnumerations[ + uris.DCIM_LCEnumeration]['ok']}, + {'text': test_utils.LifecycleControllerEnumerations[ + uris.DCIM_LCString]['ok']}]) + self.assertRaisesRegexp( + exceptions.DRACOperationFailed, re.escape(expected_message), + self.drac_client.set_lifecycle_settings, + {'Lifecycle Controller State': 'foo'}) + + +class ClientLCChangesTestCase(base.BaseTest): + + def setUp(self): + super(ClientLCChangesTestCase, self).setUp() + self.drac_client = dracclient.client.DRACClient( + **test_utils.FAKE_ENDPOINT) + + @mock.patch.object(dracclient.resources.job.JobManagement, + 'create_config_job', spec_set=True, autospec=True) + def test_commit_pending_lifecycle_changes(self, mock_create_config_job): + + self.drac_client.commit_pending_lifecycle_changes() + + mock_create_config_job.assert_called_once_with( + mock.ANY, resource_uri=uris.DCIM_LCService, + cim_creation_class_name='DCIM_LCService', + cim_name='DCIM:LCService', target='', + reboot=False, start_time='TIME_NOW', + wait_for_idrac=False, + method_name='CreateConfigJob') + + @mock.patch.object(dracclient.resources.job.JobManagement, + 'create_config_job', spec_set=True, autospec=True) + def test_commit_pending_lifecycle_changes_with_time( + self, mock_create_config_job): + timestamp = '20140924140201' + self.drac_client.commit_pending_lifecycle_changes( + start_time=timestamp) + + mock_create_config_job.assert_called_once_with( + mock.ANY, resource_uri=uris.DCIM_LCService, + cim_creation_class_name='DCIM_LCService', + cim_name='DCIM:LCService', target='', + reboot=False, start_time=timestamp, + wait_for_idrac=False, + method_name='CreateConfigJob') diff --git a/dracclient/tests/test_nic.py b/dracclient/tests/test_nic.py new file mode 100644 index 0000000..2a4ea79 --- /dev/null +++ b/dracclient/tests/test_nic.py @@ -0,0 +1,495 @@ +# +# 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 datetime +import lxml.etree +import re +from unittest import mock + +import requests_mock + +import dracclient.client +from dracclient import constants +from dracclient import exceptions +from dracclient.resources.inventory import NIC +import dracclient.resources.job +from dracclient.resources import nic +from dracclient.resources import uris +from dracclient.tests import base +from dracclient.tests import utils as test_utils + + +@requests_mock.Mocker() +@mock.patch.object(dracclient.client.WSManClient, 'wait_until_idrac_is_ready', + spec_set=True, autospec=True) +class ClientNICTestCase(base.BaseTest): + + def setUp(self): + super(ClientNICTestCase, self).setUp() + self.drac_client = dracclient.client.DRACClient( + **test_utils.FAKE_ENDPOINT) + + def test_list_nics(self, mock_requests, + mock_wait_until_idrac_is_ready): + expected_nics = [ + NIC(id='NIC.Embedded.1-1-1', + mac='B0:83:FE:C6:6F:A1', + model='Broadcom Gigabit Ethernet BCM5720 - B0:83:FE:C6:6F:A1', + speed_mbps=1000, + duplex='full duplex', + media_type='Base T'), + NIC(id='NIC.Slot.2-1-1', + mac='A0:36:9F:52:7D:1E', + model='Intel(R) Gigabit 2P I350-t Adapter - A0:36:9F:52:7D:1E', + speed_mbps=1000, + duplex='full duplex', + media_type='Base T'), + NIC(id='NIC.Slot.2-2-1', + mac='A0:36:9F:52:7D:1F', + model='Intel(R) Gigabit 2P I350-t Adapter - A0:36:9F:52:7D:1F', + speed_mbps=1000, + duplex='full duplex', + media_type='Base T'), + NIC(id='NIC.Embedded.2-1-1', + mac='B0:83:FE:C6:6F:A2', + model='Broadcom Gigabit Ethernet BCM5720 - B0:83:FE:C6:6F:A2', + speed_mbps=1000, + duplex='full duplex', + media_type='Base T') + ] + + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.InventoryEnumerations[uris.DCIM_NICView]['ok']) + + self.assertEqual(expected_nics, self.drac_client.list_nics()) + + def test_list_nics_sorted(self, mock_requests, + mock_wait_until_idrac_is_ready): + expected_nics = [ + NIC(id='NIC.Embedded.1-1-1', + mac='B0:83:FE:C6:6F:A1', + model='Broadcom Gigabit Ethernet BCM5720 - B0:83:FE:C6:6F:A1', + speed_mbps=1000, + duplex='full duplex', + media_type='Base T'), + NIC(id='NIC.Embedded.2-1-1', + mac='B0:83:FE:C6:6F:A2', + model='Broadcom Gigabit Ethernet BCM5720 - B0:83:FE:C6:6F:A2', + speed_mbps=1000, + duplex='full duplex', + media_type='Base T'), + NIC(id='NIC.Slot.2-1-1', + mac='A0:36:9F:52:7D:1E', + model='Intel(R) Gigabit 2P I350-t Adapter - A0:36:9F:52:7D:1E', + speed_mbps=1000, + duplex='full duplex', + media_type='Base T'), + NIC(id='NIC.Slot.2-2-1', + mac='A0:36:9F:52:7D:1F', + model='Intel(R) Gigabit 2P I350-t Adapter - A0:36:9F:52:7D:1F', + speed_mbps=1000, + duplex='full duplex', + media_type='Base T') + ] + + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.InventoryEnumerations[uris.DCIM_NICView]['ok']) + + self.assertEqual(expected_nics, self.drac_client.list_nics(sort=True)) + + def test_list_nic_settings(self, mock_requests, + mock_wait_until_idrac_is_ready): + expected_enum_attr = nic.NICEnumerationAttribute( + name='BootStrapType', + instance_id='NIC.Integrated.1-3-1:BootStrapType', + fqdd='NIC.Integrated.1-3-1', + read_only=False, + current_value='AutoDetect', + pending_value=None, + possible_values=['AutoDetect', 'BBS', 'Int18h', 'Int19h']) + + expected_string_attr = nic.NICStringAttribute( + name='BusDeviceFunction', + instance_id='NIC.Integrated.1-3-1:BusDeviceFunction', + fqdd='NIC.Integrated.1-3-1', + read_only=True, + current_value='02:00:00', + pending_value=None, + min_length=0, + max_length=0, + pcre_regex=None) + + expected_integer_attr = nic.NICIntegerAttribute( + name='BlnkLeds', + instance_id='NIC.Integrated.1-3-1:BlnkLeds', + fqdd='NIC.Integrated.1-3-1', + read_only=False, + current_value=0, + pending_value=None, + lower_bound=0, + upper_bound=15) + + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICEnumeration]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICString]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICInteger]['ok']}]) + + nic_settings = self.drac_client.list_nic_settings( + nic_id='NIC.Integrated.1-3-1') + + self.assertEqual(63, len(nic_settings)) + + self.assertIn('BootStrapType', nic_settings) + self.assertEqual(expected_enum_attr, + nic_settings['BootStrapType']) + + self.assertIn('BusDeviceFunction', nic_settings) + self.assertEqual(expected_string_attr, + nic_settings['BusDeviceFunction']) + + self.assertIn('BlnkLeds', nic_settings) + self.assertEqual(expected_integer_attr, + nic_settings['BlnkLeds']) + + def test_list_nic_settings_with_colliding_attrs( + self, mock_requests, mock_wait_until_idrac_is_ready): + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICEnumeration]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICString]['colliding']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICInteger]['ok']}]) + + self.assertRaises( + exceptions.DRACOperationFailed, + self.drac_client.list_nic_settings, + nic_id='NIC.Integrated.1-3-1') + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True, + autospec=True) + def test_set_nic_settings(self, mock_requests, mock_invoke, + mock_wait_until_idrac_is_ready): + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICEnumeration]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICString]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICInteger]['ok']}]) + + expected_selectors = {'CreationClassName': 'DCIM_NICService', + 'Name': 'DCIM:NICService', + 'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'DCIM:ComputerSystem'} + expected_properties = {'Target': 'NIC.Integrated.1-3-1', + 'AttributeValue': ['PXE'], + 'AttributeName': ['LegacyBootProto']} + + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.NICInvocations[uris.DCIM_NICService][ + 'SetAttributes']['ok']) + + result = self.drac_client.set_nic_settings( + nic_id='NIC.Integrated.1-3-1', + settings={'LegacyBootProto': 'PXE'}) + + self.assertEqual({'is_commit_required': True, + 'is_reboot_required': constants.RebootRequired.true}, + result) + + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_NICService, 'SetAttributes', + expected_selectors, expected_properties, + wait_for_idrac=True) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True, + autospec=True) + def test_set_nic_settings_string(self, mock_requests, mock_invoke, + mock_wait_until_idrac_is_ready): + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICEnumeration]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICString]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICInteger]['ok']}]) + + expected_selectors = {'CreationClassName': 'DCIM_NICService', + 'Name': 'DCIM:NICService', + 'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'DCIM:ComputerSystem'} + expected_properties = {'Target': 'NIC.Integrated.1-3-1', + 'AttributeValue': ['D4:AE:52:A5:B1:01'], + 'AttributeName': ['VirtMacAddr']} + + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.NICInvocations[uris.DCIM_NICService][ + 'SetAttributes']['ok']) + + result = self.drac_client.set_nic_settings( + nic_id='NIC.Integrated.1-3-1', + settings={'VirtMacAddr': 'D4:AE:52:A5:B1:01'}) + + self.assertEqual({'is_commit_required': True, + 'is_reboot_required': constants.RebootRequired.true}, + result) + + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_NICService, 'SetAttributes', + expected_selectors, expected_properties, + wait_for_idrac=True) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True, + autospec=True) + def test_set_nic_settings_integer(self, mock_requests, mock_invoke, + mock_wait_until_idrac_is_ready): + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICEnumeration]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICString]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICInteger]['ok']}]) + + expected_selectors = {'CreationClassName': 'DCIM_NICService', + 'Name': 'DCIM:NICService', + 'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'DCIM:ComputerSystem'} + expected_properties = {'Target': 'NIC.Integrated.1-3-1', + 'AttributeValue': [1], + 'AttributeName': ['SecondTgtBootLun']} + + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.NICInvocations[uris.DCIM_NICService][ + 'SetAttributes']['ok']) + + result = self.drac_client.set_nic_settings( + nic_id='NIC.Integrated.1-3-1', + settings={'SecondTgtBootLun': 1}) + + self.assertEqual({'is_commit_required': True, + 'is_reboot_required': constants.RebootRequired.true}, + result) + + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_NICService, 'SetAttributes', + expected_selectors, expected_properties, + wait_for_idrac=True) + + def test_set_nic_settings_error(self, mock_requests, + mock_wait_until_idrac_is_ready): + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICEnumeration]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICString]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICInteger]['ok']}, + {'text': test_utils.NICInvocations[ + uris.DCIM_NICService]['SetAttributes']['error']}]) + + self.assertRaises(exceptions.DRACOperationFailed, + self.drac_client.set_nic_settings, + 'NIC.InvalidTarget', + {'LegacyBootProto': 'PXE'}) + + def test_set_nic_settings_with_unknown_attr( + self, mock_requests, mock_wait_until_idrac_is_ready): + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICEnumeration]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICString]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICInteger]['ok']}]) + + self.assertRaises(exceptions.InvalidParameterValue, + self.drac_client.set_nic_settings, + 'NIC.Integrated.1-3-1', + {'foo': 'bar'}) + + def test_set_nic_settings_with_unchanged_attr( + self, mock_requests, mock_wait_until_idrac_is_ready): + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICEnumeration]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICString]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICInteger]['ok']}]) + + result = self.drac_client.set_nic_settings( + nic_id='NIC.Integrated.1-3-1', + settings={'LegacyBootProto': 'NONE'}) + + self.assertEqual({'is_commit_required': False, + 'is_reboot_required': + constants.RebootRequired.false}, + result) + + def test_set_nic_settings_with_readonly_attr( + self, mock_requests, mock_wait_until_idrac_is_ready): + expected_message = ( + "Cannot set read-only iDRAC Card attributes: ['LinkStatus'].") + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICEnumeration]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICString]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICInteger]['ok']}]) + + self.assertRaisesRegexp( + exceptions.DRACOperationFailed, re.escape(expected_message), + self.drac_client.set_nic_settings, + 'NIC.Integrated.1-3-1', + {'LinkStatus': 'Connected'}) + + def test_set_nic_settings_with_incorrect_enum( + self, mock_requests, mock_wait_until_idrac_is_ready): + expected_message = ( + "Attribute 'LegacyBootProto' cannot be set to value 'foo'. " + "It must be in ['PXE', 'iSCSI', 'NONE'].") + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICEnumeration]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICString]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICInteger]['ok']}]) + + self.assertRaisesRegexp( + exceptions.DRACOperationFailed, re.escape(expected_message), + self.drac_client.set_nic_settings, + 'NIC.Integrated.1-3-1', + {'LegacyBootProto': 'foo'}) + + def test_set_nic_settings_with_incorrect_regexp( + self, mock_requests, mock_wait_until_idrac_is_ready): + expected_message = ( + "Attribute 'VirtMacAddr' cannot be set to value 'foo.' " + "It must match regex '^([0-9a-fA-F]{2}:){5}([0-9a-fA-F]{2})$'.") + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICEnumeration]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICString]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICInteger]['ok']}]) + + self.assertRaisesRegexp( + exceptions.DRACOperationFailed, re.escape(expected_message), + self.drac_client.set_nic_settings, + 'NIC.Integrated.1-3-1', + {'VirtMacAddr': 'foo'}) + + def test_set_nic_settings_with_out_of_bounds_value( + self, mock_requests, mock_wait_until_idrac_is_ready): + expected_message = ( + "Attribute BannerMessageTimeout cannot be set to value 100. " + "It must be between 0 and 14.") + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICEnumeration]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICString]['ok']}, + {'text': test_utils.NICEnumerations[ + uris.DCIM_NICInteger]['ok']}]) + + self.assertRaisesRegexp( + exceptions.DRACOperationFailed, re.escape(expected_message), + self.drac_client.set_nic_settings, + 'NIC.Integrated.1-3-1', + {'BannerMessageTimeout': 100}) + + +class ClientNICSettingTestCase(base.BaseTest): + + def setUp(self): + super(ClientNICSettingTestCase, self).setUp() + self.drac_client = dracclient.client.DRACClient( + **test_utils.FAKE_ENDPOINT) + + @mock.patch.object(dracclient.resources.job.JobManagement, + 'create_config_job', spec_set=True, autospec=True) + def test_create_nic_config_job(self, mock_create_config_job): + + nic_id = 'NIC.Embedded.1-1-1' + self.drac_client.create_nic_config_job( + nic_id=nic_id) + + mock_create_config_job.assert_called_once_with( + mock.ANY, resource_uri=uris.DCIM_NICService, + cim_creation_class_name='DCIM_NICService', + cim_name='DCIM:NICService', + target=nic_id, + reboot=False, + start_time='TIME_NOW') + + @mock.patch.object(dracclient.resources.job.JobManagement, + 'create_config_job', spec_set=True, autospec=True) + def test_create_nic_config_job_reboot(self, mock_create_config_job): + + nic_id = 'NIC.Embedded.1-1-1' + self.drac_client.create_nic_config_job( + nic_id=nic_id, + reboot=True) + + mock_create_config_job.assert_called_once_with( + mock.ANY, resource_uri=uris.DCIM_NICService, + cim_creation_class_name='DCIM_NICService', + cim_name='DCIM:NICService', + target=nic_id, + reboot=True, + start_time='TIME_NOW') + + @mock.patch.object(dracclient.resources.job.JobManagement, + 'create_config_job', spec_set=True, autospec=True) + def test_create_nic_config_job_time(self, mock_create_config_job): + + nic_id = 'NIC.Embedded.1-1-1' + timestamp = datetime.datetime.today().strftime('%Y%m%d%H%M%S') + self.drac_client.create_nic_config_job( + nic_id=nic_id, + start_time=timestamp) + + mock_create_config_job.assert_called_once_with( + mock.ANY, resource_uri=uris.DCIM_NICService, + cim_creation_class_name='DCIM_NICService', + cim_name='DCIM:NICService', + target=nic_id, + reboot=False, + start_time=timestamp) + + @mock.patch.object(dracclient.resources.job.JobManagement, + 'create_config_job', spec_set=True, autospec=True) + def test_create_nic_config_job_no_time(self, mock_create_config_job): + + nic_id = 'NIC.Embedded.1-1-1' + self.drac_client.create_nic_config_job( + nic_id=nic_id, + start_time=None) + + mock_create_config_job.assert_called_once_with( + mock.ANY, resource_uri=uris.DCIM_NICService, + cim_creation_class_name='DCIM_NICService', + cim_name='DCIM:NICService', + target=nic_id, + reboot=False, + start_time=None) diff --git a/dracclient/tests/test_raid.py b/dracclient/tests/test_raid.py index f802db8..0793ca5 100644 --- a/dracclient/tests/test_raid.py +++ b/dracclient/tests/test_raid.py @@ -11,12 +11,17 @@ # License for the specific language governing permissions and limitations # under the License. + +import collections import lxml.etree -import mock import random +import re +from unittest import mock + import requests_mock import dracclient.client +from dracclient import constants from dracclient import exceptions import dracclient.resources.job from dracclient.resources import raid @@ -33,16 +38,278 @@ def setUp(self): super(ClientRAIDManagementTestCase, self).setUp() self.drac_client = dracclient.client.DRACClient( **test_utils.FAKE_ENDPOINT) + self.raid_controller_fqdd = "RAID.Integrated.1-1" + self.boss_controller_fqdd = "AHCI.Slot.3-1" + cntl_dict = {'RAID.Integrated.1-1': + ['Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1', + 'Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1'], + 'AHCI.Integrated.1-1': + ['Disk.Bay.0:Enclosure.Internal.0-1:AHCI.Integrated.1-1', + 'Disk.Bay.1:Enclosure.Internal.0-1:AHCI.Integrated.1-1']} + self.controllers_to_physical_disk_ids = cntl_dict + self.disk_1 = raid.PhysicalDisk( + id='Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1', + description='Disk 0 in Backplane 1 of Int RAID Controller 1', + controller='RAID.Integrated.1-1', + manufacturer='ATA', + model='ST91000640NS', + media_type='hdd', + interface_type='sata', + size_mb=953344, + free_size_mb=953344, + serial_number='9XG4SLGZ', + firmware_version='AA09', + status='ok', + raid_status='ready', + sas_address='500056B37789ABE3', + device_protocol=None, + bus=None) - def test_list_raid_controllers(self, mock_requests): + self.disk_2 = raid.PhysicalDisk( + id='Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1', + description='Disk 1 in Backplane 1 of Int RAID Controller 1', + controller='RAID.Integrated.1-1', + manufacturer='ATA', + model='ST91000640NS', + media_type='hdd', + interface_type='sata', + size_mb=953344, + free_size_mb=953344, + serial_number='9XG4SLGZ', + firmware_version='AA09', + status='online', + raid_status='ready', + sas_address='500056B37789ABE3', + device_protocol=None, + bus=None) + + self.disk_3 = raid.PhysicalDisk( + id='Disk.Bay.0:Enclosure.Internal.0-1:AHCI.Integrated.1-1', + description='Disk 1 in Backplane 1 of Int BOSS Controller 1', + controller='AHCI.Integrated.1-1', + manufacturer='ATA', + model='ST91000640NS', + media_type='hdd', + interface_type='sata', + size_mb=953344, + free_size_mb=953344, + serial_number='9XG4SLGZ', + firmware_version='AA09', + status='online', + raid_status='ready', + sas_address='500056B37789ABE3', + device_protocol=None, + bus=None) + + self.disk_4 = raid.PhysicalDisk( + id='Disk.Bay.1:Enclosure.Internal.0-1:AHCI.Integrated.1-1', + description='Disk 1 in Backplane 1 of Int RAID Controller 1', + controller='AHCI.Integrated.1-1', + manufacturer='ATA', + model='ST91000640NS', + media_type='hdd', + interface_type='sata', + size_mb=953344, + free_size_mb=953344, + serial_number='9XG4SLGZ', + firmware_version='AA09', + status='online', + raid_status='ready', + sas_address='500056B37789ABE3', + device_protocol=None, + bus=None) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_list_raid_settings(self, mock_requests, + mock_wait_until_idrac_is_ready): + expected_enum_attr = raid.RAIDEnumerableAttribute( + name='RAIDCurrentControllerMode', + instance_id='RAID.Integrated.1-1:RAIDCurrentControllerMode', # noqa + current_value=['RAID'], + pending_value=None, + read_only=True, + fqdd='RAID.Integrated.1-1', + possible_values=['RAID', 'Enhanced HBA']) + expected_string_attr = raid.RAIDStringAttribute( + name='Name', + instance_id='Disk.Virtual.1:RAID.Integrated.1-1:Name', # noqa + current_value='Virtual Disk 1', + pending_value=None, + read_only=True, + fqdd='Disk.Virtual.1:RAID.Integrated.1-1', + min_length=0, + max_length=129) + expected_integer_attr = raid.RAIDIntegerAttribute( + name='RAIDmaxSupportedVD', + instance_id='RAID.Integrated.1-1:RAIDmaxSupportedVD', # noqa + current_value=240, + pending_value=None, + read_only=True, + fqdd='RAID.Integrated.1-1', + lower_bound=0, + upper_bound=0) + # expected_string_attr + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.RAIDEnumerations[ + uris.DCIM_RAIDEnumeration]['ok']}, + {'text': test_utils.RAIDEnumerations[ + uris.DCIM_RAIDString]['ok']}, + {'text': test_utils.RAIDEnumerations[ + uris.DCIM_RAIDInteger]['ok']} + ]) + + raid_settings = self.drac_client.list_raid_settings() + self.assertEqual(219, len(raid_settings)) + # enumerable attribute + self.assertIn( + 'RAID.Integrated.1-1:RAIDCurrentControllerMode', # noqa + raid_settings) + self.assertEqual(expected_enum_attr.fqdd, raid_settings[ + 'RAID.Integrated.1-1:RAIDCurrentControllerMode'].fqdd) # noqa + # string attribute + self.assertIn( + 'Disk.Virtual.1:RAID.Integrated.1-1:Name', # noqa + raid_settings) + self.assertEqual(expected_string_attr.fqdd, + raid_settings['Disk.Virtual.1:RAID.Integrated.1-1:Name'].fqdd) # noqa + # integer attribute + self.assertIn( + 'RAID.Integrated.1-1:RAIDmaxSupportedVD', # noqa + raid_settings) + self.assertEqual(expected_integer_attr.fqdd, raid_settings[ + 'RAID.Integrated.1-1:RAIDmaxSupportedVD'].fqdd) # noqa + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + @mock.patch.object(dracclient.client.WSManClient, + 'invoke', spec_set=True, + autospec=True) + def test_set_raid_settings(self, mock_requests, + mock_invoke, + mock_wait_until_idrac_is_ready): + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.RAIDEnumerations[ + uris.DCIM_RAIDEnumeration]['ok']}, + {'text': test_utils.RAIDEnumerations[ + uris.DCIM_RAIDString]['ok']}, + {'text': test_utils.RAIDEnumerations[ + uris.DCIM_RAIDInteger]['ok']}]) + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.RAIDInvocations[uris.DCIM_RAIDService][ + 'SetAttributes']['ok']) + + result = self.drac_client.set_raid_settings( + self.raid_controller_fqdd, + {'RAID.Integrated.1-1:RAIDRequestedControllerMode': 'RAID'}) + + self.assertEqual({'is_commit_required': True, + 'is_reboot_required': constants.RebootRequired.true + }, + result) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_set_raid_settings_with_unknown_attr( + self, mock_requests, mock_wait_until_idrac_is_ready): + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.RAIDEnumerations[ + uris.DCIM_RAIDEnumeration]['ok']}, + {'text': test_utils.RAIDEnumerations[ + uris.DCIM_RAIDString]['ok']}, + {'text': test_utils.RAIDEnumerations[ + uris.DCIM_RAIDInteger]['ok']}, + {'text': test_utils.RAIDInvocations[ + uris.DCIM_RAIDService]['SetAttributes']['error']}]) + + self.assertRaises(exceptions.InvalidParameterValue, + self.drac_client.set_raid_settings, + self.raid_controller_fqdd, {'foo': 'bar'}) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_set_raid_settings_with_unchanged_attr( + self, mock_requests, mock_wait_until_idrac_is_ready): + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.RAIDEnumerations[ + uris.DCIM_RAIDEnumeration]['ok']}, + {'text': test_utils.RAIDEnumerations[ + uris.DCIM_RAIDString]['ok']}, + {'text': test_utils.RAIDEnumerations[ + uris.DCIM_RAIDInteger]['ok']}]) + attrKey = 'Disk.Virtual.1:RAID.Integrated.1-1:RAIDdefaultWritePolicy' + result = self.drac_client.set_raid_settings( + self.raid_controller_fqdd, + {attrKey: 'WriteBack'}) + + self.assertEqual({'is_commit_required': False, + 'is_reboot_required': + constants.RebootRequired.false}, + result) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_set_raid_settings_with_readonly_attr( + self, mock_requests, mock_wait_until_idrac_is_ready): + expected_message = ( + "Cannot set read-only RAID attributes: " + "['RAID.Integrated.1-1:RAIDCurrentControllerMode']." + ) + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.RAIDEnumerations[ + uris.DCIM_RAIDEnumeration]['ok']}, + {'text': test_utils.RAIDEnumerations[ + uris.DCIM_RAIDString]['ok']}, + {'text': test_utils.RAIDEnumerations[ + uris.DCIM_RAIDInteger]['ok']}]) + + self.assertRaisesRegexp( + exceptions.DRACOperationFailed, re.escape(expected_message), + self.drac_client.set_raid_settings, + self.raid_controller_fqdd, + {'RAID.Integrated.1-1:RAIDCurrentControllerMode': 'Enhanced HBA'}) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_set_raid_settings_with_incorrect_enum_value( + self, mock_requests, mock_wait_until_idrac_is_ready): + expected_message = ("Attribute 'RAIDRequestedControllerMode' cannot " + "be set to value 'foo'. It must be in " + "['RAID', 'Enhanced HBA', 'None'].") + + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.RAIDEnumerations[ + uris.DCIM_RAIDEnumeration]['ok']}, + {'text': test_utils.RAIDEnumerations[ + uris.DCIM_RAIDString]['ok']}, + {'text': test_utils.RAIDEnumerations[ + uris.DCIM_RAIDInteger]['ok']}]) + self.assertRaisesRegexp( + exceptions.DRACOperationFailed, re.escape(expected_message), + self.drac_client.set_raid_settings, + self.raid_controller_fqdd, + {'RAID.Integrated.1-1:RAIDRequestedControllerMode': 'foo'}) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_list_raid_controllers(self, mock_requests, + mock_wait_until_idrac_is_ready): expected_raid_controller = raid.RAIDController( id='RAID.Integrated.1-1', description='Integrated RAID Controller 1', manufacturer='DELL', model='PERC H710 Mini', primary_status='ok', - firmware_version='21.3.0-0009') - + firmware_version='21.3.0-0009', + bus='1', + supports_realtime=True) mock_requests.post( 'https://1.2.3.4:443/wsman', text=test_utils.RAIDEnumerations[uris.DCIM_ControllerView]['ok']) @@ -50,7 +317,11 @@ def test_list_raid_controllers(self, mock_requests): self.assertIn(expected_raid_controller, self.drac_client.list_raid_controllers()) - def test_list_virtual_disks(self, mock_requests): + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_list_virtual_disks(self, mock_requests, + mock_wait_until_idrac_is_ready): expected_virtual_disk = raid.VirtualDisk( id='Disk.Virtual.0:RAID.Integrated.1-1', name='disk 0', @@ -62,7 +333,11 @@ def test_list_virtual_disks(self, mock_requests): raid_status='online', span_depth=1, span_length=2, - pending_operations=None) + pending_operations=None, + physical_disks=[ + 'Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1', + 'Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1' + ]) mock_requests.post( 'https://1.2.3.4:443/wsman', @@ -71,7 +346,41 @@ def test_list_virtual_disks(self, mock_requests): self.assertIn(expected_virtual_disk, self.drac_client.list_virtual_disks()) - def test_list_physical_disks(self, mock_requests): + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_list_virtual_disks_with_raid_status_change( + self, mock_requests, mock_wait_until_idrac_is_ready): + expected_virtual_disk = raid.VirtualDisk( + id='Disk.Virtual.0:RAID.Integrated.1-1', + name='disk 0', + description='Virtual Disk 0 on Integrated RAID Controller 1', + controller='RAID.Integrated.1-1', + raid_level='1', + size_mb=571776, + status='ok', + raid_status='online', + span_depth=1, + span_length=2, + pending_operations=None, + physical_disks=[ + 'Disk.Bay.4:Enclosure.Internal.0-1:RAID.Integrated.1-1', + 'Disk.Bay.5:Enclosure.Internal.0-1:RAID.Integrated.1-1' + ]) + + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.RAIDEnumerations[ + uris.DCIM_VirtualDiskView]['Raid_Status_ok']) + + self.assertIn(expected_virtual_disk, + self.drac_client.list_virtual_disks()) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_list_physical_disks(self, mock_requests, + mock_wait_until_idrac_is_ready): expected_physical_disk = raid.PhysicalDisk( id='Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1', description=('Disk 1 in Backplane 1 of ' @@ -86,7 +395,10 @@ def test_list_physical_disks(self, mock_requests): serial_number='S0M3EY2Z', firmware_version='LS0A', status='ok', - raid_status='ready') + raid_status='ready', + sas_address='5000C5007764F409', + device_protocol=None, + bus=None) mock_requests.post( 'https://1.2.3.4:443/wsman', @@ -95,7 +407,11 @@ def test_list_physical_disks(self, mock_requests): self.assertIn(expected_physical_disk, self.drac_client.list_physical_disks()) - def test_list_physical_disks_direct(self, mock_requests): + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_list_physical_disks_direct(self, mock_requests, + mock_wait_until_idrac_is_ready): expected_physical_disk = raid.PhysicalDisk( id='Disk.Direct.2:RAID.Integrated.1-1', description=('Disk 2 on ' @@ -110,7 +426,40 @@ def test_list_physical_disks_direct(self, mock_requests): serial_number='S0M3EY3Z', firmware_version='LS0B', status='ok', - raid_status='ready') + raid_status='ready', + sas_address='5000C5007764F409', + device_protocol=None, + bus=None) + + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.RAIDEnumerations[uris.DCIM_PhysicalDiskView]['ok']) + + self.assertIn(expected_physical_disk, + self.drac_client.list_physical_disks()) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_list_physical_disks_nvme(self, mock_requests, + mock_wait_until_idrac_is_ready): + expected_physical_disk = raid.PhysicalDisk( + id='Disk.Bay.20:Enclosure.Internal.0-1:PCIeExtender.Slot.1', + description='PCIe SSD in Slot 20 in Bay 1', + controller='PCIeExtender.Slot.1', + manufacturer='SAMSUNG', + model='Dell Express Flash PM1725a 800GB SFF', + media_type='ssd', + interface_type='pcie', + size_mb=763097, + free_size_mb=None, + serial_number='S39YNX0JB02343', + firmware_version='1.0.4', + status='unknown', + raid_status=None, + sas_address=None, + device_protocol='NVMe-MI1.0', + bus='3E') mock_requests.post( 'https://1.2.3.4:443/wsman', @@ -142,13 +491,18 @@ def test_convert_physical_disks_1(self, mock_requests, mock_invoke): 'SystemName': 'DCIM:ComputerSystem', 'Name': 'DCIM:RAIDService'} expected_properties = {'PDArray': [device_fqdd]} + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.RAIDInvocations[uris.DCIM_RAIDService][ + 'ConvertToRAID']['ok']) result = self.drac_client.convert_physical_disks( raid_controller='controller', physical_disks=[device_fqdd], raid_enable=True) - self.assertEqual({'commit_required': False}, result) + self.assertEqual({'is_commit_required': True, + 'is_reboot_required': constants.RebootRequired.true}, + result) mock_invoke.assert_called_once_with( mock.ANY, uris.DCIM_RAIDService, expected_invocation, expected_selectors, expected_properties, @@ -168,13 +522,18 @@ def test_convert_physical_disks_n(self, mock_requests, mock_invoke): 'SystemName': 'DCIM:ComputerSystem', 'Name': 'DCIM:RAIDService'} expected_properties = {'PDArray': device_list} + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.RAIDInvocations[uris.DCIM_RAIDService][ + 'ConvertToRAID']['ok']) result = self.drac_client.convert_physical_disks( raid_controller='controller', physical_disks=device_list, raid_enable=True) - self.assertEqual({'commit_required': False}, result) + self.assertEqual({'is_commit_required': True, + 'is_reboot_required': constants.RebootRequired.true}, + result) mock_invoke.assert_called_once_with( mock.ANY, uris.DCIM_RAIDService, expected_invocation, expected_selectors, expected_properties, @@ -192,13 +551,18 @@ def test_convert_physical_disks_nonraid_1(self, mock_requests, 'SystemName': 'DCIM:ComputerSystem', 'Name': 'DCIM:RAIDService'} expected_properties = {'PDArray': [device_fqdd]} + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.RAIDInvocations[uris.DCIM_RAIDService][ + 'ConvertToRAID']['ok']) result = self.drac_client.convert_physical_disks( raid_controller='controller', physical_disks=[device_fqdd], raid_enable=False) - self.assertEqual({'commit_required': False}, result) + self.assertEqual({'is_commit_required': True, + 'is_reboot_required': constants.RebootRequired.true}, + result) mock_invoke.assert_called_once_with( mock.ANY, uris.DCIM_RAIDService, expected_invocation, expected_selectors, expected_properties, @@ -219,49 +583,28 @@ def test_convert_physical_disks_nonraid_n(self, mock_requests, 'SystemName': 'DCIM:ComputerSystem', 'Name': 'DCIM:RAIDService'} expected_properties = {'PDArray': device_list} - - result = self.drac_client.convert_physical_disks( - raid_controller='controller', - physical_disks=device_list, - raid_enable=False) - - self.assertEqual({'commit_required': False}, result) - mock_invoke.assert_called_once_with( - mock.ANY, uris.DCIM_RAIDService, expected_invocation, - expected_selectors, expected_properties, - expected_return_value=utils.RET_SUCCESS) - - @mock.patch.object(dracclient.client.WSManClient, 'invoke', - spec_set=True, autospec=True) - def test_convert_physical_disks_ok(self, mock_requests, mock_invoke): - '''Convert a number of disks to RAID mode and check the return value''' - device_list = [] - for i in range(0, random.randint(2, 10)): - device_list += self._random_fqdd() - - expected_invocation = 'ConvertToRAID' - expected_selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem', - 'CreationClassName': 'DCIM_RAIDService', - 'SystemName': 'DCIM:ComputerSystem', - 'Name': 'DCIM:RAIDService'} - expected_properties = {'PDArray': device_list} - mock_invoke.return_value = lxml.etree.fromstring( test_utils.RAIDInvocations[uris.DCIM_RAIDService][ - expected_invocation]['ok']) + 'ConvertToRAID']['ok']) result = self.drac_client.convert_physical_disks( raid_controller='controller', physical_disks=device_list, - raid_enable=True) + raid_enable=False) - self.assertEqual({'commit_required': True}, result) + self.assertEqual({'is_commit_required': True, + 'is_reboot_required': constants.RebootRequired.true}, + result) mock_invoke.assert_called_once_with( mock.ANY, uris.DCIM_RAIDService, expected_invocation, expected_selectors, expected_properties, expected_return_value=utils.RET_SUCCESS) - def test_convert_physical_disks_fail(self, mock_requests): + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_convert_physical_disks_fail(self, mock_requests, + mock_wait_until_idrac_is_ready): mock_requests.post( 'https://1.2.3.4:443/wsman', text=test_utils.RAIDInvocations[ @@ -294,7 +637,9 @@ def test_create_virtual_disk(self, mock_requests, mock_invoke): raid_controller='controller', physical_disks=['disk1', 'disk2'], raid_level='1', size_mb=42) - self.assertEqual({'commit_required': True}, result) + self.assertEqual({'is_commit_required': True, + 'is_reboot_required': constants.RebootRequired.true}, + result) mock_invoke.assert_called_once_with( mock.ANY, uris.DCIM_RAIDService, 'CreateVirtualDisk', expected_selectors, expected_properties, @@ -324,13 +669,19 @@ def test_create_virtual_disk_with_extra_params(self, mock_requests, raid_level='1', size_mb=42, disk_name='name', span_length=2, span_depth=3) - self.assertEqual({'commit_required': True}, result) + self.assertEqual({'is_commit_required': True, + 'is_reboot_required': constants.RebootRequired.true}, + result) mock_invoke.assert_called_once_with( mock.ANY, uris.DCIM_RAIDService, 'CreateVirtualDisk', expected_selectors, expected_properties, expected_return_value=utils.RET_SUCCESS) - def test_create_virtual_disk_fail(self, mock_requests): + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_create_virtual_disk_fail(self, mock_requests, + mock_wait_until_idrac_is_ready): mock_requests.post( 'https://1.2.3.4:443/wsman', text=test_utils.RAIDInvocations[ @@ -377,6 +728,24 @@ def test_create_virtual_disk_missing_size(self, mock_requests): physical_disks=['disk1', 'disk2'], raid_level='1', size_mb=None, disk_name='name', span_length=2, span_depth=3) + # This test is specifically for support of creating a RAID1 on a Dell BOSS + # card. It requires that size_mb is set to 0 + @mock.patch.object(dracclient.client.WSManClient, 'invoke', + spec_set=True, autospec=True) + def test_create_virtual_disk_0_size(self, mock_requests, mock_invoke): + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.RAIDInvocations[uris.DCIM_RAIDService][ + 'CreateVirtualDisk']['ok']) + + self.drac_client.create_virtual_disk( + raid_controller='controller', + physical_disks=['disk1', 'disk2'], + raid_level='1', + size_mb=0, + disk_name='name', + span_length=1, + span_depth=2) + def test_create_virtual_disk_invalid_size(self, mock_requests): self.assertRaises( exceptions.InvalidParameterValue, @@ -412,13 +781,19 @@ def test_delete_virtual_disk(self, mock_requests, mock_invoke): result = self.drac_client.delete_virtual_disk('disk1') - self.assertEqual({'commit_required': True}, result) + self.assertEqual({'is_commit_required': True, + 'is_reboot_required': constants.RebootRequired.true}, + result) mock_invoke.assert_called_once_with( mock.ANY, uris.DCIM_RAIDService, 'DeleteVirtualDisk', expected_selectors, expected_properties, expected_return_value=utils.RET_SUCCESS) - def test_delete_virtual_disk_fail(self, mock_requests): + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_delete_virtual_disk_fail(self, mock_requests, + mock_wait_until_idrac_is_ready): mock_requests.post( 'https://1.2.3.4:443/wsman', text=test_utils.RAIDInvocations[ @@ -428,31 +803,211 @@ def test_delete_virtual_disk_fail(self, mock_requests): exceptions.DRACOperationFailed, self.drac_client.delete_virtual_disk, 'disk1') + @mock.patch.object(dracclient.client.WSManClient, 'invoke', + spec_set=True, autospec=True) + def test_reset_raid_config(self, mock_requests, mock_invoke): + expected_selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem', + 'CreationClassName': 'DCIM_RAIDService', + 'SystemName': 'DCIM:ComputerSystem', + 'Name': 'DCIM:RAIDService'} + expected_properties = {'Target': self.raid_controller_fqdd} + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.RAIDInvocations[uris.DCIM_RAIDService][ + 'ResetConfig']['ok']) + result = self.drac_client.reset_raid_config(self.raid_controller_fqdd) + self.assertEqual({'is_commit_required': True, + 'is_reboot_required': + constants.RebootRequired.optional}, + result) + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_RAIDService, 'ResetConfig', + expected_selectors, expected_properties, + expected_return_value=utils.RET_SUCCESS) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_reset_raid_config_fail(self, mock_requests, + mock_wait_until_idrac_is_ready): + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.RAIDInvocations[ + uris.DCIM_RAIDService]['ResetConfig']['error']) + + self.assertRaises( + exceptions.DRACOperationFailed, + self.drac_client.reset_raid_config, self.raid_controller_fqdd) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', + spec_set=True, autospec=True) + def test_clear_foreign_config(self, mock_requests, mock_invoke): + expected_selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem', + 'CreationClassName': 'DCIM_RAIDService', + 'SystemName': 'DCIM:ComputerSystem', + 'Name': 'DCIM:RAIDService'} + expected_properties = {'Target': self.raid_controller_fqdd} + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.RAIDInvocations[uris.DCIM_RAIDService][ + 'ClearForeignConfig']['ok']) + + result = self.drac_client.clear_foreign_config( + self.raid_controller_fqdd) + self.assertEqual({'is_commit_required': True, + 'is_reboot_required': + constants.RebootRequired.optional}, + result) + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_RAIDService, 'ClearForeignConfig', + expected_selectors, expected_properties, + check_return_value=False) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', + spec_set=True, autospec=True) + def test_clear_foreign_config_with_no_foreign_drive(self, + mock_requests, + mock_invoke): + expected_selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem', + 'CreationClassName': 'DCIM_RAIDService', + 'SystemName': 'DCIM:ComputerSystem', + 'Name': 'DCIM:RAIDService'} + expected_properties = {'Target': self.raid_controller_fqdd} + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.RAIDInvocations[uris.DCIM_RAIDService][ + 'ClearForeignConfig']['no_foreign_drive']) + + result = self.drac_client.clear_foreign_config( + self.raid_controller_fqdd) + self.assertEqual({'is_commit_required': False, + 'is_reboot_required': + constants.RebootRequired.false}, + result) + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_RAIDService, 'ClearForeignConfig', + expected_selectors, expected_properties, + check_return_value=False) + + @mock.patch.object(dracclient.client.WSManClient, 'invoke', + spec_set=True, autospec=True) + def test_clear_foreign_config_with_operation_not_supported(self, + mock_requests, + mock_invoke): + expected_selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem', + 'CreationClassName': 'DCIM_RAIDService', + 'SystemName': 'DCIM:ComputerSystem', + 'Name': 'DCIM:RAIDService'} + expected_properties = {'Target': self.boss_controller_fqdd} + mock_invoke.return_value = lxml.etree.fromstring( + test_utils.RAIDInvocations[uris.DCIM_RAIDService][ + 'ClearForeignConfig']['foreign_drive_operation_not_supported']) + + result = self.drac_client.clear_foreign_config( + self.boss_controller_fqdd) + self.assertEqual({'is_commit_required': False, + 'is_reboot_required': + constants.RebootRequired.false}, + result) + mock_invoke.assert_called_once_with( + mock.ANY, uris.DCIM_RAIDService, 'ClearForeignConfig', + expected_selectors, expected_properties, + check_return_value=False) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_clear_foreign_config_with_invalid_controller_id( + self, + mock_requests, + mock_wait_until_idrac_is_ready): + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.RAIDInvocations[ + uris.DCIM_RAIDService]['ClearForeignConfig'] + ['invalid_controller_id']) + + self.assertRaises( + exceptions.DRACOperationFailed, + self.drac_client.clear_foreign_config, 'bad') + @mock.patch.object(dracclient.resources.job.JobManagement, 'create_config_job', spec_set=True, autospec=True) def test_commit_pending_raid_changes(self, mock_requests, mock_create_config_job): - self.drac_client.commit_pending_raid_changes('controller') + self.drac_client.commit_pending_raid_changes('controller', + realtime=False) mock_create_config_job.assert_called_once_with( mock.ANY, resource_uri=uris.DCIM_RAIDService, cim_creation_class_name='DCIM_RAIDService', - cim_name='DCIM:RAIDService', target='controller', reboot=False) + cim_name='DCIM:RAIDService', target='controller', reboot=False, + start_time='TIME_NOW', realtime=False) @mock.patch.object(dracclient.resources.job.JobManagement, 'create_config_job', spec_set=True, autospec=True) def test_commit_pending_raid_changes_with_reboot(self, mock_requests, mock_create_config_job): - self.drac_client.commit_pending_raid_changes('controller', reboot=True) + self.drac_client.commit_pending_raid_changes('controller', + reboot=True, + realtime=False) + + mock_create_config_job.assert_called_once_with( + mock.ANY, resource_uri=uris.DCIM_RAIDService, + cim_creation_class_name='DCIM_RAIDService', + cim_name='DCIM:RAIDService', target='controller', reboot=True, + start_time='TIME_NOW', realtime=False) + + @mock.patch.object(dracclient.resources.job.JobManagement, + 'create_config_job', spec_set=True, autospec=True) + def test_commit_pending_raid_changes_with_start_time( + self, mock_requests, + mock_create_config_job): + timestamp = '20140924140201' + self.drac_client.commit_pending_raid_changes('controller', + start_time=timestamp, + realtime=False) mock_create_config_job.assert_called_once_with( mock.ANY, resource_uri=uris.DCIM_RAIDService, cim_creation_class_name='DCIM_RAIDService', - cim_name='DCIM:RAIDService', target='controller', reboot=True) + cim_name='DCIM:RAIDService', target='controller', reboot=False, + start_time=timestamp, realtime=False) + + @mock.patch.object(dracclient.resources.job.JobManagement, + 'create_config_job', spec_set=True, autospec=True) + def test_commit_pending_raid_changes_with_reboot_and_start_time( + self, mock_requests, + mock_create_config_job): + timestamp = '20140924140201' + self.drac_client.commit_pending_raid_changes('controller', + reboot=True, + start_time=timestamp, + realtime=False) + + mock_create_config_job.assert_called_once_with( + mock.ANY, resource_uri=uris.DCIM_RAIDService, + cim_creation_class_name='DCIM_RAIDService', + cim_name='DCIM:RAIDService', target='controller', reboot=True, + start_time=timestamp, realtime=False) + + @mock.patch.object(dracclient.resources.job.JobManagement, + 'create_config_job', spec_set=True, autospec=True) + def test_commit_pending_raid_changes_with_realtime( + self, mock_requests, + mock_create_config_job): + timestamp = '20140924140201' + self.drac_client.commit_pending_raid_changes('controller', + reboot=False, + start_time=timestamp, + realtime=True) + + mock_create_config_job.assert_called_once_with( + mock.ANY, resource_uri=uris.DCIM_RAIDService, + cim_creation_class_name='DCIM_RAIDService', + cim_name='DCIM:RAIDService', target='controller', reboot=False, + start_time=timestamp, realtime=True) @mock.patch.object(dracclient.resources.job.JobManagement, 'delete_pending_config', spec_set=True, autospec=True) - def test_abandon_pending_bios_changes(self, mock_requests, + def test_abandon_pending_raid_changes(self, mock_requests, mock_delete_pending_config): self.drac_client.abandon_pending_raid_changes('controller') @@ -460,3 +1015,552 @@ def test_abandon_pending_bios_changes(self, mock_requests, mock.ANY, resource_uri=uris.DCIM_RAIDService, cim_creation_class_name='DCIM_RAIDService', cim_name='DCIM:RAIDService', target='controller') + + @mock.patch.object(dracclient.resources.job.JobManagement, + 'delete_pending_config', spec_set=True, autospec=True) + def test_abandon_pending_raid_changes_realtime(self, mock_requests, + mock_delete_pending_config): + self.drac_client.abandon_pending_raid_changes('controller') + + mock_delete_pending_config.assert_called_once_with( + mock.ANY, resource_uri=uris.DCIM_RAIDService, + cim_creation_class_name='DCIM_RAIDService', + cim_name='DCIM:RAIDService', target='controller') + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + @mock.patch.object(dracclient.resources.raid.RAIDManagement, + 'convert_physical_disks', + return_value={}, spec_set=True, + autospec=True) + def test_raid_controller_jbod_capable(self, mock_requests, + mock_wait_until_idrac_is_ready, + mock_convert_physical_disks): + + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.RAIDEnumerations[uris.DCIM_PhysicalDiskView]['ok']) + + is_jbod = self.drac_client.is_jbod_capable(self.raid_controller_fqdd) + + self.assertTrue(is_jbod, msg="is_jbod is true") + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + @mock.patch.object(dracclient.resources.raid.RAIDManagement, + 'convert_physical_disks', + return_value={}, spec_set=True, + autospec=True) + def test_raid_controller_jbod_non_raid(self, mock_requests, + mock_wait_until_idrac_is_ready, + mock_convert_physical_disks): + + pdv = test_utils.RAIDEnumerations[uris.DCIM_PhysicalDiskView]['ok'] + # change to non-RAID value + pdv = pdv.replace("1", + "8") + + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=pdv) + + is_jbod = self.drac_client.is_jbod_capable(self.raid_controller_fqdd) + + self.assertTrue(is_jbod, msg="is_jbod is true") + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + @mock.patch.object(dracclient.resources.raid.RAIDManagement, + 'convert_physical_disks', + return_value={}, spec_set=True, + autospec=True) + def test_raid_controller_jbod_unknown(self, mock_requests, + mock_wait_until_idrac_is_ready, + mock_convert_physical_disks): + + is_jbod = False + pdv = test_utils.RAIDEnumerations[uris.DCIM_PhysicalDiskView]['ok'] + # change to non-RAID value + pdv = pdv.replace("1", + "0") + + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=pdv) + self.assertRaises(exceptions.DRACRequestFailed, + self.drac_client.is_jbod_capable, + self.raid_controller_fqdd) + self.assertFalse(is_jbod, msg="is_jbod is false") + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + @mock.patch.object(dracclient.resources.raid.RAIDManagement, + 'convert_physical_disks', + spec_set=True, + autospec=True) + def test_raid_controller_jbod_not_supported(self, + mock_requests, + mock_convert_physical_disks, + mock_wait_idrac_is_ready): + + msg = " operation is not supported on th" + exc = exceptions.DRACOperationFailed(drac_messages=msg) + mock_convert_physical_disks.side_effect = exc + + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.RAIDEnumerations[uris.DCIM_PhysicalDiskView]['ok']) + + is_jbod = self.drac_client.is_jbod_capable(self.raid_controller_fqdd) + self.assertFalse(is_jbod, msg="is_jbod is false") + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + @mock.patch.object(dracclient.resources.raid.RAIDManagement, + 'convert_physical_disks', + spec_set=True, + autospec=True) + def test_raid_controller_jbod_ex_no_match(self, + mock_requests, + mock_convert_physical_disks, + mock_wait_until_idrac_is_ready): + + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.RAIDEnumerations[uris.DCIM_PhysicalDiskView]['ok']) + msg = "NON_MATCHING_MESSAGE" + exc = exceptions.DRACOperationFailed(drac_messages=msg) + mock_convert_physical_disks.side_effect = exc + + self.assertRaises( + exceptions.DRACOperationFailed, + self.drac_client.is_jbod_capable, self.raid_controller_fqdd) + + def test_is_raid_controller_raid(self, mock_requests): + self.assertTrue(self.drac_client + .is_raid_controller("RAID.Integrated.1-1")) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_is_raid_controller_boss(self, mock_requests, + mock_wait_until_idrac_is_ready): + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.RAIDEnumerations[uris.DCIM_ControllerView]['ok']) + self.assertTrue(self.drac_client + .is_raid_controller("AHCI.Integrated.1-1")) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_is_raid_controller_fail(self, mock_requests, + mock_wait_until_idrac_is_ready): + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.RAIDEnumerations[uris.DCIM_ControllerView]['ok']) + self.assertFalse(self.drac_client + .is_raid_controller("notRAID.Integrated.1-1")) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_is_boss_controller(self, mock_requests, + mock_wait_until_idrac_is_ready): + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.RAIDEnumerations[uris.DCIM_ControllerView]['ok']) + self.assertTrue(self.drac_client + .is_boss_controller("AHCI.Integrated.1-1")) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_is_not_boss_controller(self, mock_requests, + mock_wait_until_idrac_is_ready): + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.RAIDEnumerations[uris.DCIM_ControllerView]['ok']) + self.assertFalse(self.drac_client + .is_boss_controller("notAHCI.Integrated.1-1"), + None) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_is_boss_controller_with_cntl_list(self, mock_requests, + mock_wait_until_idrac_is_ready): + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.RAIDEnumerations[uris.DCIM_ControllerView]['ok']) + controllers = self.drac_client.list_raid_controllers() + self.assertTrue(self.drac_client + .is_boss_controller("AHCI.Integrated.1-1", + controllers)) + + def test_check_disks_status_no_controllers(self, mock_requests): + physical_disks = [self.disk_1, self.disk_2, self.disk_3, self.disk_4] + raid_mgt = self.drac_client._raid_mgmt + + cont_to_phys_disk_ids = collections.defaultdict(list) + mode = constants.RaidStatus.jbod + + raid_mgt._check_disks_status(mode, physical_disks, + cont_to_phys_disk_ids) + jbod_len = len(cont_to_phys_disk_ids['RAID.Integrated.1-1']) + self.assertEqual(jbod_len, 0) + + # Switch mode to RAID and try again + cont_to_phys_disk_ids = collections.defaultdict(list) + mode = constants.RaidStatus.raid + raid_mgt._check_disks_status(mode, physical_disks, + cont_to_phys_disk_ids) + raid_len = len(cont_to_phys_disk_ids['RAID.Integrated.1-1']) + self.assertEqual(raid_len, 0) + + def test_check_disks_status_bad(self, mock_requests): + mode = constants.RaidStatus.raid + disk_2 = self.disk_2._replace(raid_status='FAKE_STATUS') + physical_disks = [self.disk_1, disk_2, self.disk_3, self.disk_4] + raid_mgt = self.drac_client._raid_mgmt + + self.assertRaises(ValueError, + raid_mgt._check_disks_status, + mode, + physical_disks, + self.controllers_to_physical_disk_ids) + mode = constants.RaidStatus.jbod + self.assertRaises(ValueError, + raid_mgt._check_disks_status, + mode, + physical_disks, + self.controllers_to_physical_disk_ids) + + def test_check_disks_status_fail(self, mock_requests): + mode = constants.RaidStatus.raid + disk_2_failed = self.disk_2._replace(raid_status='failed') + physical_disks = [self.disk_1, disk_2_failed, self.disk_3, self.disk_4] + raid_mgt = self.drac_client._raid_mgmt + + self.assertRaises(ValueError, + raid_mgt._check_disks_status, + mode, + physical_disks, + self.controllers_to_physical_disk_ids) + mode = constants.RaidStatus.jbod + self.assertRaises(ValueError, + raid_mgt._check_disks_status, + mode, + physical_disks, + self.controllers_to_physical_disk_ids) + + def test_check_disks_status_no_change(self, mock_requests): + raid_mgt = self.drac_client._raid_mgmt + mode = constants.RaidStatus.raid + physical_disks = [self.disk_1, self.disk_2, + self.disk_3, self.disk_4] + + raid_cntl_to_phys_disk_ids = raid_mgt._check_disks_status( + mode, physical_disks, self.controllers_to_physical_disk_ids) + raid_len = len(raid_cntl_to_phys_disk_ids['RAID.Integrated.1-1']) + self.assertEqual(raid_len, 0) + + mode = constants.RaidStatus.jbod + disk_1_non_raid = self.disk_1._replace(raid_status='non-RAID') + disk_2_non_raid = self.disk_2._replace(raid_status='non-RAID') + physical_disks = [disk_1_non_raid, disk_2_non_raid, + self.disk_3, self.disk_4] + + jbod_cntl_to_phys_disk_ids = raid_mgt._check_disks_status( + mode, physical_disks, self.controllers_to_physical_disk_ids) + jbod_len = len(jbod_cntl_to_phys_disk_ids['RAID.Integrated.1-1']) + self.assertEqual(jbod_len, 0) + + def test_check_disks_status_change_state(self, mock_requests): + raid_mgt = self.drac_client._raid_mgmt + mode = constants.RaidStatus.jbod + physical_disks = [self.disk_1, self.disk_2, self.disk_3, self.disk_4] + + jbod_cntl_to_phys_disk_ids = raid_mgt._check_disks_status( + mode, physical_disks, self.controllers_to_physical_disk_ids) + jbod_len = len(jbod_cntl_to_phys_disk_ids['RAID.Integrated.1-1']) + self.assertEqual(jbod_len, 2) + + mode = constants.RaidStatus.raid + disk_1_non_raid = self.disk_1._replace(raid_status='non-RAID') + disk_2_non_raid = self.disk_2._replace(raid_status='non-RAID') + physical_disks = [disk_1_non_raid, disk_2_non_raid, + self.disk_3, self.disk_4] + raid_cntl_to_phys_disk_ids = raid_mgt._check_disks_status( + mode, physical_disks, self.controllers_to_physical_disk_ids) + raid_len = len(raid_cntl_to_phys_disk_ids['RAID.Integrated.1-1']) + self.assertEqual(raid_len, 2) + + def test_check_disks_status_bad_and_fail(self, mock_requests): + mode = constants.RaidStatus.raid + disk_1_bad = self.disk_1._replace(raid_status='FAKE_STATUS') + disk_2_failed = self.disk_2._replace(raid_status='failed') + physical_disks = [disk_1_bad, disk_2_failed, self.disk_3, self.disk_4] + raid_mgt = self.drac_client._raid_mgmt + + self.assertRaises(ValueError, + raid_mgt._check_disks_status, + mode, + physical_disks, + self.controllers_to_physical_disk_ids) + mode = constants.RaidStatus.jbod + self.assertRaises(ValueError, + raid_mgt._check_disks_status, + mode, + physical_disks, + self.controllers_to_physical_disk_ids) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + @mock.patch.object(dracclient.resources.raid.RAIDManagement, + 'convert_physical_disks', spec_set=True, + autospec=True) + def test_change_physical_disk_state_jbod( + self, mock_requests, + mock_convert_physical_disks, + wait_until_idrac_is_ready): + mode = constants.RaidStatus.jbod + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.RAIDEnumerations[uris.DCIM_PhysicalDiskView]['ok']) + cvt_phys_disks_return_value = {'is_commit_required': True, + 'is_reboot_required': constants. + RebootRequired.true} + mock_convert_physical_disks.return_value = cvt_phys_disks_return_value + + expected_return_value = {'RAID.Integrated.1-1': + cvt_phys_disks_return_value, + 'AHCI.Integrated.1-1': + cvt_phys_disks_return_value} + results = self.drac_client.change_physical_disk_state( + mode, self.controllers_to_physical_disk_ids) + self.assertEqual(results['conversion_results'], + expected_return_value) + + @mock.patch.object(dracclient.resources.raid.RAIDManagement, + 'list_physical_disks', spec_set=True, + autospec=True) + @mock.patch.object(dracclient.resources.raid.RAIDManagement, + 'convert_physical_disks', spec_set=True, + autospec=True) + def test_change_physical_disk_state_raid( + self, mock_requests, + mock_convert_physical_disks, + mock_list_physical_disks): + mode = constants.RaidStatus.raid + disk_1_non_raid = self.disk_1._replace(raid_status='non-RAID') + disk_2_non_raid = self.disk_2._replace(raid_status='non-RAID') + physical_disks = [disk_1_non_raid, disk_2_non_raid, + self.disk_3, self.disk_4] + mock_list_physical_disks.return_value = physical_disks + boss_return_value = {'is_commit_required': False, + 'is_reboot_required': + constants.RebootRequired.false} + raid_return_value = {'is_commit_required': True, + 'is_reboot_required': + constants.RebootRequired.true} + mock_convert_physical_disks.return_value = raid_return_value + + results = self.drac_client.change_physical_disk_state( + mode, self.controllers_to_physical_disk_ids) + self.assertEqual(len(results['conversion_results']), 2) + self.assertEqual(results['conversion_results']['AHCI.Integrated.1-1'], + boss_return_value) + self.assertEqual(results['conversion_results']['RAID.Integrated.1-1'], + raid_return_value) + + @mock.patch.object(dracclient.resources.raid.RAIDManagement, + 'list_physical_disks', spec_set=True, + autospec=True) + def test_change_physical_disk_state_none( + self, mock_requests, + mock_list_physical_disks): + mode = constants.RaidStatus.raid + physical_disks = [self.disk_1, self.disk_2, self.disk_3, self.disk_4] + mock_list_physical_disks.return_value = physical_disks + expected_return_value = {'is_commit_required': False, + 'is_reboot_required': + constants.RebootRequired.false} + results = self.drac_client.change_physical_disk_state( + mode, self.controllers_to_physical_disk_ids) + self.assertEqual(results['conversion_results']['RAID.Integrated.1-1'], + expected_return_value) + self.assertEqual(results['conversion_results']['AHCI.Integrated.1-1'], + expected_return_value) + + @mock.patch.object(dracclient.resources.raid.RAIDManagement, + 'list_physical_disks', spec_set=True, + autospec=True) + @mock.patch.object(dracclient.resources.raid.RAIDManagement, + 'convert_physical_disks', spec_set=True, + autospec=True, + side_effect=exceptions.DRACOperationFailed( + drac_messages=constants.NOT_SUPPORTED_MSG)) + def test_change_physical_disk_state_not_supported( + self, mock_requests, + mock_convert_physical_disks, + mock_list_physical_disks): + mode = constants.RaidStatus.raid + disk_1_non_raid = self.disk_1._replace(raid_status='non-RAID') + disk_2_non_raid = self.disk_2._replace(raid_status='non-RAID') + physical_disks = [disk_1_non_raid, disk_2_non_raid, + self.disk_3, self.disk_4] + mock_list_physical_disks.return_value = physical_disks + expected_return_value = {'is_commit_required': False, + 'is_reboot_required': + constants.RebootRequired.false} + results = self.drac_client.change_physical_disk_state( + mode, self.controllers_to_physical_disk_ids) + self.assertEqual(results['conversion_results']['RAID.Integrated.1-1'], + expected_return_value) + self.assertEqual(results['conversion_results']['AHCI.Integrated.1-1'], + expected_return_value) + + @mock.patch.object(dracclient.resources.raid.RAIDManagement, + 'list_physical_disks', spec_set=True, + autospec=True) + @mock.patch.object(dracclient.resources.raid.RAIDManagement, + 'convert_physical_disks', spec_set=True, + autospec=True, + side_effect=exceptions.DRACOperationFailed( + drac_messages="OTHER_MESSAGE")) + def test_change_physical_disk_state_raise_drac_operation_other( + self, mock_requests, + mock_convert_physical_disks, + mock_list_physical_disks): + mode = constants.RaidStatus.raid + disk_1_non_raid = self.disk_1._replace(raid_status='non-RAID') + disk_2_non_raid = self.disk_2._replace(raid_status='non-RAID') + physical_disks = [disk_1_non_raid, disk_2_non_raid, + self.disk_3, self.disk_4] + mock_list_physical_disks.return_value = physical_disks + self.assertRaisesRegexp( + exceptions.DRACOperationFailed, + "OTHER_MESSAGE", + self.drac_client.change_physical_disk_state, + mode, + self.controllers_to_physical_disk_ids) + + @mock.patch.object(dracclient.resources.raid.RAIDManagement, + 'list_physical_disks', spec_set=True, + autospec=True) + @mock.patch.object(dracclient.resources.raid.RAIDManagement, + 'convert_physical_disks', spec_set=True, + autospec=True, side_effect=Exception( + "SOMETHING_BAD_HAPPENED")) + def test_change_physical_disk_state_raise_other( + self, mock_requests, + mock_convert_physical_disks, + mock_list_physical_disks): + mode = constants.RaidStatus.raid + disk_1_non_raid = self.disk_1._replace(raid_status='non-RAID') + disk_2_non_raid = self.disk_2._replace(raid_status='non-RAID') + physical_disks = [disk_1_non_raid, disk_2_non_raid, + self.disk_3, self.disk_4] + mock_list_physical_disks.return_value = physical_disks + self.assertRaisesRegexp( + Exception, + "SOMETHING_BAD_HAPPENED", + self.drac_client.change_physical_disk_state, + mode, + self.controllers_to_physical_disk_ids) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + @mock.patch.object(dracclient.resources.raid.RAIDManagement, + 'list_physical_disks', spec_set=True, + autospec=True) + @mock.patch.object(dracclient.resources.raid.RAIDManagement, + 'convert_physical_disks', spec_set=True, + autospec=True) + def test_change_physical_disk_state_with_no_dict( + self, mock_requests, + mock_convert_physical_disks, + mock_list_physical_disks, + mock_wait_until_idrac_is_ready): + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.RAIDEnumerations[uris.DCIM_ControllerView]['ok']) + mode = constants.RaidStatus.jbod + physical_disks = [self.disk_1, self.disk_2, self.disk_3, self.disk_4] + mock_list_physical_disks.return_value = physical_disks + cvt_phys_disks_return_value = {'is_commit_required': True, + 'is_reboot_required': constants. + RebootRequired.true} + mock_convert_physical_disks.return_value = cvt_phys_disks_return_value + expected_return_value = {'RAID.Integrated.1-1': + cvt_phys_disks_return_value, + 'AHCI.Integrated.1-1': + cvt_phys_disks_return_value} + results = self.drac_client.change_physical_disk_state(mode) + self.assertDictEqual(results['conversion_results'], + expected_return_value) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + @mock.patch.object(dracclient.resources.raid.RAIDManagement, + 'list_physical_disks', spec_set=True, + autospec=True) + def test_change_physical_disk_state_with_no_raid_or_boss_card_match( + self, mock_requests, + mock_list_physical_disks, + mock_wait_until_idrac_is_ready): + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.RAIDEnumerations[uris.DCIM_ControllerView]['ok']) + mode = constants.RaidStatus.jbod + _disk_1 = self.disk_1._replace(controller='NOT_RAID.Integrated.1-1') + _disk_2 = self.disk_2._replace(controller='NOT_RAID.Integrated.1-1') + _disk_3 = self.disk_3._replace(controller='NOT_AHCI.Integrated.1-1') + _disk_4 = self.disk_4._replace(controller='NOT_AHCI.Integrated.1-1') + physical_disks = [_disk_1, _disk_2, _disk_3, _disk_4] + mock_list_physical_disks.return_value = physical_disks + results = self.drac_client.change_physical_disk_state(mode) + self.assertDictEqual(results['conversion_results'], {}) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_is_realtime_supported_with_realtime_controller( + self, + mock_requests, + mock_wait_until_idrac_is_ready): + expected_raid_controller = 'RAID.Integrated.1-1' + + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.RAIDEnumerations[uris.DCIM_ControllerView]['ok']) + + self.assertTrue( + self.drac_client.is_realtime_supported( + expected_raid_controller)) + + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_is_realtime_supported_with_non_realtime_controller( + self, + mock_requests, + mock_wait_until_idrac_is_ready): + expected_raid_controller = 'AHCI.Integrated.1-1' + + mock_requests.post( + 'https://1.2.3.4:443/wsman', + text=test_utils.RAIDEnumerations[uris.DCIM_ControllerView]['ok']) + + self.assertFalse( + self.drac_client.is_realtime_supported( + expected_raid_controller)) diff --git a/dracclient/tests/test_system.py b/dracclient/tests/test_system.py new file mode 100644 index 0000000..54c9d9b --- /dev/null +++ b/dracclient/tests/test_system.py @@ -0,0 +1,92 @@ +# +# 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. + +from unittest import mock + +import requests_mock + +import dracclient.client +from dracclient.resources import system +from dracclient.resources import uris +from dracclient.tests import base +from dracclient.tests import utils as test_utils + + +class ClientSystemConfigurationTestCase(base.BaseTest): + + def setUp(self): + super(ClientSystemConfigurationTestCase, self).setUp() + self.drac_client = dracclient.client.DRACClient( + **test_utils.FAKE_ENDPOINT) + + @requests_mock.Mocker() + @mock.patch.object(dracclient.client.WSManClient, + 'wait_until_idrac_is_ready', spec_set=True, + autospec=True) + def test_list_system_settings( + self, mock_requests, mock_wait_until_idrac_is_ready): + expected_enum_attr = system.SystemEnumerableAttribute( + name='ChassisLEDState', + instance_id='System.Embedded.1#ChassisPwrState.1#ChassisLEDState', # noqa + read_only=False, + current_value='Off', + pending_value=None, + fqdd='System.Embedded.1', + group_id='ChassisPwrState.1', + possible_values=['Unknown', 'Blinking', 'Off']) + expected_string_attr = system.SystemStringAttribute( + name='UserDefinedString', + instance_id='System.Embedded.1#LCD.1#UserDefinedString', + read_only=False, + current_value=None, + pending_value=None, + fqdd='System.Embedded.1', + group_id='LCD.1', + min_length=0, + max_length=62) + expected_integer_attr = system.SystemIntegerAttribute( + name='PowerCapValue', + instance_id='System.Embedded.1#ServerPwr.1#PowerCapValue', + read_only=False, + current_value=555, + pending_value=None, + fqdd='System.Embedded.1', + group_id='ServerPwr.1', + lower_bound=302, + upper_bound=578) + + mock_requests.post('https://1.2.3.4:443/wsman', [ + {'text': test_utils.SystemEnumerations[ + uris.DCIM_SystemEnumeration]['ok']}, + {'text': test_utils.SystemEnumerations[ + uris.DCIM_SystemString]['ok']}, + {'text': test_utils.SystemEnumerations[ + uris.DCIM_SystemInteger]['ok']}]) + + system_settings = self.drac_client.list_system_settings() + + self.assertEqual(44, len(system_settings)) + # enumerable attribute + self.assertIn('System.Embedded.1#ChassisPwrState.1#ChassisLEDState', + system_settings) + self.assertEqual(expected_enum_attr, system_settings[ + 'System.Embedded.1#ChassisPwrState.1#ChassisLEDState']) # noqa + # string attribute + self.assertIn('System.Embedded.1#LCD.1#UserDefinedString', + system_settings) + self.assertEqual(expected_string_attr, system_settings[ + 'System.Embedded.1#LCD.1#UserDefinedString']) + self.assertIn('System.Embedded.1#ServerPwr.1#PowerCapValue', + system_settings) + self.assertEqual(expected_integer_attr, + system_settings['System.Embedded.1#ServerPwr.1#PowerCapValue']) # noqa diff --git a/dracclient/tests/test_utils.py b/dracclient/tests/test_utils.py index e99db8b..171d551 100644 --- a/dracclient/tests/test_utils.py +++ b/dracclient/tests/test_utils.py @@ -27,6 +27,28 @@ class UtilsTestCase(base.BaseTest): def setUp(self): super(UtilsTestCase, self).setUp() + def test__is_attr_non_nil_True(self): + doc = etree.fromstring( + test_utils.RAIDEnumerations[ + uris.DCIM_ControllerView]['ok']) + controllers = utils.find_xml(doc, 'DCIM_ControllerView', + uris.DCIM_ControllerView, find_all=True) + version = utils.find_xml(controllers[0], 'Bus', + uris.DCIM_ControllerView) + + self.assertTrue(utils._is_attr_non_nil(version)) + + def test__is_attr_non_nil_False(self): + doc = etree.fromstring( + test_utils.RAIDEnumerations[ + uris.DCIM_ControllerView]['ok']) + controllers = utils.find_xml(doc, 'DCIM_ControllerView', + uris.DCIM_ControllerView, find_all=True) + version = utils.find_xml(controllers[0], 'DriverVersion', + uris.DCIM_ControllerView) + + self.assertFalse(utils._is_attr_non_nil(version)) + def test_get_wsman_resource_attr(self): doc = etree.fromstring( test_utils.InventoryEnumerations[uris.DCIM_CPUView]['ok']) @@ -79,3 +101,75 @@ def test_get_wsman_resource_attr_missing_text(self): exceptions.DRACEmptyResponseField, re.escape(expected_message), utils.get_wsman_resource_attr, cpus[0], uris.DCIM_CPUView, 'HyperThreadingEnabled', allow_missing=False) + + def test_get_wsman_resource_attr_missing_text_allowed(self): + doc = etree.fromstring( + test_utils.RAIDEnumerations[ + uris.DCIM_ControllerView]['ok']) + controllers = utils.find_xml(doc, 'DCIM_ControllerView', + uris.DCIM_ControllerView, find_all=True) + + result = utils.get_wsman_resource_attr( + controllers[0], uris.DCIM_ControllerView, 'DriverVersion', + allow_missing=False, nullable=True) + self.assertIsNone(result) + + def test_get_all_wsman_resource_attrs(self): + doc = etree.fromstring( + test_utils.RAIDEnumerations[uris.DCIM_VirtualDiskView]['ok']) + vdisks = utils.find_xml(doc, 'DCIM_VirtualDiskView', + uris.DCIM_VirtualDiskView, find_all=True) + + vals = utils.get_all_wsman_resource_attrs( + vdisks[0], uris.DCIM_VirtualDiskView, 'PhysicalDiskIDs') + + expected_pdisks = [ + 'Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1', + 'Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1' + ] + self.assertListEqual(expected_pdisks, vals) + + def test_get_all_wsman_resource_attrs_missing_attr_allowed(self): + doc = etree.fromstring( + test_utils.InventoryEnumerations[ + uris.DCIM_CPUView]['missing_flags']) + cpus = utils.find_xml(doc, 'DCIM_CPUView', uris.DCIM_CPUView, + find_all=True) + + vals = utils.get_all_wsman_resource_attrs( + cpus[0], uris.DCIM_CPUView, 'HyperThreadingEnabled') + + self.assertListEqual([], vals) + + def test_get_all_wsman_resource_attrs_missing_text(self): + expected_message = ("Attribute 'HyperThreadingEnabled' is not nullable" + ", but no value received") + doc = etree.fromstring( + test_utils.InventoryEnumerations[ + uris.DCIM_CPUView]['empty_flag']) + cpus = utils.find_xml(doc, 'DCIM_CPUView', uris.DCIM_CPUView, + find_all=True) + + self.assertRaisesRegexp( + exceptions.DRACEmptyResponseField, re.escape(expected_message), + utils.get_all_wsman_resource_attrs, cpus[0], uris.DCIM_CPUView, + 'HyperThreadingEnabled') + + def test_get_all_wsman_resource_attrs_missing_text_allowed(self): + doc = etree.fromstring( + test_utils.RAIDEnumerations[ + uris.DCIM_ControllerView]['ok']) + controllers = utils.find_xml(doc, 'DCIM_ControllerView', + uris.DCIM_ControllerView, find_all=True) + + result = utils.get_all_wsman_resource_attrs( + controllers[0], uris.DCIM_ControllerView, 'DriverVersion', + nullable=True) + self.assertEqual(result, []) + + def test_build_return_dict_fail(self): + self.assertRaises(exceptions.InvalidParameterValue, + utils.build_return_dict, + doc=None, + resource_uri=None, + is_reboot_required_value='foo') diff --git a/dracclient/tests/test_wsman.py b/dracclient/tests/test_wsman.py index 09f7701..c0d6ea5 100644 --- a/dracclient/tests/test_wsman.py +++ b/dracclient/tests/test_wsman.py @@ -12,12 +12,14 @@ # under the License. import collections +from unittest import mock import uuid import lxml.etree import lxml.objectify -import mock +import requests.exceptions import requests_mock +import six from dracclient import exceptions from dracclient.tests import base @@ -54,6 +56,14 @@ def test_enumerate_with_invalid_status_code(self, mock_requests): self.assertRaises(exceptions.WSManInvalidResponse, self.client.enumerate, 'resource') + @requests_mock.Mocker() + def test_enumerate_with_invalid_utf8(self, mock_requests): + mock_requests.post('https://1.2.3.4:443/wsman', + content=six.b('yay!\xC0')) + + resp = self.client.enumerate('resource') + self.assertEqual('yay!', resp.text) + @requests_mock.Mocker() def test_enumerate_with_auto_pull(self, mock_requests): mock_requests.post( @@ -68,7 +78,7 @@ def test_enumerate_with_auto_pull(self, mock_requests): foo_resource_uri = 'http://FooResource' bar_resource_uri = 'http://BarResource' self.assertEqual( - 3, len(resp_xml.findall('.//{%s}FooResource' % foo_resource_uri))) + 4, len(resp_xml.findall('.//{%s}FooResource' % foo_resource_uri))) self.assertEqual( 1, len(resp_xml.findall('.//{%s}BazResource' % bar_resource_uri))) self.assertEqual( @@ -108,6 +118,74 @@ def test_invoke(self, mock_requests): self.assertEqual('yay!', resp.text) + @requests_mock.Mocker() + def test_invoke_with_ssl_errors(self, mock_requests): + mock_requests.post('https://1.2.3.4:443/wsman', + exc=requests.exceptions.SSLError) + + self.assertRaises(exceptions.WSManRequestFailure, + self.client.invoke, 'http://resource', 'method', + {'selector': 'foo'}, {'property': 'bar'}) + + @requests_mock.Mocker() + def test_invoke_with_ssl_error_success(self, mock_requests): + expected_resp = 'yay!' + mock_requests.post('https://1.2.3.4:443/wsman', + [{'exc': requests.exceptions.SSLError}, + {'text': expected_resp}]) + + resp = self.client.invoke('http://resource', 'method', + {'selector': 'foo'}, {'property': 'bar'}) + + self.assertEqual('yay!', resp.text) + + @requests_mock.Mocker() + def test_invoke_with_connection_errors(self, mock_requests): + mock_requests.post('https://1.2.3.4:443/wsman', + exc=requests.exceptions.ConnectionError) + + self.assertRaises(exceptions.WSManRequestFailure, + self.client.invoke, 'http://resource', 'method', + {'selector': 'foo'}, {'property': 'bar'}) + + @requests_mock.Mocker() + def test_invoke_with_connection_error_success(self, mock_requests): + expected_resp = 'yay!' + mock_requests.post('https://1.2.3.4:443/wsman', + [{'exc': requests.exceptions.ConnectionError}, + {'text': expected_resp}]) + + resp = self.client.invoke('http://resource', 'method', + {'selector': 'foo'}, {'property': 'bar'}) + + self.assertEqual('yay!', resp.text) + + @requests_mock.Mocker() + def test_invoke_with_unknown_error(self, mock_requests): + mock_requests.post('https://1.2.3.4:443/wsman', + exc=requests.exceptions.HTTPError) + self.assertRaises(exceptions.WSManRequestFailure, + self.client.invoke, 'http://resource', 'method', + {'selector': 'foo'}, {'property': 'bar'}) + + @requests_mock.Mocker() + @mock.patch('time.sleep', autospec=True) + def test_client_retry_delay(self, mock_requests, mock_ts): + ssl_retry_delay = 5 + fake_endpoint = test_utils.FAKE_ENDPOINT.copy() + fake_endpoint['ssl_retry_delay'] = ssl_retry_delay + client = dracclient.wsman.Client(**fake_endpoint) + expected_resp = 'yay!' + mock_requests.post('https://1.2.3.4:443/wsman', + [{'exc': requests.exceptions.SSLError}, + {'text': expected_resp}]) + + resp = client.invoke('http://resource', 'method', + {'selector': 'foo'}, {'property': 'bar'}) + + self.assertEqual('yay!', resp.text) + mock_ts.assert_called_once_with(ssl_retry_delay) + class PayloadTestCase(base.BaseTest): diff --git a/dracclient/tests/utils.py b/dracclient/tests/utils.py index 1adcf8f..4e4ee11 100644 --- a/dracclient/tests/utils.py +++ b/dracclient/tests/utils.py @@ -29,11 +29,12 @@ def load_wsman_xml(name): """Helper function to load a WSMan XML response from a file.""" with open(os.path.join(os.path.dirname(__file__), 'wsman_mocks', - '%s.xml' % name), 'r') as f: + '%s.xml' % name), 'r') as f: xml_body = f.read() return xml_body + WSManEnumerations = { 'context': [ load_wsman_xml('wsman-enum_context-1'), @@ -132,6 +133,53 @@ def load_wsman_xml(name): 'error': load_wsman_xml( 'bios_service-invoke-delete_pending_configuration-error'), }, + }, + uris.DCIM_LCService: { + 'CreateConfigJob': { + 'ok': load_wsman_xml( + 'lc_service-invoke-create_config_job-ok'), + 'error': load_wsman_xml( + 'lc_service-invoke-create_config_job-error'), + }, + } +} + +JobService = { + uris.DCIM_JobService: { + 'DeleteJobQueue': { + 'ok': load_wsman_xml( + 'job_service-delete-job-id-ok'), + 'error': load_wsman_xml( + 'job_service-delete-job-id-error'), + } + } +} + +iDracCardEnumerations = { + uris.DCIM_iDRACCardEnumeration: { + 'ok': load_wsman_xml('idraccard_enumeration-enum-ok') + }, + uris.DCIM_iDRACCardString: { + 'ok': load_wsman_xml('idraccard_string-enum-ok') + }, + uris.DCIM_iDRACCardInteger: { + 'ok': load_wsman_xml('idraccard_integer-enum-ok') + }, +} + +iDracCardInvocations = { + uris.DCIM_iDRACCardService: { + 'SetAttributes': { + 'ok': load_wsman_xml( + 'idrac_service-invoke-set_attributes-ok') + }, + 'iDRACReset': { + 'ok': load_wsman_xml( + 'idrac_service-reset-ok'), + 'error': load_wsman_xml( + 'idrac_service-reset-error') + } + } } @@ -139,6 +187,55 @@ def load_wsman_xml(name): uris.DCIM_SystemView: { 'ok': load_wsman_xml('system_view-enum-ok') }, + uris.DCIM_LCEnumeration: { + 'ok': load_wsman_xml('lc_enumeration-enum-ok') + }, + uris.DCIM_LCString: { + 'ok': load_wsman_xml('lc_string-enum-ok') + } +} + +LifecycleControllerInvocations = { + uris.DCIM_LCService: { + 'GetRemoteServicesAPIStatus': { + 'is_ready': load_wsman_xml('lc_getremoteservicesapistatus_ready'), + 'is_not_ready': load_wsman_xml( + 'lc_getremoteservicesapistatus_not_ready'), + 'is_recovery': load_wsman_xml( + 'lc_getremoteservicesapistatus_recovery'), + }, + 'SetAttributes': { + 'ok': load_wsman_xml( + 'lc_service-invoke-set_attributes-ok'), + 'error': load_wsman_xml( + 'lc_service-invoke-set_attributes-error'), + } + } +} + +NICEnumerations = { + uris.DCIM_NICEnumeration: { + 'ok': load_wsman_xml('nic_enumeration-enum-ok'), + }, + uris.DCIM_NICString: { + 'ok': load_wsman_xml('nic_string-enum-ok'), + # this duplicates the LinkStatus from nic_enumeration-enum-ok + 'colliding': load_wsman_xml('nic_string-enum-colliding'), + }, + uris.DCIM_NICInteger: { + 'ok': load_wsman_xml('nic_integer-enum-ok') + }, +} + +NICInvocations = { + uris.DCIM_NICService: { + 'SetAttributes': { + 'ok': load_wsman_xml( + 'nic_service-invoke-set_attributes-ok'), + 'error': load_wsman_xml( + 'nic_service-invoke-set_attributes-error'), + } + }, } RAIDEnumerations = { @@ -149,7 +246,18 @@ def load_wsman_xml(name): 'ok': load_wsman_xml('physical_disk_view-enum-ok') }, uris.DCIM_VirtualDiskView: { + 'Raid_Status_ok': load_wsman_xml( + 'virtual_disk_view-enum-with-raid-status-ok'), 'ok': load_wsman_xml('virtual_disk_view-enum-ok') + }, + uris.DCIM_RAIDEnumeration: { + 'ok': load_wsman_xml('raid_enumeration-enum-ok') + }, + uris.DCIM_RAIDString: { + 'ok': load_wsman_xml('raid_string-enum-ok') + }, + uris.DCIM_RAIDInteger: { + 'ok': load_wsman_xml('raid_integer-enum-ok') } } @@ -172,6 +280,40 @@ def load_wsman_xml(name): 'raid_service-invoke-convert_physical_disks-ok'), 'error': load_wsman_xml( 'raid_service-invoke-convert_physical_disks-error'), + }, + 'ResetConfig': { + 'ok': load_wsman_xml( + 'raid_service-invoke-reset_raid_config-ok'), + 'error': load_wsman_xml( + 'raid_service-invoke-reset_raid_config-error'), + }, + 'ClearForeignConfig': { + 'ok': load_wsman_xml( + 'raid_service-invoke-clear_foreign_config-ok'), + 'no_foreign_drive': load_wsman_xml( + 'raid_service-invoke-clear_foreign_config-no_foreign_drive'), + 'invalid_controller_id': load_wsman_xml( + 'raid_service-invoke-clear_foreign_config-invalid_controller'), + 'foreign_drive_operation_not_supported': load_wsman_xml( + 'raid_service-invoke-clear_foreign_config-not_supported'), + }, + 'SetAttributes': { + 'ok': load_wsman_xml( + 'raid_service-invoke-set_attributes-ok'), + 'error': load_wsman_xml( + 'raid_service-invoke-set_attributes-error'), } } } + +SystemEnumerations = { + uris.DCIM_SystemEnumeration: { + 'ok': load_wsman_xml('system_enumeration-enum-ok'), + }, + uris.DCIM_SystemString: { + 'ok': load_wsman_xml('system_string-enum-ok'), + }, + uris.DCIM_SystemInteger: { + 'ok': load_wsman_xml('system_integer-enum-ok'), + } +} diff --git a/dracclient/tests/wsman_mocks/bios_enumeration-enum-ok.xml b/dracclient/tests/wsman_mocks/bios_enumeration-enum-ok.xml index 6804d46..f817041 100644 --- a/dracclient/tests/wsman_mocks/bios_enumeration-enum-ok.xml +++ b/dracclient/tests/wsman_mocks/bios_enumeration-enum-ok.xml @@ -202,13 +202,13 @@ Logical Processor Idling DynamicCoreAllocation Disabled - - 421 + <Dep><AttrLev Op="OR"><ROIf Name="ProcPwrPerf">MaxPerf</ROIf></AttrLev></Dep> + 5817 BIOS.Setup.1-1 Processor Settings ProcSettings BIOS.Setup.1-1:DynamicCoreAllocation - false + true Enabled Disabled @@ -1492,4 +1492,4 @@ - \ No newline at end of file + diff --git a/dracclient/tests/wsman_mocks/controller_view-enum-ok.xml b/dracclient/tests/wsman_mocks/controller_view-enum-ok.xml index 74c6488..069a0d8 100644 --- a/dracclient/tests/wsman_mocks/controller_view-enum-ok.xml +++ b/dracclient/tests/wsman_mocks/controller_view-enum-ok.xml @@ -43,6 +43,7 @@ 0 1 PERC H710 Mini + 1 1 5B083FE0D2D0F200 1 @@ -52,9 +53,49 @@ 0 0 + + 2 + 512 + 1 + 2.5.13.2009 + 1 + Unknown + DELL + 2 + Unknown + AHCI.Integrated.1-1 + + 1 + 0 + AHCI.Integrated.1-1 + 0 + AHCI.Integrated.1-1 + + 20150226175957.000000+000 + 20150226175950.000000+000 + Generation 2 + Generation 3 + 5B + 1 + 1F38 + 1028 + 1000 + 0 + 1 + BOSS-S1 + 0 + 1 + 5B083FE0D2D0F201 + 1 + 1 + 1 + 1 + 0 + 0 + - \ No newline at end of file + diff --git a/dracclient/tests/wsman_mocks/idrac_service-invoke-set_attributes-ok.xml b/dracclient/tests/wsman_mocks/idrac_service-invoke-set_attributes-ok.xml new file mode 100644 index 0000000..3f52ea8 --- /dev/null +++ b/dracclient/tests/wsman_mocks/idrac_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_iDRACCardService/SetAttributesResponse + uuid:305ed6f4-2269-43c5-8c28-00b85e81099d + uuid:683c34bc-53c4-13c4-8064-17c1f0d9bed4 + + + + The command was successful + RAC001 + No + 0 + Set PendingValue + + + diff --git a/dracclient/tests/wsman_mocks/idrac_service-reset-error.xml b/dracclient/tests/wsman_mocks/idrac_service-reset-error.xml new file mode 100644 index 0000000..9cc45d4 --- /dev/null +++ b/dracclient/tests/wsman_mocks/idrac_service-reset-error.xml @@ -0,0 +1,22 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + + http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_iDRACCardService/iDRACResetResponse + + uuid:a65ce3df-3690-42dd-af45-5c1f2cd0793b + + uuid:e8f2cbe0-6fd0-1fd0-8057-dc9c046694d0 + + + + + Invalid parameter value for Force + Force + RAC004 + 2 + + + \ No newline at end of file diff --git a/dracclient/tests/wsman_mocks/idrac_service-reset-ok.xml b/dracclient/tests/wsman_mocks/idrac_service-reset-ok.xml new file mode 100644 index 0000000..4b1eda0 --- /dev/null +++ b/dracclient/tests/wsman_mocks/idrac_service-reset-ok.xml @@ -0,0 +1,22 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + + http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_iDRACCardService/iDRACResetResponse + + uuid:a4a1cd1a-7c10-4dfc-98d9-d0cc2cd7c80c + + uuid:6f9ecf40-6fd1-1fd1-a60b-dc9c046694d0 + + + + + iDRAC was successfully reset. + RAC064 + 0 + + + + diff --git a/dracclient/tests/wsman_mocks/idraccard_enumeration-enum-ok.xml b/dracclient/tests/wsman_mocks/idraccard_enumeration-enum-ok.xml new file mode 100644 index 0000000..35bc8b9 --- /dev/null +++ b/dracclient/tests/wsman_mocks/idraccard_enumeration-enum-ok.xml @@ -0,0 +1,4393 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + uuid:d3870438-c87e-40e7-ad98-ab5fd4fe6279 + uuid:a841c777-40aa-10aa-821b-de7e4e771814 + + + + + + iDRAC Type + Type + 13G Monolithic + 12G/13G + + 6 + iDRAC.Embedded.2 + RAC Information + Info.1 + iDRAC.Embedded.2#Info.1#Type + true + + 12G/13G + 12G Monolithic + 12G Modular + 13G Monolithic + 13G Modular + 12G DCS + 13G DCS + + + iDRAC Type + Type + 13G Monolithic + 12G/13G + + 6 + iDRAC.Embedded.1 + RAC Information + Info.1 + iDRAC.Embedded.1#Info.1#Type + true + + 12G/13G + 12G Monolithic + 12G Modular + 13G Monolithic + 13G Modular + 12G DCS + 13G DCS + + + NIC Enable + Enable + Enabled + Enabled + + 51 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#Enable + false + + Disabled + Enabled + + + NIC Selection + Selection + Dedicated + Dedicated + + 53 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#Selection + false + + Dedicated + LOM1 + LOM2 + LOM3 + LOM4 + + + NIC Failover + Failover + None + None + + 54 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#Failover + false + + None + + + NIC Speed + Speed + 1000 + 100 + + 56 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#Speed + false + + 10 + 100 + 1000 + + + NIC Auto Negotiation + Autoneg + Enabled + Enabled + + 55 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#Autoneg + false + + Disabled + Enabled + + + NIC Duplex + Duplex + Full + Full + + 57 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#Duplex + false + + Half + Full + + + DNS Register RAC + DNSRegister + Disabled + Disabled + + 60 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#DNSRegister + false + + Disabled + Enabled + + + DNS Domain Name from DHCP + DNSDomainFromDHCP + Disabled + Disabled + + 180 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#DNSDomainFromDHCP + false + + Disabled + Enabled + + + Enable VLAN + VLanEnable + Disabled + Disabled + + 63 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#VLanEnable + false + + Disabled + Enabled + + + DNS Domain Name from DHCP + DNSDomainNameFromDHCP + Disabled + Disabled + + 180 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#DNSDomainNameFromDHCP + false + + Disabled + Enabled + + + Auto NIC Enable + AutoDetect + Disabled + Disabled + + 66 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#AutoDetect + false + + Disabled + Enabled + + + Auto Configuration enable + AutoConfig + Disabled + Disabled + + 69 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#AutoConfig + false + + Disabled + Enable Once + Enable Once After Reset + + + VLan port + VLanPort + Both + Both + + 70 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#VLanPort + false + + Both + Dedicated port only + LOM ports only + + + Active NIC Interface + ActiveNIC + Dedicated + Dedicated + + 71 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#ActiveNIC + true + + No LOM Active + LOM1 + LOM2 + LOM3 + LOM4 + Dedicated + Unknown + + + Active NIC Link Status + LinkStatus + LinkPresent + NoLink + + 72 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#LinkStatus + true + + NoLink + LinkPresent + + + Active NIC Link Speed + LinkSpeed + 1Gbps + 100Mbps + + 73 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#LinkSpeed + true + + 10Mbps + 100Mbps + 1Gbps + Unknown + + + Active NIC Link Mode + LinkMode + FullDuplex + FullDuplex + + 74 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#LinkMode + true + + HalfDuplex + FullDuplex + Unknown + + + Auto Dedicated NIC + AutoDedicatedNIC + Disabled + Disabled + + 75 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#AutoDedicatedNIC + false + + Disabled + Enabled + + + IPv4 Enable + Enable + Enabled + Enabled + + 101 + iDRAC.Embedded.1 + IPv4 Information + IPv4.1 + iDRAC.Embedded.1#IPv4.1#Enable + false + + Disabled + Enabled + + + IPv4 DHCP Enable + DHCPEnable + Disabled + Disabled + + 102 + iDRAC.Embedded.1 + IPv4 Information + IPv4.1 + iDRAC.Embedded.1#IPv4.1#DHCPEnable + false + + Disabled + Enabled + + + DNS Servers From DHCP + DNSFromDHCP + Disabled + Disabled + + 106 + iDRAC.Embedded.1 + IPv4 Information + IPv4.1 + iDRAC.Embedded.1#IPv4.1#DNSFromDHCP + false + + Disabled + Enabled + + + IPV6 Enable + Enable + Disabled + Disabled + + 151 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#Enable + false + + Disabled + Enabled + + + IPV6 Auto Config + AutoConfig + Enabled + Enabled + + 152 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#AutoConfig + false + + Disabled + Enabled + + + DNS Server From DHCP6 + DNSFromDHCP6 + Disabled + Disabled + + 153 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#DNSFromDHCP6 + false + + Disabled + Enabled + + + Address State + AddressState + Disabled + Active + + 175 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#AddressState + true + + Active + Disabled + Pending + Failed + Deprecated + Invalid + + + DNS Domain Name from DHCP + DNSDomainFromDHCP + Disabled + Disabled + + 183 + iDRAC.Embedded.1 + NIC Static Information + NICStatic.1 + iDRAC.Embedded.1#NICStatic.1#DNSDomainFromDHCP + false + + Disabled + Enabled + + + DNS Servers From DHCP + DNSFromDHCP + Disabled + Disabled + + 190 + iDRAC.Embedded.1 + IPv4 Static Information + IPv4Static.1 + iDRAC.Embedded.1#IPv4Static.1#DNSFromDHCP + false + + Disabled + Enabled + + + DNS Server From DHCP6 + DNSFromDHCP6 + Disabled + Disabled + + 196 + iDRAC.Embedded.1 + IPv6 Static Information + IPv6Static.1 + iDRAC.Embedded.1#IPv6Static.1#DNSFromDHCP6 + false + + Disabled + Enabled + + + Enable or Disable IPMI over LAN + Enable + Disabled + Disabled + + 201 + iDRAC.Embedded.1 + IPMI LAN Information + IPMILan.1 + iDRAC.Embedded.1#IPMILan.1#Enable + false + + Disabled + Enabled + + + Privilege Limit + PrivLimit + Administrator + Administrator + + 202 + iDRAC.Embedded.1 + IPMI LAN Information + IPMILan.1 + iDRAC.Embedded.1#IPMILan.1#PrivLimit + false + + User + Operator + Administrator + + + Enable or Disable Alerts over LAN + AlertEnable + Disabled + Disabled + + 205 + iDRAC.Embedded.1 + IPMI LAN Information + IPMILan.1 + iDRAC.Embedded.1#IPMILan.1#AlertEnable + false + + Disabled + Enabled + + + User Admin IPMI LAN Privilege + IpmiLanPrivilege + No Access + No Access + + 254 + iDRAC.Embedded.1 + iDRAC Users + Users.1 + iDRAC.Embedded.1#Users.1#IpmiLanPrivilege + true + + User + Operator + Administrator + No Access + + + User Admin IPMI Serial Privilege + IpmiSerialPrivilege + No Access + No Access + + 255 + iDRAC.Embedded.1 + iDRAC Users + Users.1 + iDRAC.Embedded.1#Users.1#IpmiSerialPrivilege + true + + User + Operator + Administrator + No Access + + + User Admin Enable + Enable + Disabled + Disabled + + 256 + iDRAC.Embedded.1 + iDRAC Users + Users.1 + iDRAC.Embedded.1#Users.1#Enable + true + + Disabled + Enabled + + + User Admin SOL Enable + SolEnable + Disabled + Disabled + + 257 + iDRAC.Embedded.1 + iDRAC Users + Users.1 + iDRAC.Embedded.1#Users.1#SolEnable + true + + Disabled + Enabled + + + SNMP V3 Protocol Enable + ProtocolEnable + Disabled + Disabled + + 258 + iDRAC.Embedded.1 + iDRAC Users + Users.1 + iDRAC.Embedded.1#Users.1#ProtocolEnable + true + + Disabled + Enabled + + + SNMP V3 Authentication Protocol + AuthenticationProtocol + SHA + SHA + + 259 + iDRAC.Embedded.1 + iDRAC Users + Users.1 + iDRAC.Embedded.1#Users.1#AuthenticationProtocol + true + + None + MD5 + SHA + + + SNMP V3 Privacy Protocol + PrivacyProtocol + AES + AES + + 260 + iDRAC.Embedded.1 + iDRAC Users + Users.1 + iDRAC.Embedded.1#Users.1#PrivacyProtocol + true + + None + DES + AES + + + User Admin IPMI LAN Privilege + IpmiLanPrivilege + Administrator + Administrator + + 264 + iDRAC.Embedded.1 + iDRAC Users + Users.2 + iDRAC.Embedded.1#Users.2#IpmiLanPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin IPMI Serial Privilege + IpmiSerialPrivilege + Administrator + Administrator + + 265 + iDRAC.Embedded.1 + iDRAC Users + Users.2 + iDRAC.Embedded.1#Users.2#IpmiSerialPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin Enable + Enable + Enabled + Disabled + + 266 + iDRAC.Embedded.1 + iDRAC Users + Users.2 + iDRAC.Embedded.1#Users.2#Enable + false + + Disabled + Enabled + + + User Admin SOL Enable + SolEnable + Enabled + Disabled + + 267 + iDRAC.Embedded.1 + iDRAC Users + Users.2 + iDRAC.Embedded.1#Users.2#SolEnable + false + + Disabled + Enabled + + + SNMP V3 Protocol Enable + ProtocolEnable + Disabled + Disabled + + 268 + iDRAC.Embedded.1 + iDRAC Users + Users.2 + iDRAC.Embedded.1#Users.2#ProtocolEnable + false + + Disabled + Enabled + + + SNMP V3 Authentication Protocol + AuthenticationProtocol + SHA + SHA + + 269 + iDRAC.Embedded.1 + iDRAC Users + Users.2 + iDRAC.Embedded.1#Users.2#AuthenticationProtocol + false + + None + MD5 + SHA + + + SNMP V3 Privacy Protocol + PrivacyProtocol + AES + AES + + 270 + iDRAC.Embedded.1 + iDRAC Users + Users.2 + iDRAC.Embedded.1#Users.2#PrivacyProtocol + false + + None + DES + AES + + + User Admin IPMI LAN Privilege + IpmiLanPrivilege + Administrator + No Access + + 274 + iDRAC.Embedded.1 + iDRAC Users + Users.3 + iDRAC.Embedded.1#Users.3#IpmiLanPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin IPMI Serial Privilege + IpmiSerialPrivilege + No Access + No Access + + 275 + iDRAC.Embedded.1 + iDRAC Users + Users.3 + iDRAC.Embedded.1#Users.3#IpmiSerialPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin Enable + Enable + Enabled + Disabled + + 276 + iDRAC.Embedded.1 + iDRAC Users + Users.3 + iDRAC.Embedded.1#Users.3#Enable + false + + Disabled + Enabled + + + User Admin SOL Enable + SolEnable + Disabled + Disabled + + 277 + iDRAC.Embedded.1 + iDRAC Users + Users.3 + iDRAC.Embedded.1#Users.3#SolEnable + false + + Disabled + Enabled + + + SNMP V3 Protocol Enable + ProtocolEnable + Disabled + Disabled + + 278 + iDRAC.Embedded.1 + iDRAC Users + Users.3 + iDRAC.Embedded.1#Users.3#ProtocolEnable + false + + Disabled + Enabled + + + SNMP V3 Authentication Protocol + AuthenticationProtocol + SHA + SHA + + 279 + iDRAC.Embedded.1 + iDRAC Users + Users.3 + iDRAC.Embedded.1#Users.3#AuthenticationProtocol + false + + None + MD5 + SHA + + + SNMP V3 Privacy Protocol + PrivacyProtocol + AES + AES + + 280 + iDRAC.Embedded.1 + iDRAC Users + Users.3 + iDRAC.Embedded.1#Users.3#PrivacyProtocol + false + + None + DES + AES + + + User Admin IPMI LAN Privilege + IpmiLanPrivilege + No Access + No Access + + 284 + iDRAC.Embedded.1 + iDRAC Users + Users.4 + iDRAC.Embedded.1#Users.4#IpmiLanPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin IPMI Serial Privilege + IpmiSerialPrivilege + No Access + No Access + + 285 + iDRAC.Embedded.1 + iDRAC Users + Users.4 + iDRAC.Embedded.1#Users.4#IpmiSerialPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin Enable + Enable + Enabled + Disabled + + 286 + iDRAC.Embedded.1 + iDRAC Users + Users.4 + iDRAC.Embedded.1#Users.4#Enable + false + + Disabled + Enabled + + + User Admin SOL Enable + SolEnable + Disabled + Disabled + + 287 + iDRAC.Embedded.1 + iDRAC Users + Users.4 + iDRAC.Embedded.1#Users.4#SolEnable + false + + Disabled + Enabled + + + SNMP V3 Protocol Enable + ProtocolEnable + Disabled + Disabled + + 288 + iDRAC.Embedded.1 + iDRAC Users + Users.4 + iDRAC.Embedded.1#Users.4#ProtocolEnable + false + + Disabled + Enabled + + + SNMP V3 Authentication Protocol + AuthenticationProtocol + SHA + SHA + + 289 + iDRAC.Embedded.1 + iDRAC Users + Users.4 + iDRAC.Embedded.1#Users.4#AuthenticationProtocol + false + + None + MD5 + SHA + + + SNMP V3 Privacy Protocol + PrivacyProtocol + AES + AES + + 290 + iDRAC.Embedded.1 + iDRAC Users + Users.4 + iDRAC.Embedded.1#Users.4#PrivacyProtocol + false + + None + DES + AES + + + User Admin IPMI LAN Privilege + IpmiLanPrivilege + No Access + No Access + + 294 + iDRAC.Embedded.1 + iDRAC Users + Users.5 + iDRAC.Embedded.1#Users.5#IpmiLanPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin IPMI Serial Privilege + IpmiSerialPrivilege + No Access + No Access + + 295 + iDRAC.Embedded.1 + iDRAC Users + Users.5 + iDRAC.Embedded.1#Users.5#IpmiSerialPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin Enable + Enable + Disabled + Disabled + + 296 + iDRAC.Embedded.1 + iDRAC Users + Users.5 + iDRAC.Embedded.1#Users.5#Enable + false + + Disabled + Enabled + + + User Admin SOL Enable + SolEnable + Disabled + Disabled + + 297 + iDRAC.Embedded.1 + iDRAC Users + Users.5 + iDRAC.Embedded.1#Users.5#SolEnable + false + + Disabled + Enabled + + + SNMP V3 Protocol Enable + ProtocolEnable + Disabled + Disabled + + 298 + iDRAC.Embedded.1 + iDRAC Users + Users.5 + iDRAC.Embedded.1#Users.5#ProtocolEnable + false + + Disabled + Enabled + + + SNMP V3 Authentication Protocol + AuthenticationProtocol + SHA + SHA + + 299 + iDRAC.Embedded.1 + iDRAC Users + Users.5 + iDRAC.Embedded.1#Users.5#AuthenticationProtocol + false + + None + MD5 + SHA + + + SNMP V3 Privacy Protocol + PrivacyProtocol + AES + AES + + 300 + iDRAC.Embedded.1 + iDRAC Users + Users.5 + iDRAC.Embedded.1#Users.5#PrivacyProtocol + false + + None + DES + AES + + + User Admin IPMI LAN Privilege + IpmiLanPrivilege + No Access + No Access + + 304 + iDRAC.Embedded.1 + iDRAC Users + Users.6 + iDRAC.Embedded.1#Users.6#IpmiLanPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin IPMI Serial Privilege + IpmiSerialPrivilege + No Access + No Access + + 305 + iDRAC.Embedded.1 + iDRAC Users + Users.6 + iDRAC.Embedded.1#Users.6#IpmiSerialPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin Enable + Enable + Disabled + Disabled + + 306 + iDRAC.Embedded.1 + iDRAC Users + Users.6 + iDRAC.Embedded.1#Users.6#Enable + false + + Disabled + Enabled + + + User Admin SOL Enable + SolEnable + Disabled + Disabled + + 307 + iDRAC.Embedded.1 + iDRAC Users + Users.6 + iDRAC.Embedded.1#Users.6#SolEnable + false + + Disabled + Enabled + + + SNMP V3 Protocol Enable + ProtocolEnable + Disabled + Disabled + + 308 + iDRAC.Embedded.1 + iDRAC Users + Users.6 + iDRAC.Embedded.1#Users.6#ProtocolEnable + false + + Disabled + Enabled + + + SNMP V3 Authentication Protocol + AuthenticationProtocol + SHA + SHA + + 309 + iDRAC.Embedded.1 + iDRAC Users + Users.6 + iDRAC.Embedded.1#Users.6#AuthenticationProtocol + false + + None + MD5 + SHA + + + SNMP V3 Privacy Protocol + PrivacyProtocol + AES + AES + + 310 + iDRAC.Embedded.1 + iDRAC Users + Users.6 + iDRAC.Embedded.1#Users.6#PrivacyProtocol + false + + None + DES + AES + + + User Admin IPMI LAN Privilege + IpmiLanPrivilege + No Access + No Access + + 314 + iDRAC.Embedded.1 + iDRAC Users + Users.7 + iDRAC.Embedded.1#Users.7#IpmiLanPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin IPMI Serial Privilege + IpmiSerialPrivilege + No Access + No Access + + 315 + iDRAC.Embedded.1 + iDRAC Users + Users.7 + iDRAC.Embedded.1#Users.7#IpmiSerialPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin Enable + Enable + Disabled + Disabled + + 316 + iDRAC.Embedded.1 + iDRAC Users + Users.7 + iDRAC.Embedded.1#Users.7#Enable + false + + Disabled + Enabled + + + User Admin SOL Enable + SolEnable + Disabled + Disabled + + 317 + iDRAC.Embedded.1 + iDRAC Users + Users.7 + iDRAC.Embedded.1#Users.7#SolEnable + false + + Disabled + Enabled + + + SNMP V3 Protocol Enable + ProtocolEnable + Disabled + Disabled + + 318 + iDRAC.Embedded.1 + iDRAC Users + Users.7 + iDRAC.Embedded.1#Users.7#ProtocolEnable + false + + Disabled + Enabled + + + SNMP V3 Authentication Protocol + AuthenticationProtocol + SHA + SHA + + 319 + iDRAC.Embedded.1 + iDRAC Users + Users.7 + iDRAC.Embedded.1#Users.7#AuthenticationProtocol + false + + None + MD5 + SHA + + + SNMP V3 Privacy Protocol + PrivacyProtocol + AES + AES + + 320 + iDRAC.Embedded.1 + iDRAC Users + Users.7 + iDRAC.Embedded.1#Users.7#PrivacyProtocol + false + + None + DES + AES + + + User Admin IPMI LAN Privilege + IpmiLanPrivilege + No Access + No Access + + 324 + iDRAC.Embedded.1 + iDRAC Users + Users.8 + iDRAC.Embedded.1#Users.8#IpmiLanPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin IPMI Serial Privilege + IpmiSerialPrivilege + No Access + No Access + + 325 + iDRAC.Embedded.1 + iDRAC Users + Users.8 + iDRAC.Embedded.1#Users.8#IpmiSerialPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin Enable + Enable + Disabled + Disabled + + 326 + iDRAC.Embedded.1 + iDRAC Users + Users.8 + iDRAC.Embedded.1#Users.8#Enable + false + + Disabled + Enabled + + + User Admin SOL Enable + SolEnable + Disabled + Disabled + + 327 + iDRAC.Embedded.1 + iDRAC Users + Users.8 + iDRAC.Embedded.1#Users.8#SolEnable + false + + Disabled + Enabled + + + SNMP V3 Protocol Enable + ProtocolEnable + Disabled + Disabled + + 328 + iDRAC.Embedded.1 + iDRAC Users + Users.8 + iDRAC.Embedded.1#Users.8#ProtocolEnable + false + + Disabled + Enabled + + + SNMP V3 Authentication Protocol + AuthenticationProtocol + SHA + SHA + + 329 + iDRAC.Embedded.1 + iDRAC Users + Users.8 + iDRAC.Embedded.1#Users.8#AuthenticationProtocol + false + + None + MD5 + SHA + + + SNMP V3 Privacy Protocol + PrivacyProtocol + AES + AES + + 330 + iDRAC.Embedded.1 + iDRAC Users + Users.8 + iDRAC.Embedded.1#Users.8#PrivacyProtocol + false + + None + DES + AES + + + User Admin IPMI LAN Privilege + IpmiLanPrivilege + No Access + No Access + + 334 + iDRAC.Embedded.1 + iDRAC Users + Users.9 + iDRAC.Embedded.1#Users.9#IpmiLanPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin IPMI Serial Privilege + IpmiSerialPrivilege + No Access + No Access + + 335 + iDRAC.Embedded.1 + iDRAC Users + Users.9 + iDRAC.Embedded.1#Users.9#IpmiSerialPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin Enable + Enable + Disabled + Disabled + + 336 + iDRAC.Embedded.1 + iDRAC Users + Users.9 + iDRAC.Embedded.1#Users.9#Enable + false + + Disabled + Enabled + + + User Admin SOL Enable + SolEnable + Disabled + Disabled + + 337 + iDRAC.Embedded.1 + iDRAC Users + Users.9 + iDRAC.Embedded.1#Users.9#SolEnable + false + + Disabled + Enabled + + + SNMP V3 Protocol Enable + ProtocolEnable + Disabled + Disabled + + 338 + iDRAC.Embedded.1 + iDRAC Users + Users.9 + iDRAC.Embedded.1#Users.9#ProtocolEnable + false + + Disabled + Enabled + + + SNMP V3 Authentication Protocol + AuthenticationProtocol + SHA + SHA + + 339 + iDRAC.Embedded.1 + iDRAC Users + Users.9 + iDRAC.Embedded.1#Users.9#AuthenticationProtocol + false + + None + MD5 + SHA + + + SNMP V3 Privacy Protocol + PrivacyProtocol + AES + AES + + 340 + iDRAC.Embedded.1 + iDRAC Users + Users.9 + iDRAC.Embedded.1#Users.9#PrivacyProtocol + false + + None + DES + AES + + + User Admin IPMI LAN Privilege + IpmiLanPrivilege + No Access + No Access + + 344 + iDRAC.Embedded.1 + iDRAC Users + Users.10 + iDRAC.Embedded.1#Users.10#IpmiLanPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin IPMI Serial Privilege + IpmiSerialPrivilege + No Access + No Access + + 345 + iDRAC.Embedded.1 + iDRAC Users + Users.10 + iDRAC.Embedded.1#Users.10#IpmiSerialPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin Enable + Enable + Disabled + Disabled + + 346 + iDRAC.Embedded.1 + iDRAC Users + Users.10 + iDRAC.Embedded.1#Users.10#Enable + false + + Disabled + Enabled + + + User Admin SOL Enable + SolEnable + Disabled + Disabled + + 347 + iDRAC.Embedded.1 + iDRAC Users + Users.10 + iDRAC.Embedded.1#Users.10#SolEnable + false + + Disabled + Enabled + + + SNMP V3 Protocol Enable + ProtocolEnable + Disabled + Disabled + + 348 + iDRAC.Embedded.1 + iDRAC Users + Users.10 + iDRAC.Embedded.1#Users.10#ProtocolEnable + false + + Disabled + Enabled + + + SNMP V3 Authentication Protocol + AuthenticationProtocol + SHA + SHA + + 349 + iDRAC.Embedded.1 + iDRAC Users + Users.10 + iDRAC.Embedded.1#Users.10#AuthenticationProtocol + false + + None + MD5 + SHA + + + SNMP V3 Privacy Protocol + PrivacyProtocol + AES + AES + + 350 + iDRAC.Embedded.1 + iDRAC Users + Users.10 + iDRAC.Embedded.1#Users.10#PrivacyProtocol + false + + None + DES + AES + + + User Admin IPMI LAN Privilege + IpmiLanPrivilege + No Access + No Access + + 354 + iDRAC.Embedded.1 + iDRAC Users + Users.11 + iDRAC.Embedded.1#Users.11#IpmiLanPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin IPMI Serial Privilege + IpmiSerialPrivilege + No Access + No Access + + 355 + iDRAC.Embedded.1 + iDRAC Users + Users.11 + iDRAC.Embedded.1#Users.11#IpmiSerialPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin Enable + Enable + Disabled + Disabled + + 356 + iDRAC.Embedded.1 + iDRAC Users + Users.11 + iDRAC.Embedded.1#Users.11#Enable + false + + Disabled + Enabled + + + User Admin SOL Enable + SolEnable + Disabled + Disabled + + 357 + iDRAC.Embedded.1 + iDRAC Users + Users.11 + iDRAC.Embedded.1#Users.11#SolEnable + false + + Disabled + Enabled + + + SNMP V3 Protocol Enable + ProtocolEnable + Disabled + Disabled + + 358 + iDRAC.Embedded.1 + iDRAC Users + Users.11 + iDRAC.Embedded.1#Users.11#ProtocolEnable + false + + Disabled + Enabled + + + SNMP V3 Authentication Protocol + AuthenticationProtocol + SHA + SHA + + 359 + iDRAC.Embedded.1 + iDRAC Users + Users.11 + iDRAC.Embedded.1#Users.11#AuthenticationProtocol + false + + None + MD5 + SHA + + + SNMP V3 Privacy Protocol + PrivacyProtocol + AES + AES + + 360 + iDRAC.Embedded.1 + iDRAC Users + Users.11 + iDRAC.Embedded.1#Users.11#PrivacyProtocol + false + + None + DES + AES + + + User Admin IPMI LAN Privilege + IpmiLanPrivilege + No Access + No Access + + 364 + iDRAC.Embedded.1 + iDRAC Users + Users.12 + iDRAC.Embedded.1#Users.12#IpmiLanPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin IPMI Serial Privilege + IpmiSerialPrivilege + No Access + No Access + + 365 + iDRAC.Embedded.1 + iDRAC Users + Users.12 + iDRAC.Embedded.1#Users.12#IpmiSerialPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin Enable + Enable + Disabled + Disabled + + 366 + iDRAC.Embedded.1 + iDRAC Users + Users.12 + iDRAC.Embedded.1#Users.12#Enable + false + + Disabled + Enabled + + + User Admin SOL Enable + SolEnable + Disabled + Disabled + + 367 + iDRAC.Embedded.1 + iDRAC Users + Users.12 + iDRAC.Embedded.1#Users.12#SolEnable + false + + Disabled + Enabled + + + SNMP V3 Protocol Enable + ProtocolEnable + Disabled + Disabled + + 368 + iDRAC.Embedded.1 + iDRAC Users + Users.12 + iDRAC.Embedded.1#Users.12#ProtocolEnable + false + + Disabled + Enabled + + + SNMP V3 Authentication Protocol + AuthenticationProtocol + SHA + SHA + + 369 + iDRAC.Embedded.1 + iDRAC Users + Users.12 + iDRAC.Embedded.1#Users.12#AuthenticationProtocol + false + + None + MD5 + SHA + + + SNMP V3 Privacy Protocol + PrivacyProtocol + AES + AES + + 370 + iDRAC.Embedded.1 + iDRAC Users + Users.12 + iDRAC.Embedded.1#Users.12#PrivacyProtocol + false + + None + DES + AES + + + User Admin IPMI LAN Privilege + IpmiLanPrivilege + No Access + No Access + + 374 + iDRAC.Embedded.1 + iDRAC Users + Users.13 + iDRAC.Embedded.1#Users.13#IpmiLanPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin IPMI Serial Privilege + IpmiSerialPrivilege + No Access + No Access + + 375 + iDRAC.Embedded.1 + iDRAC Users + Users.13 + iDRAC.Embedded.1#Users.13#IpmiSerialPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin Enable + Enable + Disabled + Disabled + + 376 + iDRAC.Embedded.1 + iDRAC Users + Users.13 + iDRAC.Embedded.1#Users.13#Enable + false + + Disabled + Enabled + + + User Admin SOL Enable + SolEnable + Disabled + Disabled + + 377 + iDRAC.Embedded.1 + iDRAC Users + Users.13 + iDRAC.Embedded.1#Users.13#SolEnable + false + + Disabled + Enabled + + + SNMP V3 Protocol Enable + ProtocolEnable + Disabled + Disabled + + 378 + iDRAC.Embedded.1 + iDRAC Users + Users.13 + iDRAC.Embedded.1#Users.13#ProtocolEnable + false + + Disabled + Enabled + + + SNMP V3 Authentication Protocol + AuthenticationProtocol + SHA + SHA + + 379 + iDRAC.Embedded.1 + iDRAC Users + Users.13 + iDRAC.Embedded.1#Users.13#AuthenticationProtocol + false + + None + MD5 + SHA + + + SNMP V3 Privacy Protocol + PrivacyProtocol + AES + AES + + 380 + iDRAC.Embedded.1 + iDRAC Users + Users.13 + iDRAC.Embedded.1#Users.13#PrivacyProtocol + false + + None + DES + AES + + + User Admin IPMI LAN Privilege + IpmiLanPrivilege + No Access + No Access + + 384 + iDRAC.Embedded.1 + iDRAC Users + Users.14 + iDRAC.Embedded.1#Users.14#IpmiLanPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin IPMI Serial Privilege + IpmiSerialPrivilege + No Access + No Access + + 385 + iDRAC.Embedded.1 + iDRAC Users + Users.14 + iDRAC.Embedded.1#Users.14#IpmiSerialPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin Enable + Enable + Disabled + Disabled + + 386 + iDRAC.Embedded.1 + iDRAC Users + Users.14 + iDRAC.Embedded.1#Users.14#Enable + false + + Disabled + Enabled + + + User Admin SOL Enable + SolEnable + Disabled + Disabled + + 387 + iDRAC.Embedded.1 + iDRAC Users + Users.14 + iDRAC.Embedded.1#Users.14#SolEnable + false + + Disabled + Enabled + + + SNMP V3 Protocol Enable + ProtocolEnable + Disabled + Disabled + + 388 + iDRAC.Embedded.1 + iDRAC Users + Users.14 + iDRAC.Embedded.1#Users.14#ProtocolEnable + false + + Disabled + Enabled + + + SNMP V3 Authentication Protocol + AuthenticationProtocol + SHA + SHA + + 389 + iDRAC.Embedded.1 + iDRAC Users + Users.14 + iDRAC.Embedded.1#Users.14#AuthenticationProtocol + false + + None + MD5 + SHA + + + SNMP V3 Privacy Protocol + PrivacyProtocol + AES + AES + + 390 + iDRAC.Embedded.1 + iDRAC Users + Users.14 + iDRAC.Embedded.1#Users.14#PrivacyProtocol + false + + None + DES + AES + + + User Admin IPMI LAN Privilege + IpmiLanPrivilege + No Access + No Access + + 394 + iDRAC.Embedded.1 + iDRAC Users + Users.15 + iDRAC.Embedded.1#Users.15#IpmiLanPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin IPMI Serial Privilege + IpmiSerialPrivilege + No Access + No Access + + 395 + iDRAC.Embedded.1 + iDRAC Users + Users.15 + iDRAC.Embedded.1#Users.15#IpmiSerialPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin Enable + Enable + Disabled + Disabled + + 396 + iDRAC.Embedded.1 + iDRAC Users + Users.15 + iDRAC.Embedded.1#Users.15#Enable + false + + Disabled + Enabled + + + User Admin SOL Enable + SolEnable + Disabled + Disabled + + 397 + iDRAC.Embedded.1 + iDRAC Users + Users.15 + iDRAC.Embedded.1#Users.15#SolEnable + false + + Disabled + Enabled + + + SNMP V3 Protocol Enable + ProtocolEnable + Disabled + Disabled + + 398 + iDRAC.Embedded.1 + iDRAC Users + Users.15 + iDRAC.Embedded.1#Users.15#ProtocolEnable + false + + Disabled + Enabled + + + SNMP V3 Authentication Protocol + AuthenticationProtocol + SHA + SHA + + 399 + iDRAC.Embedded.1 + iDRAC Users + Users.15 + iDRAC.Embedded.1#Users.15#AuthenticationProtocol + false + + None + MD5 + SHA + + + SNMP V3 Privacy Protocol + PrivacyProtocol + AES + AES + + 400 + iDRAC.Embedded.1 + iDRAC Users + Users.15 + iDRAC.Embedded.1#Users.15#PrivacyProtocol + false + + None + DES + AES + + + User Admin IPMI LAN Privilege + IpmiLanPrivilege + No Access + No Access + + 404 + iDRAC.Embedded.1 + iDRAC Users + Users.16 + iDRAC.Embedded.1#Users.16#IpmiLanPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin IPMI Serial Privilege + IpmiSerialPrivilege + No Access + No Access + + 405 + iDRAC.Embedded.1 + iDRAC Users + Users.16 + iDRAC.Embedded.1#Users.16#IpmiSerialPrivilege + false + + User + Operator + Administrator + No Access + + + User Admin Enable + Enable + Disabled + Disabled + + 406 + iDRAC.Embedded.1 + iDRAC Users + Users.16 + iDRAC.Embedded.1#Users.16#Enable + false + + Disabled + Enabled + + + User Admin SOL Enable + SolEnable + Disabled + Disabled + + 407 + iDRAC.Embedded.1 + iDRAC Users + Users.16 + iDRAC.Embedded.1#Users.16#SolEnable + false + + Disabled + Enabled + + + SNMP V3 Protocol Enable + ProtocolEnable + Disabled + Disabled + + 408 + iDRAC.Embedded.1 + iDRAC Users + Users.16 + iDRAC.Embedded.1#Users.16#ProtocolEnable + false + + Disabled + Enabled + + + SNMP V3 Authentication Protocol + AuthenticationProtocol + SHA + SHA + + 409 + iDRAC.Embedded.1 + iDRAC Users + Users.16 + iDRAC.Embedded.1#Users.16#AuthenticationProtocol + false + + None + MD5 + SHA + + + SNMP V3 Privacy Protocol + PrivacyProtocol + AES + AES + + 410 + iDRAC.Embedded.1 + iDRAC Users + Users.16 + iDRAC.Embedded.1#Users.16#PrivacyProtocol + false + + None + DES + AES + + + Enable or Disable TFTP for Firmware Update + FwUpdateTFTPEnable + Enabled + Enabled + + 451 + iDRAC.Embedded.1 + Firmware Update + Update.1 + iDRAC.Embedded.1#Update.1#FwUpdateTFTPEnable + false + + Disabled + Enabled + + + Enable Email Alerts + Enable + Disabled + Disabled + + 471 + iDRAC.Embedded.1 + RAC Email Alert + EmailAlert.1 + iDRAC.Embedded.1#EmailAlert.1#Enable + false + + Disabled + Enabled + + + Enable Email Alerts + Enable + Disabled + Disabled + + 491 + iDRAC.Embedded.1 + RAC Email Alert + EmailAlert.2 + iDRAC.Embedded.1#EmailAlert.2#Enable + false + + Disabled + Enabled + + + Enable Email Alerts + Enable + Disabled + Disabled + + 511 + iDRAC.Embedded.1 + RAC Email Alert + EmailAlert.3 + iDRAC.Embedded.1#EmailAlert.3#Enable + false + + Disabled + Enabled + + + Enable Email Alerts + Enable + Disabled + Disabled + + 521 + iDRAC.Embedded.1 + RAC Email Alert + EmailAlert.4 + iDRAC.Embedded.1#EmailAlert.4#Enable + false + + Disabled + Enabled + + + Enable SMTP Authentication + SMTPAuthentication + Disabled + Disabled + + 543 + iDRAC.Embedded.1 + RAC Remote Hosts + RemoteHosts.1 + iDRAC.Embedded.1#RemoteHosts.1#SMTPAuthentication + false + + Disabled + Enabled + + + Enable + Enable + Disabled + Disabled + + 551 + iDRAC.Embedded.1 + Telnet Configuration + Telnet.1 + iDRAC.Embedded.1#Telnet.1#Enable + false + + Disabled + Enabled + + + Enable + Enable + Enabled + Enabled + + 561 + iDRAC.Embedded.1 + RAC SSH + SSH.1 + iDRAC.Embedded.1#SSH.1#Enable + false + + Disabled + Enabled + + + Enable + Enable + Enabled + Enabled + + 571 + iDRAC.Embedded.1 + RAC Web Server + WebServer.1 + iDRAC.Embedded.1#WebServer.1#Enable + false + + Disabled + Enabled + + + Enable + LowerEncryptionBitLength + Enabled + Enabled + + 575 + iDRAC.Embedded.1 + RAC Web Server + WebServer.1 + iDRAC.Embedded.1#WebServer.1#LowerEncryptionBitLength + false + + Disabled + Enabled + + + Https Redirection + HttpsRedirection + Enabled + Enabled + + 576 + iDRAC.Embedded.1 + RAC Web Server + WebServer.1 + iDRAC.Embedded.1#WebServer.1#HttpsRedirection + false + + Disabled + Enabled + + + SSL Encryption Bit Length + SSLEncryptionBitLength + 128-Bit or higher + 128-Bit or higher + + 577 + iDRAC.Embedded.1 + RAC Web Server + WebServer.1 + iDRAC.Embedded.1#WebServer.1#SSLEncryptionBitLength + false + + Auto-Negotiate + 128-Bit or higher + 168-Bit or higher + 256-Bit or higher + + + TLS Protocol Support + TLSProtocol + TLS 1.1 and Higher + TLS 1.1 and Higher + + 579 + iDRAC.Embedded.1 + RAC Web Server + WebServer.1 + iDRAC.Embedded.1#WebServer.1#TLSProtocol + false + + TLS 1.0 and Higher + TLS 1.1 and Higher + TLS 1.2 Only + + + Enable + Enable + Enabled + Enabled + + 581 + iDRAC.Embedded.1 + Virtual Console Configuration + VirtualConsole.1 + iDRAC.Embedded.1#VirtualConsole.1#Enable + false + + Disabled + Enabled + + + Encrypt Enable + EncryptEnable + AES + AES + + 582 + iDRAC.Embedded.1 + Virtual Console Configuration + VirtualConsole.1 + iDRAC.Embedded.1#VirtualConsole.1#EncryptEnable + false + + None + AES + + + Local Video + LocalVideo + Enabled + Enabled + + 583 + iDRAC.Embedded.1 + Virtual Console Configuration + VirtualConsole.1 + iDRAC.Embedded.1#VirtualConsole.1#LocalVideo + false + + Disabled + Enabled + + + Plugin Type + PluginType + Active X + Active X + + 584 + iDRAC.Embedded.1 + Virtual Console Configuration + VirtualConsole.1 + iDRAC.Embedded.1#VirtualConsole.1#PluginType + false + + Active X + Java + HTML5 + + + Default action upon session sharing request timeout + AccessPrivilege + Deny Access + Full Access + + 588 + iDRAC.Embedded.1 + Virtual Console Configuration + VirtualConsole.1 + iDRAC.Embedded.1#VirtualConsole.1#AccessPrivilege + false + + Deny Access + Read Only Access + Full Access + + + Attach State + AttachState + Auto-Attach + Auto-Attach + + 589 + iDRAC.Embedded.1 + Virtual Console Configuration + VirtualConsole.1 + iDRAC.Embedded.1#VirtualConsole.1#AttachState + false + + Detached + Attached + Auto-Attach + + + Remote Enable + Enable + Enabled + Enabled + + 591 + iDRAC.Embedded.1 + Remote Racadm Configuration + Racadm.1 + iDRAC.Embedded.1#Racadm.1#Enable + false + + Disabled + Enabled + + + Serial Console Enable + Enable + Enabled + Enabled + + 601 + iDRAC.Embedded.1 + Serial Configuration + Serial.1 + iDRAC.Embedded.1#Serial.1#Enable + false + + Disabled + Enabled + + + Serial Baud Rate + BaudRate + 57600 + 57600 + + 602 + iDRAC.Embedded.1 + Serial Configuration + Serial.1 + iDRAC.Embedded.1#Serial.1#BaudRate + false + + 9600 + 19200 + 38400 + 57600 + 115200 + + + Serial Console No Authentication + NoAuth + Disabled + Disabled + + 604 + iDRAC.Embedded.1 + Serial Configuration + Serial.1 + iDRAC.Embedded.1#Serial.1#NoAuth + false + + Disabled + Enabled + + + Serial Communication Redirection Enable + Enable + Enabled + Enabled + + 611 + iDRAC.Embedded.1 + RAC Serial Redirection + SerialRedirection.1 + iDRAC.Embedded.1#SerialRedirection.1#Enable + false + + Disabled + Enabled + + + IPMI Serial Connection Mode + ConnectionMode + Basic + Basic + + 621 + iDRAC.Embedded.1 + RAC IPMI Serial + IPMISerial.1 + iDRAC.Embedded.1#IPMISerial.1#ConnectionMode + false + + Terminal + Basic + + + IPMI Serial Baud Rate + BaudRate + 57600 + 57600 + + 622 + iDRAC.Embedded.1 + RAC IPMI Serial + IPMISerial.1 + iDRAC.Embedded.1#IPMISerial.1#BaudRate + false + + 9600 + 19200 + 57600 + 115200 + + + IPMI Serial Flow Control + FlowControl + RTS/CTS + RTS/CTS + + 623 + iDRAC.Embedded.1 + RAC IPMI Serial + IPMISerial.1 + iDRAC.Embedded.1#IPMISerial.1#FlowControl + false + + None + RTS/CTS + + + IPMI Serial Channel Privilege Limit + ChanPrivLimit + Administrator + Administrator + + 624 + iDRAC.Embedded.1 + RAC IPMI Serial + IPMISerial.1 + iDRAC.Embedded.1#IPMISerial.1#ChanPrivLimit + false + + User + Operator + Administrator + + + IPMI Serial Line Edit + LineEdit + Enabled + Enabled + + 625 + iDRAC.Embedded.1 + RAC IPMI Serial + IPMISerial.1 + iDRAC.Embedded.1#IPMISerial.1#LineEdit + false + + Disabled + Enabled + + + IPMI Serial Delete Control + DeleteControl + Disabled + Disabled + + 626 + iDRAC.Embedded.1 + RAC IPMI Serial + IPMISerial.1 + iDRAC.Embedded.1#IPMISerial.1#DeleteControl + false + + Disabled + Enabled + + + IPMI Serial Echo Control + EchoControl + Enabled + Enabled + + 627 + iDRAC.Embedded.1 + RAC IPMI Serial + IPMISerial.1 + iDRAC.Embedded.1#IPMISerial.1#EchoControl + false + + Disabled + Enabled + + + IPMI Serial Handshake Control + HandshakeControl + Enabled + Enabled + + 628 + iDRAC.Embedded.1 + RAC IPMI Serial + IPMISerial.1 + iDRAC.Embedded.1#IPMISerial.1#HandshakeControl + false + + Disabled + Enabled + + + IPMI Serial New Line Sequence + NewLineSeq + CR-LF + CR-LF + + 629 + iDRAC.Embedded.1 + RAC IPMI Serial + IPMISerial.1 + iDRAC.Embedded.1#IPMISerial.1#NewLineSeq + false + + None + CR-LF + Null + CR + LF-CR + LF + + + IPMI Serial Input New Line Sequence + InputNewLineSeq + Enter + Null + + 630 + iDRAC.Embedded.1 + RAC IPMI Serial + IPMISerial.1 + iDRAC.Embedded.1#IPMISerial.1#InputNewLineSeq + false + + Enter + Null + + + IPMI SOL Enable + Enable + Disabled + Enabled + + 641 + iDRAC.Embedded.1 + IPMI SOL + IPMISOL.1 + iDRAC.Embedded.1#IPMISOL.1#Enable + false + + Disabled + Enabled + + + IPMI SOL Baud Rate + BaudRate + 115200 + 115200 + + 642 + iDRAC.Embedded.1 + IPMI SOL + IPMISOL.1 + iDRAC.Embedded.1#IPMISOL.1#BaudRate + false + + 9600 + 19200 + 57600 + 115200 + + + IPMI SOL Min Privilege + MinPrivilege + Administrator + Administrator + + 643 + iDRAC.Embedded.1 + IPMI SOL + IPMISOL.1 + iDRAC.Embedded.1#IPMISOL.1#MinPrivilege + false + + User + Operator + Administrator + + + SNMP Agent Enable + AgentEnable + Enabled + Enabled + + 701 + iDRAC.Embedded.1 + SNMP Configuration + SNMP.1 + iDRAC.Embedded.1#SNMP.1#AgentEnable + false + + Disabled + Enabled + + + SNMP Trap Format + TrapFormat + SNMPv1 + SNMPv1 + + 703 + iDRAC.Embedded.1 + SNMP Configuration + SNMP.1 + iDRAC.Embedded.1#SNMP.1#TrapFormat + false + + SNMPv1 + SNMPv2 + SNMPv3 + + + SNMP Protocol + SNMPProtocol + All + All + + 704 + iDRAC.Embedded.1 + SNMP Configuration + SNMP.1 + iDRAC.Embedded.1#SNMP.1#SNMPProtocol + false + + All + SNMPv3 + + + RAC Virtual Media Attached + Attached + AutoAttach + AutoAttach + + 711 + iDRAC.Embedded.1 + Virtual Media + VirtualMedia.1 + iDRAC.Embedded.1#VirtualMedia.1#Attached + false + + Detached + Attached + AutoAttach + + + Virtual Media Boot Once + BootOnce + Disabled + Disabled + + 712 + iDRAC.Embedded.1 + Virtual Media + VirtualMedia.1 + iDRAC.Embedded.1#VirtualMedia.1#BootOnce + false + + Disabled + Enabled + + + Virtual Media Key Enable + KeyEnable + Disabled + Disabled + + 713 + iDRAC.Embedded.1 + Virtual Media + VirtualMedia.1 + iDRAC.Embedded.1#VirtualMedia.1#KeyEnable + false + + Disabled + Enabled + + + Virtual Media Floppy Emulation + FloppyEmulation + Disabled + Disabled + + 714 + iDRAC.Embedded.1 + Virtual Media + VirtualMedia.1 + iDRAC.Embedded.1#VirtualMedia.1#FloppyEmulation + false + + Disabled + Enabled + + + Virtual Media Encrypt Enable + EncryptEnable + None + AES + + 715 + iDRAC.Embedded.1 + Virtual Media + VirtualMedia.1 + iDRAC.Embedded.1#VirtualMedia.1#EncryptEnable + false + + None + AES + + + Enable + Enable + Enabled + Enabled + + 716 + iDRAC.Embedded.1 + Virtual Media + VirtualMedia.1 + iDRAC.Embedded.1#VirtualMedia.1#Enable + false + + Disabled + Enabled + + + Tune IP Range Enable + RangeEnable + Disabled + Disabled + + 721 + iDRAC.Embedded.1 + IP Blocking + IPBlocking.1 + iDRAC.Embedded.1#IPBlocking.1#RangeEnable + false + + Disabled + Enabled + + + Tune IP Block Enable + BlockEnable + Enabled + Enabled + + 724 + iDRAC.Embedded.1 + IP Blocking + IPBlocking.1 + iDRAC.Embedded.1#IPBlocking.1#BlockEnable + true + + Disabled + Enabled + + + Preboot Config + PrebootConfig + Disabled + Disabled + + 741 + iDRAC.Embedded.1 + Local Security + LocalSecurity.1 + iDRAC.Embedded.1#LocalSecurity.1#PrebootConfig + false + + Disabled + Enabled + + + Local Config + LocalConfig + Disabled + Disabled + + 742 + iDRAC.Embedded.1 + Local Security + LocalSecurity.1 + iDRAC.Embedded.1#LocalSecurity.1#LocalConfig + false + + Disabled + Enabled + + + CSR Key Size + CsrKeySize + 2048 + 2048 + + 768 + iDRAC.Embedded.1 + RAC Certificate + Security.1 + iDRAC.Embedded.1#Security.1#CsrKeySize + false + + 1024 + 2048 + 4096 + + + FIPS Mode + FIPSMode + Disabled + Disabled + + 769 + iDRAC.Embedded.1 + RAC Certificate + Security.1 + iDRAC.Embedded.1#Security.1#FIPSMode + false + + Enabled + Disabled + + + Enable LDAP + Enable + Disabled + Disabled + + 1081 + iDRAC.Embedded.1 + LDAP + LDAP.1 + iDRAC.Embedded.1#LDAP.1#Enable + false + + Disabled + Enabled + + + LDAP Group Attribute Is Domain Name + GroupAttributeIsDN + Enabled + Enabled + + 1087 + iDRAC.Embedded.1 + LDAP + LDAP.1 + iDRAC.Embedded.1#LDAP.1#GroupAttributeIsDN + false + + Disabled + Enabled + + + Enable LDAP Certificate Validation + CertValidationEnable + Enabled + Enabled + + 1091 + iDRAC.Embedded.1 + LDAP + LDAP.1 + iDRAC.Embedded.1#LDAP.1#CertValidationEnable + false + + Disabled + Enabled + + + Active Directory Enable + Enable + Disabled + Disabled + + 771 + iDRAC.Embedded.1 + Active Directory + ActiveDirectory.1 + iDRAC.Embedded.1#ActiveDirectory.1#Enable + false + + Disabled + Enabled + + + Active Directory Schema Type + Schema + Extended Schema + Extended Schema + + 775 + iDRAC.Embedded.1 + Active Directory + ActiveDirectory.1 + iDRAC.Embedded.1#ActiveDirectory.1#Schema + false + + Extended Schema + Standard Schema + + + Certificate Validation Enable + CertValidationEnable + Disabled + Disabled + + 782 + iDRAC.Embedded.1 + Active Directory + ActiveDirectory.1 + iDRAC.Embedded.1#ActiveDirectory.1#CertValidationEnable + false + + Disabled + Enabled + + + SSO Enable + SSOEnable + Disabled + Disabled + + 1063 + iDRAC.Embedded.1 + Active Directory + ActiveDirectory.1 + iDRAC.Embedded.1#ActiveDirectory.1#SSOEnable + false + + Disabled + Enabled + + + Global Catalog Server Lookup Enable + GCLookupEnable + Disabled + Disabled + + 784 + iDRAC.Embedded.1 + Active Directory + ActiveDirectory.1 + iDRAC.Embedded.1#ActiveDirectory.1#GCLookupEnable + false + + Disabled + Enabled + + + Domain Controller Lookup Enable + DCLookupEnable + Disabled + Disabled + + 785 + iDRAC.Embedded.1 + Active Directory + ActiveDirectory.1 + iDRAC.Embedded.1#ActiveDirectory.1#DCLookupEnable + false + + Disabled + Enabled + + + Domain Controller Lookup By User Domain + DCLookupByUserDomain + Enabled + Enabled + + 788 + iDRAC.Embedded.1 + Active Directory + ActiveDirectory.1 + iDRAC.Embedded.1#ActiveDirectory.1#DCLookupByUserDomain + false + + Disabled + Enabled + + + Smart Card Logon Enable + SmartCardLogonEnable + Disabled + Disabled + + 1061 + iDRAC.Embedded.1 + Smart Card Configuration + SmartCard.1 + iDRAC.Embedded.1#SmartCard.1#SmartCardLogonEnable + false + + Disabled + Enabled + Enabled With Racadm + + + Smart Card CRL Enable + SmartCardCRLEnable + Disabled + Disabled + + 1062 + iDRAC.Embedded.1 + Smart Card Configuration + SmartCard.1 + iDRAC.Embedded.1#SmartCard.1#SmartCardCRLEnable + false + + Disabled + Enabled + + + Sys Log Enable + SysLogEnable + Disabled + Disabled + + 1071 + iDRAC.Embedded.1 + Sys Log + SysLog.1 + iDRAC.Embedded.1#SysLog.1#SysLogEnable + false + + Disabled + Enabled + + + Power Log Enable + PowerLogEnable + Disabled + Disabled + + 1076 + iDRAC.Embedded.1 + Sys Log + SysLog.1 + iDRAC.Embedded.1#SysLog.1#PowerLogEnable + false + + Disabled + Enabled + + + State + State + Disabled + Disabled + + 1152 + iDRAC.Embedded.1 + SNMP Trap IPv6 + SNMPTrapIPv6.1 + iDRAC.Embedded.1#SNMPTrapIPv6.1#State + false + + Disabled + Enabled + + + State + State + Disabled + Disabled + + 1162 + iDRAC.Embedded.1 + SNMP Trap IPv6 + SNMPTrapIPv6.2 + iDRAC.Embedded.1#SNMPTrapIPv6.2#State + false + + Disabled + Enabled + + + State + State + Disabled + Disabled + + 1172 + iDRAC.Embedded.1 + SNMP Trap IPv6 + SNMPTrapIPv6.3 + iDRAC.Embedded.1#SNMPTrapIPv6.3#State + false + + Disabled + Enabled + + + State + State + Disabled + Disabled + + 1182 + iDRAC.Embedded.1 + SNMP Trap IPv6 + SNMPTrapIPv6.4 + iDRAC.Embedded.1#SNMPTrapIPv6.4#State + false + + Disabled + Enabled + + + State + State + Disabled + Disabled + + 1192 + iDRAC.Embedded.1 + SNMP Trap IPv4 + SNMPTrapIPv4.1 + iDRAC.Embedded.1#SNMPTrapIPv4.1#State + false + + Disabled + Enabled + + + State + State + Disabled + Disabled + + 1202 + iDRAC.Embedded.1 + SNMP Trap IPv4 + SNMPTrapIPv4.2 + iDRAC.Embedded.1#SNMPTrapIPv4.2#State + false + + Disabled + Enabled + + + State + State + Disabled + Disabled + + 1212 + iDRAC.Embedded.1 + SNMP Trap IPv4 + SNMPTrapIPv4.3 + iDRAC.Embedded.1#SNMPTrapIPv4.3#State + false + + Disabled + Enabled + + + State + State + Disabled + Disabled + + 1222 + iDRAC.Embedded.1 + SNMP Trap IPv4 + SNMPTrapIPv4.4 + iDRAC.Embedded.1#SNMPTrapIPv4.4#State + false + + Disabled + Enabled + + + Media Attach State + MediaAttachState + Detached + Detached + + 1232 + iDRAC.Embedded.1 + Remote File Share + RFS.1 + iDRAC.Embedded.1#RFS.1#MediaAttachState + true + + Attached + Detached + + + iDRAC Remote File Share Write protected + WriteProtected + Read Only + Read Only + + 1234 + iDRAC.Embedded.1 + Remote File Share + RFS.1 + iDRAC.Embedded.1#RFS.1#WriteProtected + true + + Read Only + Read Write + + + OS-BMC Pass Through Capability + PTCapability + Capable + Not Capable + + 1240 + iDRAC.Embedded.1 + OS-BMC Passthru Configuration + OS-BMC.1 + iDRAC.Embedded.1#OS-BMC.1#PTCapability + true + + Not Capable + Capable + Unavailable + + + LC and Host Private Channel State + AdminState + Disabled + Disabled + + 1241 + iDRAC.Embedded.1 + OS-BMC Passthru Configuration + OS-BMC.1 + iDRAC.Embedded.1#OS-BMC.1#AdminState + false + + Disabled + Enabled + + + OS-BMC PT Mode + PTMode + usb-p2p + usb-p2p + + 1244 + iDRAC.Embedded.1 + OS-BMC Passthru Configuration + OS-BMC.1 + iDRAC.Embedded.1#OS-BMC.1#PTMode + false + + lom-p2p + usb-p2p + + + State + State + Disabled + Disabled + + 1602 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.1 + iDRAC.Embedded.1#SNMPAlert.1#State + false + + Disabled + Enabled + + + State + State + Disabled + Disabled + + 1604 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.2 + iDRAC.Embedded.1#SNMPAlert.2#State + false + + Disabled + Enabled + + + State + State + Disabled + Disabled + + 1606 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.3 + iDRAC.Embedded.1#SNMPAlert.3#State + false + + Disabled + Enabled + + + State + State + Disabled + Disabled + + 1608 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.4 + iDRAC.Embedded.1#SNMPAlert.4#State + false + + Disabled + Enabled + + + State + State + Disabled + Disabled + + 1610 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.5 + iDRAC.Embedded.1#SNMPAlert.5#State + false + + Disabled + Enabled + + + State + State + Disabled + Disabled + + 1612 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.6 + iDRAC.Embedded.1#SNMPAlert.6#State + false + + Disabled + Enabled + + + State + State + Disabled + Disabled + + 1614 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.7 + iDRAC.Embedded.1#SNMPAlert.7#State + false + + Disabled + Enabled + + + State + State + Disabled + Disabled + + 1616 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.8 + iDRAC.Embedded.1#SNMPAlert.8#State + false + + Disabled + Enabled + + + Default Credential Mitigation + DefaultCredentialMitigation + Enabled + Enabled + + 1700 + iDRAC.Embedded.1 + Default Credential Mitigation Configuration + DefaultCredentialMitigationConfigGroup.1 + iDRAC.Embedded.1#DefaultCredentialMitigationConfigGroup.1#DefaultCredentialMitigation + false + + Disabled + Enabled + + + Auto OS Lock State + AutoOSLockState + Enabled + Enabled + + 1500 + iDRAC.Embedded.1 + Automatic OS Lock Group + AutoOSLockGroup.1 + iDRAC.Embedded.1#AutoOSLockGroup.1#AutoOSLockState + false + + Disabled + Enabled + + + NTP Enable + NTPEnable + Disabled + Disabled + + 2004 + iDRAC.Embedded.1 + NTP Configuration Group + NTPConfigGroup.1 + iDRAC.Embedded.1#NTPConfigGroup.1#NTPEnable + false + + Disabled + Enabled + + + SEL OEM Event Filter Enable + SELOEMEventFilterEnable + Disabled + Disabled + + 2130 + iDRAC.Embedded.1 + iDRAC Logging + Logging.1 + iDRAC.Embedded.1#Logging.1#SELOEMEventFilterEnable + false + + Disabled + Enabled + + + IOIDOpt Enable + IOIDOptEnable + Disabled + Disabled + + 2140 + iDRAC.Embedded.1 + IO Identity Optimization + IOIDOpt.1 + iDRAC.Embedded.1#IOIDOpt.1#IOIDOptEnable + false + + Disabled + Enabled + + + Virtual Address Persistence Policy Non Auxiliary Powered + VirtualAddressPersistencePolicyNonAuxPwrd + WarmReset + WarmReset + + 2141 + iDRAC.Embedded.1 + IO Identity Optimization + IOIDOpt.1 + iDRAC.Embedded.1#IOIDOpt.1#VirtualAddressPersistencePolicyNonAuxPwrd + false + + None + WarmReset + ColdReset + WarmReset, ColdReset + ACPowerLoss + WarmReset, ACPowerLoss + ColdReset, ACPowerLoss + WarmReset, ColdReset, ACPowerLoss + + + Virtual Address Persistence Policy Auxiliary Powered + VirtualAddressPersistencePolicyAuxPwrd + WarmReset, ColdReset + WarmReset, ColdReset + + 2142 + iDRAC.Embedded.1 + IO Identity Optimization + IOIDOpt.1 + iDRAC.Embedded.1#IOIDOpt.1#VirtualAddressPersistencePolicyAuxPwrd + false + + None + WarmReset + ColdReset + WarmReset, ColdReset + ACPowerLoss + WarmReset, ACPowerLoss + ColdReset, ACPowerLoss + WarmReset, ColdReset, ACPowerLoss + + + Initiator Persistence Policy + InitiatorPersistencePolicy + WarmReset, ColdReset, ACPowerLoss + WarmReset, ColdReset, ACPowerLoss + + 2143 + iDRAC.Embedded.1 + IO Identity Optimization + IOIDOpt.1 + iDRAC.Embedded.1#IOIDOpt.1#InitiatorPersistencePolicy + false + + None + WarmReset + ColdReset + WarmReset, ColdReset + ACPowerLoss + WarmReset, ACPowerLoss + ColdReset, ACPowerLoss + WarmReset, ColdReset, ACPowerLoss + + + Storage Target Persistence Policy + StorageTargetPersistencePolicy + WarmReset, ColdReset, ACPowerLoss + WarmReset, ColdReset, ACPowerLoss + + 2144 + iDRAC.Embedded.1 + IO Identity Optimization + IOIDOpt.1 + iDRAC.Embedded.1#IOIDOpt.1#StorageTargetPersistencePolicy + false + + None + WarmReset + ColdReset + WarmReset, ColdReset + ACPowerLoss + WarmReset, ACPowerLoss + ColdReset, ACPowerLoss + WarmReset, ColdReset, ACPowerLoss + + + OMSA Presence on Host + OMSAPresence + NA + NA + + 2150 + iDRAC.Embedded.1 + ServiceModule + ServiceModule.1 + iDRAC.Embedded.1#ServiceModule.1#OMSAPresence + true + + Not Present + Present + NA + + + Sharing of OS Information via ServiceModule + OSInfo + Enabled + Enabled + + 2151 + iDRAC.Embedded.1 + ServiceModule + ServiceModule.1 + iDRAC.Embedded.1#ServiceModule.1#OSInfo + false + + Disabled + Enabled + + + Watchdog timer via ServiceModule + WatchdogState + Disabled + Disabled + + 2152 + iDRAC.Embedded.1 + ServiceModule + ServiceModule.1 + iDRAC.Embedded.1#ServiceModule.1#WatchdogState + false + + Disabled + Enabled + + + Recovery action on watchdog alert + WatchdogRecoveryAction + None + None + + 2154 + iDRAC.Embedded.1 + ServiceModule + ServiceModule.1 + iDRAC.Embedded.1#ServiceModule.1#WatchdogRecoveryAction + false + + None + Reboot + Poweroff + Powercycle + + + LCL replication in OS Log + LCLReplication + Disabled + Disabled + + 2156 + iDRAC.Embedded.1 + ServiceModule + ServiceModule.1 + iDRAC.Embedded.1#ServiceModule.1#LCLReplication + false + + Disabled + Enabled + + + Populate WMI information via ServiceModule + WMIInfo + Disabled + Disabled + + 2157 + iDRAC.Embedded.1 + ServiceModule + ServiceModule.1 + iDRAC.Embedded.1#ServiceModule.1#WMIInfo + false + + Disabled + Enabled + + + ServiceModule Enable + ServiceModuleEnable + Enabled + Enabled + + 2159 + iDRAC.Embedded.1 + ServiceModule + ServiceModule.1 + iDRAC.Embedded.1#ServiceModule.1#ServiceModuleEnable + false + + Disabled + Enabled + + + ServiceModule service state on host + ServiceModuleState + Not Running + Not Running + + 2160 + iDRAC.Embedded.1 + ServiceModule + ServiceModule.1 + iDRAC.Embedded.1#ServiceModule.1#ServiceModuleState + true + + Not Running + Running + + + iDRAC Hard Reset + iDRACHardReset + Enabled + Enabled + + 2222 + iDRAC.Embedded.1 + ServiceModule + ServiceModule.1 + iDRAC.Embedded.1#ServiceModule.1#iDRACHardReset + false + + Disabled + Enabled + + + Enable + Enable + Disabled + Disabled + + 2162 + iDRAC.Embedded.1 + RAC VNC Server + VNCServer.1 + iDRAC.Embedded.1#VNCServer.1#Enable + false + + Disabled + Enabled + + + LowerEncryptionBitLength + LowerEncryptionBitLength + Disabled + Disabled + + 2165 + iDRAC.Embedded.1 + RAC VNC Server + VNCServer.1 + iDRAC.Embedded.1#VNCServer.1#LowerEncryptionBitLength + false + + Disabled + Enabled + + + SSL Encryption Bit Length + SSLEncryptionBitLength + Disabled + Disabled + + 2167 + iDRAC.Embedded.1 + RAC VNC Server + VNCServer.1 + iDRAC.Embedded.1#VNCServer.1#SSLEncryptionBitLength + false + + Disabled + Auto Negotiate + 128-Bit or higher + 168-Bit or higher + 256-Bit or higher + + + Enable + Enable + Disabled + Disabled + + 2174 + iDRAC.Embedded.1 + vFlash + vFlashSD.1 + iDRAC.Embedded.1#vFlashSD.1#Enable + false + + Disabled + Enabled + + + Boot Once + BootOnce + Enabled + Enabled + + 2191 + iDRAC.Embedded.1 + Server Boot + ServerBoot.1 + iDRAC.Embedded.1#ServerBoot.1#BootOnce + false + + Enabled + Disabled + + + Management Port Mode + ManagementPortMode + Automatic + Automatic + + 2200 + iDRAC.Embedded.1 + USB Management + USB.1 + iDRAC.Embedded.1#USB.1#ManagementPortMode + false + + Automatic + Standard OS Use + iDRAC Direct Only + + + Configuration XML + ConfigurationXML + Enabled while server has default credential settings only + Enabled while server has default credential settings only + + 2201 + iDRAC.Embedded.1 + USB Management + USB.1 + iDRAC.Embedded.1#USB.1#ConfigurationXML + false + + Disabled + Enabled while server has default credential settings only + Enabled + + + Port Status + PortStatus + Enabled + Enabled + + 2202 + iDRAC.Embedded.1 + USB Management + USB.1 + iDRAC.Embedded.1#USB.1#PortStatus + true + + Disabled + Enabled + + + Enable + Enable + Disabled + Disabled + + 2221 + iDRAC.Embedded.1 + ASR Config + ASRConfig.1 + iDRAC.Embedded.1#ASRConfig.1#Enable + false + + Disabled + Enabled + + + Custom UI + CustomUI + DefaultUI + DefaultUI + + 2222 + iDRAC.Embedded.1 + DCS Custom + DCSCustom.1 + iDRAC.Embedded.1#DCSCustom.1#CustomUI + false + + DefaultUI + Custom UI Enabled + + + Ignore Certificate Errors + IgnoreCertificateErrors + Yes + Yes + + 2242 + iDRAC.Embedded.1 + RedfishEventing + RedfishEventing.1 + iDRAC.Embedded.1#RedfishEventing.1#IgnoreCertificateErrors + true + + No + Yes + + + Enable + Enable + Enabled + Enabled + + 2250 + iDRAC.Embedded.1 + Redfish + Redfish.1 + iDRAC.Embedded.1#Redfish.1#Enable + false + + Disabled + Enabled + + + + + + + diff --git a/dracclient/tests/wsman_mocks/idraccard_integer-enum-ok.xml b/dracclient/tests/wsman_mocks/idraccard_integer-enum-ok.xml new file mode 100644 index 0000000..906b031 --- /dev/null +++ b/dracclient/tests/wsman_mocks/idraccard_integer-enum-ok.xml @@ -0,0 +1,1397 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + uuid:1b114e09-e635-4ad9-90dd-3045421499a7 + uuid:a92483bc-40aa-10aa-8221-de7e4e771814 + + + + + + NIC MTU + MTU + 1500 + 1500 + + 58 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#MTU + false + 576 + + 1500 + + + VLAN Priority + VLanPriority + 0 + 0 + + 64 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#VLanPriority + false + 0 + + 7 + + + VLAN ID + VLanID + 1 + 1 + + 65 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#VLanID + false + 1 + + 4096 + + + Shared to Dedicated Failover Timeout + DedicatedNICScanTime + 5 + 5 + + 67 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#DedicatedNICScanTime + false + 5 + + 255 + + + Dedicated to Shared Failover Timeout + SharedNICScanTime + 30 + 30 + + 68 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#SharedNICScanTime + false + 5 + + 255 + + + IPV6 Link Local Prefix Length + PrefixLength + 64 + 64 + + 157 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#PrefixLength + false + 1 + + 128 + + + Total Number of Extended IP + IPV6NumOfExtAddress + 0 + 0 + + 160 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#IPV6NumOfExtAddress + true + 0 + + 255 + + + IPV6 Link Local Prefix Length + PrefixLength + 64 + 64 + + 193 + iDRAC.Embedded.1 + IPv6 Static Information + IPv6Static.1 + iDRAC.Embedded.1#IPv6Static.1#PrefixLength + false + 1 + + 128 + + + User Admin Privilege + Privilege + 0 + 0 + + 253 + iDRAC.Embedded.1 + iDRAC Users + Users.1 + iDRAC.Embedded.1#Users.1#Privilege + true + 0 + + 511 + + + User Admin Privilege + Privilege + 511 + 511 + + 263 + iDRAC.Embedded.1 + iDRAC Users + Users.2 + iDRAC.Embedded.1#Users.2#Privilege + false + 0 + + 511 + + + User Admin Privilege + Privilege + 0 + 0 + + 273 + iDRAC.Embedded.1 + iDRAC Users + Users.3 + iDRAC.Embedded.1#Users.3#Privilege + false + 0 + + 511 + + + User Admin Privilege + Privilege + 313 + 0 + + 283 + iDRAC.Embedded.1 + iDRAC Users + Users.4 + iDRAC.Embedded.1#Users.4#Privilege + false + 0 + + 511 + + + User Admin Privilege + Privilege + 0 + 0 + + 293 + iDRAC.Embedded.1 + iDRAC Users + Users.5 + iDRAC.Embedded.1#Users.5#Privilege + false + 0 + + 511 + + + User Admin Privilege + Privilege + 0 + 0 + + 303 + iDRAC.Embedded.1 + iDRAC Users + Users.6 + iDRAC.Embedded.1#Users.6#Privilege + false + 0 + + 511 + + + User Admin Privilege + Privilege + 0 + 0 + + 313 + iDRAC.Embedded.1 + iDRAC Users + Users.7 + iDRAC.Embedded.1#Users.7#Privilege + false + 0 + + 511 + + + User Admin Privilege + Privilege + 0 + 0 + + 323 + iDRAC.Embedded.1 + iDRAC Users + Users.8 + iDRAC.Embedded.1#Users.8#Privilege + false + 0 + + 511 + + + User Admin Privilege + Privilege + 0 + 0 + + 333 + iDRAC.Embedded.1 + iDRAC Users + Users.9 + iDRAC.Embedded.1#Users.9#Privilege + false + 0 + + 511 + + + User Admin Privilege + Privilege + 0 + 0 + + 343 + iDRAC.Embedded.1 + iDRAC Users + Users.10 + iDRAC.Embedded.1#Users.10#Privilege + false + 0 + + 511 + + + User Admin Privilege + Privilege + 0 + 0 + + 353 + iDRAC.Embedded.1 + iDRAC Users + Users.11 + iDRAC.Embedded.1#Users.11#Privilege + false + 0 + + 511 + + + User Admin Privilege + Privilege + 0 + 0 + + 363 + iDRAC.Embedded.1 + iDRAC Users + Users.12 + iDRAC.Embedded.1#Users.12#Privilege + false + 0 + + 511 + + + User Admin Privilege + Privilege + 0 + 0 + + 373 + iDRAC.Embedded.1 + iDRAC Users + Users.13 + iDRAC.Embedded.1#Users.13#Privilege + false + 0 + + 511 + + + User Admin Privilege + Privilege + 0 + 0 + + 383 + iDRAC.Embedded.1 + iDRAC Users + Users.14 + iDRAC.Embedded.1#Users.14#Privilege + false + 0 + + 511 + + + User Admin Privilege + Privilege + 0 + 0 + + 393 + iDRAC.Embedded.1 + iDRAC Users + Users.15 + iDRAC.Embedded.1#Users.15#Privilege + false + 0 + + 511 + + + User Admin Privilege + Privilege + 0 + 0 + + 403 + iDRAC.Embedded.1 + iDRAC Users + Users.16 + iDRAC.Embedded.1#Users.16#Privilege + false + 0 + + 511 + + + SMTP Port + SMTPPort + 25 + 25 + + 542 + iDRAC.Embedded.1 + RAC Remote Hosts + RemoteHosts.1 + iDRAC.Embedded.1#RemoteHosts.1#SMTPPort + false + 1 + + 65535 + + + Telnet Port + Port + 23 + 23 + + 552 + iDRAC.Embedded.1 + Telnet Configuration + Telnet.1 + iDRAC.Embedded.1#Telnet.1#Port + false + 1 + + 65535 + + + Timeout + Timeout + 1800 + 1800 + + 553 + iDRAC.Embedded.1 + Telnet Configuration + Telnet.1 + iDRAC.Embedded.1#Telnet.1#Timeout + false + 60 + + 10800 + + + SSH Port + Port + 22 + 22 + + 562 + iDRAC.Embedded.1 + RAC SSH + SSH.1 + iDRAC.Embedded.1#SSH.1#Port + false + 1 + + 65535 + + + SSH Idle Timeout + Timeout + 1800 + 1800 + + 563 + iDRAC.Embedded.1 + RAC SSH + SSH.1 + iDRAC.Embedded.1#SSH.1#Timeout + false + 60 + + 10800 + + + Http Port + HttpPort + 80 + 80 + + 572 + iDRAC.Embedded.1 + RAC Web Server + WebServer.1 + iDRAC.Embedded.1#WebServer.1#HttpPort + false + 1 + + 65535 + + + Https Port + HttpsPort + 443 + 443 + + 573 + iDRAC.Embedded.1 + RAC Web Server + WebServer.1 + iDRAC.Embedded.1#WebServer.1#HttpsPort + false + 1 + + 65535 + + + Timeout + Timeout + 1800 + 1800 + + 574 + iDRAC.Embedded.1 + RAC Web Server + WebServer.1 + iDRAC.Embedded.1#WebServer.1#Timeout + false + 60 + + 10800 + + + Max Number Of Sessions + MaxNumberOfSessions + 8 + 8 + + 578 + iDRAC.Embedded.1 + RAC Web Server + WebServer.1 + iDRAC.Embedded.1#WebServer.1#MaxNumberOfSessions + true + 1 + + 8 + + + Max Sessions + MaxSessions + 6 + 6 + + 585 + iDRAC.Embedded.1 + Virtual Console Configuration + VirtualConsole.1 + iDRAC.Embedded.1#VirtualConsole.1#MaxSessions + false + 1 + + 6 + + + vKVM Port + Port + 5900 + 5900 + + 586 + iDRAC.Embedded.1 + Virtual Console Configuration + VirtualConsole.1 + iDRAC.Embedded.1#VirtualConsole.1#Port + false + 1 + + 65535 + + + Timeout + Timeout + 1800 + 1800 + + 587 + iDRAC.Embedded.1 + Virtual Console Configuration + VirtualConsole.1 + iDRAC.Embedded.1#VirtualConsole.1#Timeout + false + 60 + + 10800 + + + Remote Timeout + Timeout + 60 + 60 + + 592 + iDRAC.Embedded.1 + Remote Racadm Configuration + Racadm.1 + iDRAC.Embedded.1#Racadm.1#Timeout + false + 10 + + 1920 + + + Serial Console Idle Timeout + IdleTimeout + 300 + 300 + + 603 + iDRAC.Embedded.1 + Serial Configuration + Serial.1 + iDRAC.Embedded.1#Serial.1#IdleTimeout + false + 60 + + 1920 + + + Serial History Size + HistorySize + 8192 + 8192 + + 605 + iDRAC.Embedded.1 + Serial Configuration + Serial.1 + iDRAC.Embedded.1#Serial.1#HistorySize + false + 0 + + 8192 + + + IPMI SOL Accumulate Interval + AccumulateInterval + 10 + 10 + + 644 + iDRAC.Embedded.1 + IPMI SOL + IPMISOL.1 + iDRAC.Embedded.1#IPMISOL.1#AccumulateInterval + false + 1 + + 255 + + + IPMI SOL Send Threshold + SendThreshold + 255 + 255 + + 645 + iDRAC.Embedded.1 + IPMI SOL + IPMISOL.1 + iDRAC.Embedded.1#IPMISOL.1#SendThreshold + false + 1 + + 255 + + + IPMI SOL Retry Count + RetryCount + 7 + 255 + + 646 + iDRAC.Embedded.1 + IPMI SOL + IPMISOL.1 + iDRAC.Embedded.1#IPMISOL.1#RetryCount + true + 1 + + 255 + + + IPMI SOL Retry Interval + RetryInterval + 48 + 255 + + 647 + iDRAC.Embedded.1 + IPMI SOL + IPMISOL.1 + iDRAC.Embedded.1#IPMISOL.1#RetryInterval + true + 1 + + 255 + + + Discovery Port + DiscoveryPort + 161 + 161 + + 705 + iDRAC.Embedded.1 + SNMP Configuration + SNMP.1 + iDRAC.Embedded.1#SNMP.1#DiscoveryPort + false + 1 + + 65535 + + + Alert Port + AlertPort + 162 + 162 + + 706 + iDRAC.Embedded.1 + SNMP Configuration + SNMP.1 + iDRAC.Embedded.1#SNMP.1#AlertPort + false + 1 + + 65535 + + + Tune IP Block Fail Count + FailCount + 3 + 3 + + 731 + iDRAC.Embedded.1 + IP Blocking + IPBlocking.1 + iDRAC.Embedded.1#IPBlocking.1#FailCount + true + 2 + + 16 + + + Tune IP Block Fail Window + FailWindow + 60 + 60 + + 732 + iDRAC.Embedded.1 + IP Blocking + IPBlocking.1 + iDRAC.Embedded.1#IPBlocking.1#FailWindow + true + 10 + + 65535 + + + Tune IP Block Penalty Time + PenaltyTime + 600 + 600 + + 733 + iDRAC.Embedded.1 + IP Blocking + IPBlocking.1 + iDRAC.Embedded.1#IPBlocking.1#PenaltyTime + true + 2 + + 65535 + + + Tune Time Zone Offset + TimeZoneOffset + 0 + 0 + + 751 + iDRAC.Embedded.1 + Time Zone Configuration Information + Time.1 + iDRAC.Embedded.1#Time.1#TimeZoneOffset + false + -43200 + + 46800 + + + Tune Day Light Offset + DaylightOffset + 0 + 0 + + 752 + iDRAC.Embedded.1 + Time Zone Configuration Information + Time.1 + iDRAC.Embedded.1#Time.1#DaylightOffset + false + 0 + + 60 + + + LDAP Port + Port + 636 + 636 + + 1083 + iDRAC.Embedded.1 + LDAP + LDAP.1 + iDRAC.Embedded.1#LDAP.1#Port + false + 1 + + 65535 + + + Active Directory Authentication Timeout + AuthTimeout + 120 + 120 + + 774 + iDRAC.Embedded.1 + Active Directory + ActiveDirectory.1 + iDRAC.Embedded.1#ActiveDirectory.1#AuthTimeout + false + 15 + + 300 + + + AD Group Privilege + Privilege + 0 + 0 + + 803 + iDRAC.Embedded.1 + AD Group Configuration + ADGroup.1 + iDRAC.Embedded.1#ADGroup.1#Privilege + false + 0 + + 511 + + + AD Group Privilege + Privilege + 0 + 0 + + 813 + iDRAC.Embedded.1 + AD Group Configuration + ADGroup.2 + iDRAC.Embedded.1#ADGroup.2#Privilege + false + 0 + + 511 + + + AD Group Privilege + Privilege + 0 + 0 + + 823 + iDRAC.Embedded.1 + AD Group Configuration + ADGroup.3 + iDRAC.Embedded.1#ADGroup.3#Privilege + false + 0 + + 511 + + + AD Group Privilege + Privilege + 0 + 0 + + 833 + iDRAC.Embedded.1 + ADGroup Configuration + ADGroup.4 + iDRAC.Embedded.1#ADGroup.4#Privilege + false + 0 + + 511 + + + AD Group Privilege + Privilege + 0 + 0 + + 843 + iDRAC.Embedded.1 + ADGroup Configuration + ADGroup.5 + iDRAC.Embedded.1#ADGroup.5#Privilege + false + 0 + + 511 + + + Sys Log Port + Port + 514 + 514 + + 1072 + iDRAC.Embedded.1 + Sys Log + SysLog.1 + iDRAC.Embedded.1#SysLog.1#Port + false + 1 + + 65535 + + + Power Log Interval + PowerLogInterval + 5 + 5 + + 1077 + iDRAC.Embedded.1 + Sys Log + SysLog.1 + iDRAC.Embedded.1#SysLog.1#PowerLogInterval + false + 1 + + 1440 + + + LDAP Group Privilege + Privilege + 0 + 0 + + 1102 + iDRAC.Embedded.1 + LDAP Group + LDAPRoleGroup.1 + iDRAC.Embedded.1#LDAPRoleGroup.1#Privilege + false + 0 + + 511 + + + LDAP Group Privilege + Privilege + 0 + 0 + + 1112 + iDRAC.Embedded.1 + LDAP Group + LDAPRoleGroup.2 + iDRAC.Embedded.1#LDAPRoleGroup.2#Privilege + false + 0 + + 511 + + + LDAP Group Privilege + Privilege + 0 + 0 + + 1122 + iDRAC.Embedded.1 + LDAP Group + LDAPRoleGroup.3 + iDRAC.Embedded.1#LDAPRoleGroup.3#Privilege + false + 0 + + 511 + + + LDAP Group Privilege + Privilege + 0 + 0 + + 1132 + iDRAC.Embedded.1 + LDAP Group + LDAPRoleGroup.4 + iDRAC.Embedded.1#LDAPRoleGroup.4#Privilege + false + 0 + + 511 + + + LDAP Group Privilege + Privilege + 0 + 0 + + 1142 + iDRAC.Embedded.1 + LDAP Group + LDAPRoleGroup.5 + iDRAC.Embedded.1#LDAPRoleGroup.5#Privilege + false + 0 + + 511 + + + Destination Number + DestinationNum + 1 + 1 + + 1151 + iDRAC.Embedded.1 + SNMP Trap IPv6 + SNMPTrapIPv6.1 + iDRAC.Embedded.1#SNMPTrapIPv6.1#DestinationNum + true + 1 + + 4 + + + Destination Number + DestinationNum + 1 + 1 + + 1161 + iDRAC.Embedded.1 + SNMP Trap IPv6 + SNMPTrapIPv6.2 + iDRAC.Embedded.1#SNMPTrapIPv6.2#DestinationNum + true + 1 + + 4 + + + Destination Number + DestinationNum + 1 + 1 + + 1171 + iDRAC.Embedded.1 + SNMP Trap IPv6 + SNMPTrapIPv6.3 + iDRAC.Embedded.1#SNMPTrapIPv6.3#DestinationNum + true + 1 + + 4 + + + Destination Number + DestinationNum + 1 + 1 + + 1181 + iDRAC.Embedded.1 + SNMP Trap IPv6 + SNMPTrapIPv6.4 + iDRAC.Embedded.1#SNMPTrapIPv6.4#DestinationNum + true + 1 + + 4 + + + Destination Number + DestinationNum + 1 + 1 + + 1191 + iDRAC.Embedded.1 + SNMP Trap IPv4 + SNMPTrapIPv4.1 + iDRAC.Embedded.1#SNMPTrapIPv4.1#DestinationNum + true + 1 + + 4 + + + Destination Number + DestinationNum + 1 + 1 + + 1201 + iDRAC.Embedded.1 + SNMP Trap IPv4 + SNMPTrapIPv4.2 + iDRAC.Embedded.1#SNMPTrapIPv4.2#DestinationNum + true + 1 + + 4 + + + Destination Number + DestinationNum + 1 + 1 + + 1211 + iDRAC.Embedded.1 + SNMP Trap IPv4 + SNMPTrapIPv4.3 + iDRAC.Embedded.1#SNMPTrapIPv4.3#DestinationNum + true + 1 + + 4 + + + Destination Number + DestinationNum + 1 + 1 + + 1221 + iDRAC.Embedded.1 + SNMP Trap IPv4 + SNMPTrapIPv4.4 + iDRAC.Embedded.1#SNMPTrapIPv4.4#DestinationNum + true + 1 + + 4 + + + SNMP V3 UserID + SNMPv3UserID + 0 + 0 + + 1604 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.1 + iDRAC.Embedded.1#SNMPAlert.1#SNMPv3UserID + true + 0 + + 16 + + + SNMP V3 UserID + SNMPv3UserID + 0 + 0 + + 1604 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.2 + iDRAC.Embedded.1#SNMPAlert.2#SNMPv3UserID + true + 0 + + 16 + + + SNMP V3 UserID + SNMPv3UserID + 0 + 0 + + 1604 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.3 + iDRAC.Embedded.1#SNMPAlert.3#SNMPv3UserID + true + 0 + + 16 + + + SNMP V3 UserID + SNMPv3UserID + 0 + 0 + + 1610 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.4 + iDRAC.Embedded.1#SNMPAlert.4#SNMPv3UserID + true + 0 + + 16 + + + SNMP V3 UserID + SNMPv3UserID + 0 + 0 + + 1612 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.5 + iDRAC.Embedded.1#SNMPAlert.5#SNMPv3UserID + true + 0 + + 16 + + + SNMP V3 UserID + SNMPv3UserID + 0 + 0 + + 1614 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.6 + iDRAC.Embedded.1#SNMPAlert.6#SNMPv3UserID + true + 0 + + 16 + + + SNMP V3 UserID + SNMPv3UserID + 0 + 0 + + 1616 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.7 + iDRAC.Embedded.1#SNMPAlert.7#SNMPv3UserID + true + 0 + + 16 + + + SNMP V3 UserID + SNMPv3UserID + 0 + 0 + + 1618 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.8 + iDRAC.Embedded.1#SNMPAlert.8#SNMPv3UserID + true + 0 + + 16 + + + NTP Maximum Distance + NTPMaxDist + 16 + 16 + + 2005 + iDRAC.Embedded.1 + NTP Configuration Group + NTPConfigGroup.1 + iDRAC.Embedded.1#NTPConfigGroup.1#NTPMaxDist + false + 1 + + 128 + + + System reset time on watchdog alert + WatchdogResetTime + 480 + 480 + + 2153 + iDRAC.Embedded.1 + ServiceModule + ServiceModule.1 + iDRAC.Embedded.1#ServiceModule.1#WatchdogResetTime + false + 60 + + 720 + + + Port + Port + 5901 + 5901 + + 2164 + iDRAC.Embedded.1 + RAC VNC Server + VNCServer.1 + iDRAC.Embedded.1#VNCServer.1#Port + false + 1024 + + 65535 + + + Timeout + Timeout + 300 + 300 + + 2166 + iDRAC.Embedded.1 + RAC VNC Server + VNCServer.1 + iDRAC.Embedded.1#VNCServer.1#Timeout + false + 60 + + 10800 + + + Delivery Retry Attempts + DeliveryRetryAttempts + 3 + 3 + + 2240 + iDRAC.Embedded.1 + RedfishEventing + RedfishEventing.1 + iDRAC.Embedded.1#RedfishEventing.1#DeliveryRetryAttempts + false + 0 + + 5 + + + Delivery Retry Interval In Seconds + DeliveryRetryIntervalInSeconds + 30 + 30 + + 2241 + iDRAC.Embedded.1 + RedfishEventing + RedfishEventing.1 + iDRAC.Embedded.1#RedfishEventing.1#DeliveryRetryIntervalInSeconds + false + 5 + + 60 + + + + + + + diff --git a/dracclient/tests/wsman_mocks/idraccard_string-enum-ok.xml b/dracclient/tests/wsman_mocks/idraccard_string-enum-ok.xml new file mode 100644 index 0000000..07d5adb --- /dev/null +++ b/dracclient/tests/wsman_mocks/idraccard_string-enum-ok.xml @@ -0,0 +1,4549 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + uuid:437c3101-0e6a-41f5-ad49-8a09b3ee5589 + uuid:a8ddc513-40aa-10aa-821d-de7e4e771814 + + + + + + iDRAC Product Information + Product + Integrated Dell Remote Access Controller + + + 1 + iDRAC.Embedded.1 + RAC Information + Info.1 + iDRAC.Embedded.1#Info.1#Product + true + 63 + 0 + + + + iDRAC Description Information + Description + This system component provides a complete set of remote management functions for Dell PowerEdge Servers + + + 2 + iDRAC.Embedded.1 + RAC Information + Info.1 + iDRAC.Embedded.1#Info.1#Description + true + 255 + 0 + + + + iDRAC Version Information + Version + 2.40.40.40 + + + 3 + iDRAC.Embedded.1 + RAC Information + Info.1 + iDRAC.Embedded.1#Info.1#Version + true + 63 + 0 + + + + iDRAC Build Information + Build + 45 + + + 4 + iDRAC.Embedded.1 + RAC Information + Info.1 + iDRAC.Embedded.1#Info.1#Build + true + 16 + 0 + + + + iDRAC Name + Name + idrac-9CDK182 + iDRAC + + 5 + iDRAC.Embedded.1 + RAC Information + Info.1 + iDRAC.Embedded.1#Info.1#Name + true + 15 + 0 + + + + Server Generation + ServerGen + 13G + + + 7 + iDRAC.Embedded.1 + RAC Information + Info.1 + iDRAC.Embedded.1#Info.1#ServerGen + true + 10 + 0 + + + + MAC Address + MACAddress + 14:18:77:4E:7E:DE + + + 52 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#MACAddress + true + 17 + 0 + + + + DNS RAC Name + DNSRacName + idrac-9CDK182 + idrac-SVCTAG + + 59 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#DNSRacName + false + 63 + 0 + + + + DNS Domain Name + DNSDomainName + ib.sfdc.net + + + 181 + iDRAC.Embedded.1 + NIC Information + NIC.1 + iDRAC.Embedded.1#NIC.1#DNSDomainName + false + 254 + 0 + + + + IPv4 Address + Address + 10.224.178.123 + 192.168.0.120 + + 103 + iDRAC.Embedded.1 + IPv4 Information + IPv4.1 + iDRAC.Embedded.1#IPv4.1#Address + false + 16 + 0 + + + + Net Mask + Netmask + 255.255.255.0 + 255.255.255.0 + + 104 + iDRAC.Embedded.1 + IPv4 Information + IPv4.1 + iDRAC.Embedded.1#IPv4.1#Netmask + false + 16 + 0 + + + + Gateway + Gateway + 10.224.178.1 + 192.168.0.1 + + 105 + iDRAC.Embedded.1 + IPv4 Information + IPv4.1 + iDRAC.Embedded.1#IPv4.1#Gateway + false + 16 + 0 + + + + DNS Server 1 + DNS1 + 10.225.9.2 + 0.0.0.0 + + 107 + iDRAC.Embedded.1 + IPv4 Information + IPv4.1 + iDRAC.Embedded.1#IPv4.1#DNS1 + false + 16 + 0 + + + + DNS Server 2 + DNS2 + 10.225.9.18 + 0.0.0.0 + + 108 + iDRAC.Embedded.1 + IPv4 Information + IPv4.1 + iDRAC.Embedded.1#IPv4.1#DNS2 + false + 16 + 0 + + + + IPV6 Address 1 + Address1 + :: + :: + + 154 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#Address1 + false + 63 + 0 + + + + IPV6 Gateway + Gateway + :: + :: + + 155 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#Gateway + false + 63 + 0 + + + + IPV6 Link Local Address + LinkLocalAddress + :: + :: + + 156 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#LinkLocalAddress + true + 63 + 0 + + + + IPV6 DNS Server1 + DNS1 + :: + :: + + 158 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#DNS1 + false + 63 + 0 + + + + IPV6 DNS Server2 + DNS2 + :: + :: + + 159 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#DNS2 + false + 63 + 0 + + + + IPV6 Address 2 + Address2 + :: + :: + + 161 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#Address2 + true + 63 + 0 + + + + IPV6 Address 3 + Address3 + :: + :: + + 162 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#Address3 + true + 63 + 0 + + + + IPV6 Address 4 + Address4 + :: + :: + + 163 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#Address4 + true + 63 + 0 + + + + IPV6 Address 5 + Address5 + :: + :: + + 164 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#Address5 + true + 63 + 0 + + + + IPV6 Address 6 + Address6 + :: + :: + + 165 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#Address6 + true + 63 + 0 + + + + IPV6 Address 7 + Address7 + :: + :: + + 166 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#Address7 + true + 63 + 0 + + + + IPV6 Address 8 + Address8 + :: + :: + + 167 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#Address8 + true + 63 + 0 + + + + IPV6 Address 9 + Address9 + :: + :: + + 168 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#Address9 + true + 63 + 0 + + + + IPV6 Address 10 + Address10 + :: + :: + + 169 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#Address10 + true + 63 + 0 + + + + IPV6 Address 11 + Address11 + :: + :: + + 170 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#Address11 + true + 63 + 0 + + + + IPV6 Address 12 + Address12 + :: + :: + + 171 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#Address12 + true + 63 + 0 + + + + IPV6 Address 13 + Address13 + :: + :: + + 172 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#Address13 + true + 63 + 0 + + + + IPV6 Address 14 + Address14 + :: + :: + + 173 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#Address14 + true + 63 + 0 + + + + IPV6 Address 15 + Address15 + :: + :: + + 174 + iDRAC.Embedded.1 + IPv6 Information + IPv6.1 + iDRAC.Embedded.1#IPv6.1#Address15 + true + 63 + 0 + + + + DNS Domain Name + DNSDomainName + ib.sfdc.net + + + 182 + iDRAC.Embedded.1 + NIC Static Information + NICStatic.1 + iDRAC.Embedded.1#NICStatic.1#DNSDomainName + false + 254 + 0 + + + + IPv4 Address + Address + 10.224.178.123 + 192.168.0.120 + + 185 + iDRAC.Embedded.1 + IPv4 Static Information + IPv4Static.1 + iDRAC.Embedded.1#IPv4Static.1#Address + false + 16 + 0 + + + + Net Mask + Netmask + 255.255.255.0 + 255.255.255.0 + + 186 + iDRAC.Embedded.1 + IPv4 Static Information + IPv4Static.1 + iDRAC.Embedded.1#IPv4Static.1#Netmask + false + 16 + 0 + + + + Gateway + Gateway + 10.224.178.1 + 192.168.0.1 + + 187 + iDRAC.Embedded.1 + IPv4 Static Information + IPv4Static.1 + iDRAC.Embedded.1#IPv4Static.1#Gateway + false + 16 + 0 + + + + DNS Server 1 + DNS1 + 10.225.9.2 + 0.0.0.0 + + 188 + iDRAC.Embedded.1 + IPv4 Static Information + IPv4Static.1 + iDRAC.Embedded.1#IPv4Static.1#DNS1 + false + 16 + 0 + + + + DNS Server 2 + DNS2 + 10.225.9.18 + 0.0.0.0 + + 189 + iDRAC.Embedded.1 + IPv4 Static Information + IPv4Static.1 + iDRAC.Embedded.1#IPv4Static.1#DNS2 + false + 16 + 0 + + + + IPV6 Address 1 + Address1 + :: + :: + + 191 + iDRAC.Embedded.1 + IPv6 Static Information + IPv6Static.1 + iDRAC.Embedded.1#IPv6Static.1#Address1 + false + 63 + 0 + + + + IPV6 Gateway + Gateway + :: + :: + + 192 + iDRAC.Embedded.1 + IPv6 Static Information + IPv6Static.1 + iDRAC.Embedded.1#IPv6Static.1#Gateway + false + 63 + 0 + + + + IPV6 DNS Server1 + DNS1 + :: + :: + + 194 + iDRAC.Embedded.1 + IPv6 Static Information + IPv6Static.1 + iDRAC.Embedded.1#IPv6Static.1#DNS1 + false + 63 + 0 + + + + IPV6 DNS Server2 + DNS2 + :: + :: + + 195 + iDRAC.Embedded.1 + IPv6 Static Information + IPv6Static.1 + iDRAC.Embedded.1#IPv6Static.1#DNS2 + false + 63 + 0 + + + + Encryption Key + EncryptionKey + 0000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000 + + 203 + iDRAC.Embedded.1 + IPMI LAN Information + IPMILan.1 + iDRAC.Embedded.1#IPMILan.1#EncryptionKey + false + 40 + 0 + + + + Community Name + CommunityName + WYSkmGB8 + public + + 204 + iDRAC.Embedded.1 + IPMI LAN Information + IPMILan.1 + iDRAC.Embedded.1#IPMILan.1#CommunityName + false + 18 + 0 + + + + User Admin User Name + UserName + + + + 251 + iDRAC.Embedded.1 + iDRAC Users + Users.1 + iDRAC.Embedded.1#Users.1#UserName + true + 16 + 0 + + + + SHA256 hash of the password + SHA256Password + + + + 2624 + iDRAC.Embedded.1 + iDRAC Users + Users.1 + iDRAC.Embedded.1#Users.1#SHA256Password + false + 64 + 0 + + + + SHA1 Hash of the SNMPv3 Key + SHA1v3Key + + + + 2625 + iDRAC.Embedded.1 + iDRAC Users + Users.1 + iDRAC.Embedded.1#Users.1#SHA1v3Key + false + 40 + 0 + + + + MD5 Hash of the SNMPv3 key + MD5v3Key + + + + 2626 + iDRAC.Embedded.1 + iDRAC Users + Users.1 + iDRAC.Embedded.1#Users.1#MD5v3Key + false + 32 + 0 + + + + Salt String Appended To Password Prior To Hash + SHA256PasswordSalt + + + + 2627 + iDRAC.Embedded.1 + iDRAC Users + Users.1 + iDRAC.Embedded.1#Users.1#SHA256PasswordSalt + false + 32 + 0 + + + + User Admin User Name + UserName + admin + root + + 261 + iDRAC.Embedded.1 + iDRAC Users + Users.2 + iDRAC.Embedded.1#Users.2#UserName + false + 16 + 0 + + + + SHA256 hash of the password + SHA256Password + AC403CC78DC7F1C340A8913CAAA53460E6F91775AB16ADFAA9B5DDBE57D4798C + + + 2634 + iDRAC.Embedded.1 + iDRAC Users + Users.2 + iDRAC.Embedded.1#Users.2#SHA256Password + false + 64 + 0 + + + + SHA1 Hash of the SNMPv3 Key + SHA1v3Key + c22d74e14376ce5e964bd13d468c392de73db061 + + + 2635 + iDRAC.Embedded.1 + iDRAC Users + Users.2 + iDRAC.Embedded.1#Users.2#SHA1v3Key + false + 40 + 0 + + + + MD5 Hash of the SNMPv3 key + MD5v3Key + 5e58df0460c546d875c50341476ada6c + + + 2636 + iDRAC.Embedded.1 + iDRAC Users + Users.2 + iDRAC.Embedded.1#Users.2#MD5v3Key + false + 32 + 0 + + + + Salt String Appended To Password Prior To Hash + SHA256PasswordSalt + DB8A8304C5EAAA238E3BE93F6B9CC7DB + + + 2637 + iDRAC.Embedded.1 + iDRAC Users + Users.2 + iDRAC.Embedded.1#Users.2#SHA256PasswordSalt + false + 32 + 0 + + + + User Admin User Name + UserName + mrmon + + + 271 + iDRAC.Embedded.1 + iDRAC Users + Users.3 + iDRAC.Embedded.1#Users.3#UserName + false + 16 + 0 + + + + SHA256 hash of the password + SHA256Password + ACD86A03B4789BBCA4D6B3EFC50825FC1BD36A65A5B662D5263C50B1032DC20D + + + 2644 + iDRAC.Embedded.1 + iDRAC Users + Users.3 + iDRAC.Embedded.1#Users.3#SHA256Password + false + 64 + 0 + + + + SHA1 Hash of the SNMPv3 Key + SHA1v3Key + e176e67d8e05f7f8c862729d71ecfa1529290e7a + + + 2645 + iDRAC.Embedded.1 + iDRAC Users + Users.3 + iDRAC.Embedded.1#Users.3#SHA1v3Key + false + 40 + 0 + + + + MD5 Hash of the SNMPv3 key + MD5v3Key + f636a0e73b7c7113d948b0c738be6f56 + + + 2646 + iDRAC.Embedded.1 + iDRAC Users + Users.3 + iDRAC.Embedded.1#Users.3#MD5v3Key + false + 32 + 0 + + + + Salt String Appended To Password Prior To Hash + SHA256PasswordSalt + DC06E8E9C4F80AFB73FFFADE82AF9DFA + + + 2647 + iDRAC.Embedded.1 + iDRAC Users + Users.3 + iDRAC.Embedded.1#Users.3#SHA256PasswordSalt + false + 32 + 0 + + + + User Admin User Name + UserName + oscnoc + + + 281 + iDRAC.Embedded.1 + iDRAC Users + Users.4 + iDRAC.Embedded.1#Users.4#UserName + false + 16 + 0 + + + + SHA256 hash of the password + SHA256Password + AA62370E0F53FC0FAD156CB65ACE4E176BF7E05A937D3134ED9A85C9ED1BB72F + + + 2654 + iDRAC.Embedded.1 + iDRAC Users + Users.4 + iDRAC.Embedded.1#Users.4#SHA256Password + false + 64 + 0 + + + + SHA1 Hash of the SNMPv3 Key + SHA1v3Key + 779dfe35824475dc95f7b993c0a9f6cd21724119 + + + 2655 + iDRAC.Embedded.1 + iDRAC Users + Users.4 + iDRAC.Embedded.1#Users.4#SHA1v3Key + false + 40 + 0 + + + + MD5 Hash of the SNMPv3 key + MD5v3Key + 015a288c1f21d6e7792391eeb7bc8106 + + + 2656 + iDRAC.Embedded.1 + iDRAC Users + Users.4 + iDRAC.Embedded.1#Users.4#MD5v3Key + false + 32 + 0 + + + + Salt String Appended To Password Prior To Hash + SHA256PasswordSalt + 8B65F922B8917D3E9173A0D9BAC4E42D + + + 2657 + iDRAC.Embedded.1 + iDRAC Users + Users.4 + iDRAC.Embedded.1#Users.4#SHA256PasswordSalt + false + 32 + 0 + + + + User Admin User Name + UserName + + + + 291 + iDRAC.Embedded.1 + iDRAC Users + Users.5 + iDRAC.Embedded.1#Users.5#UserName + false + 16 + 0 + + + + SHA256 hash of the password + SHA256Password + + + + 2664 + iDRAC.Embedded.1 + iDRAC Users + Users.5 + iDRAC.Embedded.1#Users.5#SHA256Password + false + 64 + 0 + + + + SHA1 Hash of the SNMPv3 Key + SHA1v3Key + + + + 2665 + iDRAC.Embedded.1 + iDRAC Users + Users.5 + iDRAC.Embedded.1#Users.5#SHA1v3Key + false + 40 + 0 + + + + MD5 Hash of the SNMPv3 key + MD5v3Key + + + + 2666 + iDRAC.Embedded.1 + iDRAC Users + Users.5 + iDRAC.Embedded.1#Users.5#MD5v3Key + false + 32 + 0 + + + + Salt String Appended To Password Prior To Hash + SHA256PasswordSalt + + + + 2667 + iDRAC.Embedded.1 + iDRAC Users + Users.5 + iDRAC.Embedded.1#Users.5#SHA256PasswordSalt + false + 32 + 0 + + + + User Admin User Name + UserName + + + + 301 + iDRAC.Embedded.1 + iDRAC Users + Users.6 + iDRAC.Embedded.1#Users.6#UserName + false + 16 + 0 + + + + SHA256 hash of the password + SHA256Password + + + + 2674 + iDRAC.Embedded.1 + iDRAC Users + Users.6 + iDRAC.Embedded.1#Users.6#SHA256Password + false + 64 + 0 + + + + SHA1 Hash of the SNMPv3 Key + SHA1v3Key + + + + 2675 + iDRAC.Embedded.1 + iDRAC Users + Users.6 + iDRAC.Embedded.1#Users.6#SHA1v3Key + false + 40 + 0 + + + + MD5 Hash of the SNMPv3 key + MD5v3Key + + + + 2676 + iDRAC.Embedded.1 + iDRAC Users + Users.6 + iDRAC.Embedded.1#Users.6#MD5v3Key + false + 32 + 0 + + + + Salt String Appended To Password Prior To Hash + SHA256PasswordSalt + + + + 2677 + iDRAC.Embedded.1 + iDRAC Users + Users.6 + iDRAC.Embedded.1#Users.6#SHA256PasswordSalt + false + 32 + 0 + + + + User Admin User Name + UserName + + + + 311 + iDRAC.Embedded.1 + iDRAC Users + Users.7 + iDRAC.Embedded.1#Users.7#UserName + false + 16 + 0 + + + + SHA256 hash of the password + SHA256Password + + + + 2684 + iDRAC.Embedded.1 + iDRAC Users + Users.7 + iDRAC.Embedded.1#Users.7#SHA256Password + false + 64 + 0 + + + + SHA1 Hash of the SNMPv3 Key + SHA1v3Key + + + + 2685 + iDRAC.Embedded.1 + iDRAC Users + Users.7 + iDRAC.Embedded.1#Users.7#SHA1v3Key + false + 40 + 0 + + + + MD5 Hash of the SNMPv3 key + MD5v3Key + + + + 2686 + iDRAC.Embedded.1 + iDRAC Users + Users.7 + iDRAC.Embedded.1#Users.7#MD5v3Key + false + 32 + 0 + + + + Salt String Appended To Password Prior To Hash + SHA256PasswordSalt + + + + 2687 + iDRAC.Embedded.1 + iDRAC Users + Users.7 + iDRAC.Embedded.1#Users.7#SHA256PasswordSalt + false + 32 + 0 + + + + User Admin User Name + UserName + + + + 321 + iDRAC.Embedded.1 + iDRAC Users + Users.8 + iDRAC.Embedded.1#Users.8#UserName + false + 16 + 0 + + + + SHA256 hash of the password + SHA256Password + + + + 2694 + iDRAC.Embedded.1 + iDRAC Users + Users.8 + iDRAC.Embedded.1#Users.8#SHA256Password + false + 64 + 0 + + + + SHA1 Hash of the SNMPv3 Key + SHA1v3Key + + + + 2695 + iDRAC.Embedded.1 + iDRAC Users + Users.8 + iDRAC.Embedded.1#Users.8#SHA1v3Key + false + 40 + 0 + + + + MD5 Hash of the SNMPv3 key + MD5v3Key + + + + 2696 + iDRAC.Embedded.1 + iDRAC Users + Users.8 + iDRAC.Embedded.1#Users.8#MD5v3Key + false + 32 + 0 + + + + Salt String Appended To Password Prior To Hash + SHA256PasswordSalt + + + + 2697 + iDRAC.Embedded.1 + iDRAC Users + Users.8 + iDRAC.Embedded.1#Users.8#SHA256PasswordSalt + false + 32 + 0 + + + + User Admin User Name + UserName + + + + 331 + iDRAC.Embedded.1 + iDRAC Users + Users.9 + iDRAC.Embedded.1#Users.9#UserName + false + 16 + 0 + + + + SHA256 hash of the password + SHA256Password + + + + 2704 + iDRAC.Embedded.1 + iDRAC Users + Users.9 + iDRAC.Embedded.1#Users.9#SHA256Password + false + 64 + 0 + + + + SHA1 Hash of the SNMPv3 Key + SHA1v3Key + + + + 2705 + iDRAC.Embedded.1 + iDRAC Users + Users.9 + iDRAC.Embedded.1#Users.9#SHA1v3Key + false + 40 + 0 + + + + MD5 Hash of the SNMPv3 key + MD5v3Key + + + + 2706 + iDRAC.Embedded.1 + iDRAC Users + Users.9 + iDRAC.Embedded.1#Users.9#MD5v3Key + false + 32 + 0 + + + + Salt String Appended To Password Prior To Hash + SHA256PasswordSalt + + + + 2707 + iDRAC.Embedded.1 + iDRAC Users + Users.9 + iDRAC.Embedded.1#Users.9#SHA256PasswordSalt + false + 32 + 0 + + + + User Admin User Name + UserName + + + + 341 + iDRAC.Embedded.1 + iDRAC Users + Users.10 + iDRAC.Embedded.1#Users.10#UserName + false + 16 + 0 + + + + SHA256 hash of the password + SHA256Password + + + + 2714 + iDRAC.Embedded.1 + iDRAC Users + Users.10 + iDRAC.Embedded.1#Users.10#SHA256Password + false + 64 + 0 + + + + SHA1 Hash of the SNMPv3 Key + SHA1v3Key + + + + 2715 + iDRAC.Embedded.1 + iDRAC Users + Users.10 + iDRAC.Embedded.1#Users.10#SHA1v3Key + false + 40 + 0 + + + + MD5 Hash of the SNMPv3 key + MD5v3Key + + + + 2716 + iDRAC.Embedded.1 + iDRAC Users + Users.10 + iDRAC.Embedded.1#Users.10#MD5v3Key + false + 32 + 0 + + + + Salt String Appended To Password Prior To Hash + SHA256PasswordSalt + + + + 2717 + iDRAC.Embedded.1 + iDRAC Users + Users.10 + iDRAC.Embedded.1#Users.10#SHA256PasswordSalt + false + 32 + 0 + + + + User Admin User Name + UserName + + + + 351 + iDRAC.Embedded.1 + iDRAC Users + Users.11 + iDRAC.Embedded.1#Users.11#UserName + false + 16 + 0 + + + + SHA256 hash of the password + SHA256Password + + + + 2724 + iDRAC.Embedded.1 + iDRAC Users + Users.11 + iDRAC.Embedded.1#Users.11#SHA256Password + false + 64 + 0 + + + + SHA1 Hash of the SNMPv3 Key + SHA1v3Key + + + + 2725 + iDRAC.Embedded.1 + iDRAC Users + Users.11 + iDRAC.Embedded.1#Users.11#SHA1v3Key + false + 40 + 0 + + + + MD5 Hash of the SNMPv3 key + MD5v3Key + + + + 2726 + iDRAC.Embedded.1 + iDRAC Users + Users.11 + iDRAC.Embedded.1#Users.11#MD5v3Key + false + 32 + 0 + + + + Salt String Appended To Password Prior To Hash + SHA256PasswordSalt + + + + 2727 + iDRAC.Embedded.1 + iDRAC Users + Users.11 + iDRAC.Embedded.1#Users.11#SHA256PasswordSalt + false + 32 + 0 + + + + User Admin User Name + UserName + + + + 361 + iDRAC.Embedded.1 + iDRAC Users + Users.12 + iDRAC.Embedded.1#Users.12#UserName + false + 16 + 0 + + + + SHA256 hash of the password + SHA256Password + + + + 2734 + iDRAC.Embedded.1 + iDRAC Users + Users.12 + iDRAC.Embedded.1#Users.12#SHA256Password + false + 64 + 0 + + + + SHA1 Hash of the SNMPv3 Key + SHA1v3Key + + + + 2735 + iDRAC.Embedded.1 + iDRAC Users + Users.12 + iDRAC.Embedded.1#Users.12#SHA1v3Key + false + 40 + 0 + + + + MD5 Hash of the SNMPv3 key + MD5v3Key + + + + 2736 + iDRAC.Embedded.1 + iDRAC Users + Users.12 + iDRAC.Embedded.1#Users.12#MD5v3Key + false + 32 + 0 + + + + Salt String Appended To Password Prior To Hash + SHA256PasswordSalt + + + + 2737 + iDRAC.Embedded.1 + iDRAC Users + Users.12 + iDRAC.Embedded.1#Users.12#SHA256PasswordSalt + false + 32 + 0 + + + + User Admin User Name + UserName + + + + 371 + iDRAC.Embedded.1 + iDRAC Users + Users.13 + iDRAC.Embedded.1#Users.13#UserName + false + 16 + 0 + + + + SHA256 hash of the password + SHA256Password + + + + 2744 + iDRAC.Embedded.1 + iDRAC Users + Users.13 + iDRAC.Embedded.1#Users.13#SHA256Password + false + 64 + 0 + + + + SHA1 Hash of the SNMPv3 Key + SHA1v3Key + + + + 2745 + iDRAC.Embedded.1 + iDRAC Users + Users.13 + iDRAC.Embedded.1#Users.13#SHA1v3Key + false + 40 + 0 + + + + MD5 Hash of the SNMPv3 key + MD5v3Key + + + + 2746 + iDRAC.Embedded.1 + iDRAC Users + Users.13 + iDRAC.Embedded.1#Users.13#MD5v3Key + false + 32 + 0 + + + + Salt String Appended To Password Prior To Hash + SHA256PasswordSalt + + + + 2747 + iDRAC.Embedded.1 + iDRAC Users + Users.13 + iDRAC.Embedded.1#Users.13#SHA256PasswordSalt + false + 32 + 0 + + + + User Admin User Name + UserName + + + + 381 + iDRAC.Embedded.1 + iDRAC Users + Users.14 + iDRAC.Embedded.1#Users.14#UserName + false + 16 + 0 + + + + SHA256 hash of the password + SHA256Password + + + + 2754 + iDRAC.Embedded.1 + iDRAC Users + Users.14 + iDRAC.Embedded.1#Users.14#SHA256Password + false + 64 + 0 + + + + SHA1 Hash of the SNMPv3 Key + SHA1v3Key + + + + 2755 + iDRAC.Embedded.1 + iDRAC Users + Users.14 + iDRAC.Embedded.1#Users.14#SHA1v3Key + false + 40 + 0 + + + + MD5 Hash of the SNMPv3 key + MD5v3Key + + + + 2756 + iDRAC.Embedded.1 + iDRAC Users + Users.14 + iDRAC.Embedded.1#Users.14#MD5v3Key + false + 32 + 0 + + + + Salt String Appended To Password Prior To Hash + SHA256PasswordSalt + + + + 2757 + iDRAC.Embedded.1 + iDRAC Users + Users.14 + iDRAC.Embedded.1#Users.14#SHA256PasswordSalt + false + 32 + 0 + + + + User Admin User Name + UserName + + + + 391 + iDRAC.Embedded.1 + iDRAC Users + Users.15 + iDRAC.Embedded.1#Users.15#UserName + false + 16 + 0 + + + + SHA256 hash of the password + SHA256Password + + + + 2764 + iDRAC.Embedded.1 + iDRAC Users + Users.15 + iDRAC.Embedded.1#Users.15#SHA256Password + false + 64 + 0 + + + + SHA1 Hash of the SNMPv3 Key + SHA1v3Key + + + + 2765 + iDRAC.Embedded.1 + iDRAC Users + Users.15 + iDRAC.Embedded.1#Users.15#SHA1v3Key + false + 40 + 0 + + + + MD5 Hash of the SNMPv3 key + MD5v3Key + + + + 2766 + iDRAC.Embedded.1 + iDRAC Users + Users.15 + iDRAC.Embedded.1#Users.15#MD5v3Key + false + 32 + 0 + + + + Salt String Appended To Password Prior To Hash + SHA256PasswordSalt + + + + 2767 + iDRAC.Embedded.1 + iDRAC Users + Users.15 + iDRAC.Embedded.1#Users.15#SHA256PasswordSalt + false + 32 + 0 + + + + User Admin User Name + UserName + + + + 401 + iDRAC.Embedded.1 + iDRAC Users + Users.16 + iDRAC.Embedded.1#Users.16#UserName + false + 16 + 0 + + + + SHA256 hash of the password + SHA256Password + + + + 2774 + iDRAC.Embedded.1 + iDRAC Users + Users.16 + iDRAC.Embedded.1#Users.16#SHA256Password + false + 64 + 0 + + + + SHA1 Hash of the SNMPv3 Key + SHA1v3Key + + + + 2775 + iDRAC.Embedded.1 + iDRAC Users + Users.16 + iDRAC.Embedded.1#Users.16#SHA1v3Key + false + 40 + 0 + + + + MD5 Hash of the SNMPv3 key + MD5v3Key + + + + 2776 + iDRAC.Embedded.1 + iDRAC Users + Users.16 + iDRAC.Embedded.1#Users.16#MD5v3Key + false + 32 + 0 + + + + Salt String Appended To Password Prior To Hash + SHA256PasswordSalt + + + + 2777 + iDRAC.Embedded.1 + iDRAC Users + Users.16 + iDRAC.Embedded.1#Users.16#SHA256PasswordSalt + false + 32 + 0 + + + + Firmware Update IP Address + FwUpdateIPAddr + 0.0.0.0 + 0.0.0.0 + + 452 + iDRAC.Embedded.1 + Firmware Update + Update.1 + iDRAC.Embedded.1#Update.1#FwUpdateIPAddr + false + 255 + 0 + + + + Firmware Update File Path + FwUpdatePath + + + + 453 + iDRAC.Embedded.1 + Firmware Update + Update.1 + iDRAC.Embedded.1#Update.1#FwUpdatePath + false + 255 + 0 + + + + Email Alert Address + Address + + + + 472 + iDRAC.Embedded.1 + RAC Email Alert + EmailAlert.1 + iDRAC.Embedded.1#EmailAlert.1#Address + false + 64 + 0 + + + + Email Alert Custom Message + CustomMsg + + + + 473 + iDRAC.Embedded.1 + RAC Email Alert + EmailAlert.1 + iDRAC.Embedded.1#EmailAlert.1#CustomMsg + false + 32 + 0 + + + + Email Alert Address + Address + + + + 492 + iDRAC.Embedded.1 + RAC Email Alert + EmailAlert.2 + iDRAC.Embedded.1#EmailAlert.2#Address + false + 64 + 0 + + + + Email Alert Custom Message + CustomMsg + + + + 493 + iDRAC.Embedded.1 + RAC Email Alert + EmailAlert.2 + iDRAC.Embedded.1#EmailAlert.2#CustomMsg + false + 32 + 0 + + + + Email Alert Address + Address + + + + 512 + iDRAC.Embedded.1 + RAC Email Alert + EmailAlert.3 + iDRAC.Embedded.1#EmailAlert.3#Address + false + 64 + 0 + + + + Email Alert Custom Message + CustomMsg + + + + 513 + iDRAC.Embedded.1 + RAC Email Alert + EmailAlert.3 + iDRAC.Embedded.1#EmailAlert.3#CustomMsg + false + 32 + 0 + + + + Email Alert Address + Address + + + + 522 + iDRAC.Embedded.1 + RAC Email Alert + EmailAlert.4 + iDRAC.Embedded.1#EmailAlert.4#Address + false + 64 + 0 + + + + Email Alert Custom Message + CustomMsg + + + + 523 + iDRAC.Embedded.1 + RAC Email Alert + EmailAlert.4 + iDRAC.Embedded.1#EmailAlert.4#CustomMsg + false + 32 + 0 + + + + SMTP Server IP Address + SMTPServerIPAddress + 10.224.39.20 + 0.0.0.0 + + 541 + iDRAC.Embedded.1 + RAC Remote Hosts + RemoteHosts.1 + iDRAC.Embedded.1#RemoteHosts.1#SMTPServerIPAddress + false + 255 + 0 + + + + SMTP User Name + SMTPUserName + + + + 544 + iDRAC.Embedded.1 + RAC Remote Hosts + RemoteHosts.1 + iDRAC.Embedded.1#RemoteHosts.1#SMTPUserName + false + 50 + 0 + + + + Serial Console Command + Command + + + + 606 + iDRAC.Embedded.1 + Serial Configuration + Serial.1 + iDRAC.Embedded.1#Serial.1#Command + false + 128 + 0 + + + + Serial Console Quit Key + QuitKey + ^\ + ^\ + + 612 + iDRAC.Embedded.1 + RAC Serial Redirection + SerialRedirection.1 + iDRAC.Embedded.1#SerialRedirection.1#QuitKey + false + 2 + 0 + + + + SNMP Agent Community + AgentCommunity + WYSkmGB8 + public + + 702 + iDRAC.Embedded.1 + SNMP Configuration + SNMP.1 + iDRAC.Embedded.1#SNMP.1#AgentCommunity + false + 31 + 0 + + + + Tune IP Range Address + RangeAddr + 192.168.1.1 + 192.168.1.1 + + 722 + iDRAC.Embedded.1 + IP Blocking + IPBlocking.1 + iDRAC.Embedded.1#IPBlocking.1#RangeAddr + false + 16 + 0 + + + + Tune IP Range Mask + RangeMask + 255.255.255.0 + 255.255.255.0 + + 723 + iDRAC.Embedded.1 + IP Blocking + IPBlocking.1 + iDRAC.Embedded.1#IPBlocking.1#RangeMask + false + 16 + 0 + + + + Time Zone String + TimeZone + CST6CDT + US/Central + + 753 + iDRAC.Embedded.1 + Time Zone Configuration Information + Time.1 + iDRAC.Embedded.1#Time.1#TimeZone + false + 32 + 0 + + + + CSR Common Name + CsrCommonName + + + + 761 + iDRAC.Embedded.1 + RAC Certificate + Security.1 + iDRAC.Embedded.1#Security.1#CsrCommonName + false + 254 + 0 + + + + CSR Organization Name + CsrOrganizationName + + + + 762 + iDRAC.Embedded.1 + RAC Certificate + Security.1 + iDRAC.Embedded.1#Security.1#CsrOrganizationName + false + 254 + 0 + + + + CSR Organization Unit + CsrOrganizationUnit + + + + 763 + iDRAC.Embedded.1 + RAC Certificate + Security.1 + iDRAC.Embedded.1#Security.1#CsrOrganizationUnit + false + 254 + 0 + + + + CSR Locality Name + CsrLocalityName + + + + 764 + iDRAC.Embedded.1 + RAC Certificate + Security.1 + iDRAC.Embedded.1#Security.1#CsrLocalityName + false + 254 + 0 + + + + CSR State Name + CsrStateName + + + + 765 + iDRAC.Embedded.1 + RAC Certificate + Security.1 + iDRAC.Embedded.1#Security.1#CsrStateName + false + 254 + 0 + + + + CSR Country Code + CsrCountryCode + US + US + + 766 + iDRAC.Embedded.1 + RAC Certificate + Security.1 + iDRAC.Embedded.1#Security.1#CsrCountryCode + false + 2 + 0 + + + + CSR Email Address + CsrEmailAddr + + + + 767 + iDRAC.Embedded.1 + RAC Certificate + Security.1 + iDRAC.Embedded.1#Security.1#CsrEmailAddr + false + 254 + 0 + + + + LDAP Server + Server + + + + 1082 + iDRAC.Embedded.1 + LDAP + LDAP.1 + iDRAC.Embedded.1#LDAP.1#Server + false + 1024 + 0 + + + + LDAP Base Domain Name + BaseDN + + + + 1084 + iDRAC.Embedded.1 + LDAP + LDAP.1 + iDRAC.Embedded.1#LDAP.1#BaseDN + false + 254 + 0 + + + + LDAP User Attribute + UserAttribute + + + + 1085 + iDRAC.Embedded.1 + LDAP + LDAP.1 + iDRAC.Embedded.1#LDAP.1#UserAttribute + false + 254 + 0 + + + + LDAP Group Attribute + GroupAttribute + + + + 1086 + iDRAC.Embedded.1 + LDAP + LDAP.1 + iDRAC.Embedded.1#LDAP.1#GroupAttribute + false + 254 + 0 + + + + LDAP Bind User Distinguished Name + BindDN + + + + 1088 + iDRAC.Embedded.1 + LDAP + LDAP.1 + iDRAC.Embedded.1#LDAP.1#BindDN + false + 254 + 0 + + + + LDAP Search Filter + SearchFilter + + + + 1090 + iDRAC.Embedded.1 + LDAP + LDAP.1 + iDRAC.Embedded.1#LDAP.1#SearchFilter + false + 1024 + 0 + + + + Active Directory RAC Name + RacName + + + + 772 + iDRAC.Embedded.1 + Active Directory + ActiveDirectory.1 + iDRAC.Embedded.1#ActiveDirectory.1#RacName + false + 254 + 0 + + + + Active Directory RAC Domain + RacDomain + + + + 773 + iDRAC.Embedded.1 + Active Directory + ActiveDirectory.1 + iDRAC.Embedded.1#ActiveDirectory.1#RacDomain + false + 254 + 0 + + + + Domain Controller 1 + DomainController1 + + + + 776 + iDRAC.Embedded.1 + Active Directory + ActiveDirectory.1 + iDRAC.Embedded.1#ActiveDirectory.1#DomainController1 + false + 254 + 0 + + + + Domain Controller 2 + DomainController2 + + + + 777 + iDRAC.Embedded.1 + Active Directory + ActiveDirectory.1 + iDRAC.Embedded.1#ActiveDirectory.1#DomainController2 + false + 254 + 0 + + + + Domain Controller 3 + DomainController3 + + + + 778 + iDRAC.Embedded.1 + Active Directory + ActiveDirectory.1 + iDRAC.Embedded.1#ActiveDirectory.1#DomainController3 + false + 254 + 0 + + + + Global Catalog 1 + GlobalCatalog1 + + + + 779 + iDRAC.Embedded.1 + Active Directory + ActiveDirectory.1 + iDRAC.Embedded.1#ActiveDirectory.1#GlobalCatalog1 + false + 254 + 0 + + + + Global Catalog 2 + GlobalCatalog2 + + + + 780 + iDRAC.Embedded.1 + Active Directory + ActiveDirectory.1 + iDRAC.Embedded.1#ActiveDirectory.1#GlobalCatalog2 + false + 254 + 0 + + + + Global Catalog 3 + GlobalCatalog3 + + + + 781 + iDRAC.Embedded.1 + Active Directory + ActiveDirectory.1 + iDRAC.Embedded.1#ActiveDirectory.1#GlobalCatalog3 + false + 254 + 0 + + + + Active Directory Root Domain + GCRootDomain + + + + 786 + iDRAC.Embedded.1 + Active Directory + ActiveDirectory.1 + iDRAC.Embedded.1#ActiveDirectory.1#GCRootDomain + false + 254 + 0 + + + + Active Directory Lookup Domain Name + DCLookupDomainName + + + + 787 + iDRAC.Embedded.1 + Active Directory + ActiveDirectory.1 + iDRAC.Embedded.1#ActiveDirectory.1#DCLookupDomainName + false + 254 + 0 + + + + AD Role Group Name + Name + + + + 801 + iDRAC.Embedded.1 + AD Group Configuration + ADGroup.1 + iDRAC.Embedded.1#ADGroup.1#Name + false + 254 + 0 + + + + AD Group Domain + Domain + + + + 802 + iDRAC.Embedded.1 + AD Group Configuration + ADGroup.1 + iDRAC.Embedded.1#ADGroup.1#Domain + false + 254 + 0 + + + + AD Role Group Name + Name + + + + 811 + iDRAC.Embedded.1 + AD Group Configuration + ADGroup.2 + iDRAC.Embedded.1#ADGroup.2#Name + false + 254 + 0 + + + + AD Group Domain + Domain + + + + 812 + iDRAC.Embedded.1 + AD Group Configuration + ADGroup.2 + iDRAC.Embedded.1#ADGroup.2#Domain + false + 254 + 0 + + + + AD Role Group Name + Name + + + + 821 + iDRAC.Embedded.1 + AD Group Configuration + ADGroup.3 + iDRAC.Embedded.1#ADGroup.3#Name + false + 254 + 0 + + + + AD Group Domain + Domain + + + + 822 + iDRAC.Embedded.1 + AD Group Configuration + ADGroup.3 + iDRAC.Embedded.1#ADGroup.3#Domain + false + 254 + 0 + + + + AD Role Group Name + Name + + + + 831 + iDRAC.Embedded.1 + ADGroup Configuration + ADGroup.4 + iDRAC.Embedded.1#ADGroup.4#Name + false + 254 + 0 + + + + AD Group Domain + Domain + + + + 832 + iDRAC.Embedded.1 + ADGroup Configuration + ADGroup.4 + iDRAC.Embedded.1#ADGroup.4#Domain + false + 254 + 0 + + + + AD Role Group Name + Name + + + + 841 + iDRAC.Embedded.1 + ADGroup Configuration + ADGroup.5 + iDRAC.Embedded.1#ADGroup.5#Name + false + 254 + 0 + + + + AD Group Domain + Domain + + + + 842 + iDRAC.Embedded.1 + ADGroup Configuration + ADGroup.5 + iDRAC.Embedded.1#ADGroup.5#Domain + false + 254 + 0 + + + + User Domain Name + Name + + + + 851 + iDRAC.Embedded.1 + User Domain + UserDomain.1 + iDRAC.Embedded.1#UserDomain.1#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 856 + iDRAC.Embedded.1 + User Domain + UserDomain.2 + iDRAC.Embedded.1#UserDomain.2#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 861 + iDRAC.Embedded.1 + User Domain + UserDomain.3 + iDRAC.Embedded.1#UserDomain.3#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 866 + iDRAC.Embedded.1 + User Domain + UserDomain.4 + iDRAC.Embedded.1#UserDomain.4#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 871 + iDRAC.Embedded.1 + User Domain + UserDomain.5 + iDRAC.Embedded.1#UserDomain.5#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 876 + iDRAC.Embedded.1 + User Domain + UserDomain.6 + iDRAC.Embedded.1#UserDomain.6#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 881 + iDRAC.Embedded.1 + User Domain + UserDomain.7 + iDRAC.Embedded.1#UserDomain.7#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 886 + iDRAC.Embedded.1 + User Domain + UserDomain.8 + iDRAC.Embedded.1#UserDomain.8#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 891 + iDRAC.Embedded.1 + User Domain + UserDomain.9 + iDRAC.Embedded.1#UserDomain.9#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 896 + iDRAC.Embedded.1 + User Domain + UserDomain.10 + iDRAC.Embedded.1#UserDomain.10#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 901 + iDRAC.Embedded.1 + User Domain + UserDomain.11 + iDRAC.Embedded.1#UserDomain.11#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 906 + iDRAC.Embedded.1 + User Domain + UserDomain.12 + iDRAC.Embedded.1#UserDomain.12#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 911 + iDRAC.Embedded.1 + User Domain + UserDomain.13 + iDRAC.Embedded.1#UserDomain.13#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 916 + iDRAC.Embedded.1 + User Domain + UserDomain.14 + iDRAC.Embedded.1#UserDomain.14#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 921 + iDRAC.Embedded.1 + User Domain + UserDomain.15 + iDRAC.Embedded.1#UserDomain.15#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 926 + iDRAC.Embedded.1 + User Domain + UserDomain.16 + iDRAC.Embedded.1#UserDomain.16#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 931 + iDRAC.Embedded.1 + User Domain + UserDomain.17 + iDRAC.Embedded.1#UserDomain.17#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 936 + iDRAC.Embedded.1 + User Domain + UserDomain.18 + iDRAC.Embedded.1#UserDomain.18#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 941 + iDRAC.Embedded.1 + User Domain + UserDomain.19 + iDRAC.Embedded.1#UserDomain.19#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 946 + iDRAC.Embedded.1 + User Domain + UserDomain.20 + iDRAC.Embedded.1#UserDomain.20#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 951 + iDRAC.Embedded.1 + User Domain + UserDomain.21 + iDRAC.Embedded.1#UserDomain.21#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 956 + iDRAC.Embedded.1 + User Domain + UserDomain.22 + iDRAC.Embedded.1#UserDomain.22#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 961 + iDRAC.Embedded.1 + User Domain + UserDomain.23 + iDRAC.Embedded.1#UserDomain.23#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 966 + iDRAC.Embedded.1 + User Domain + UserDomain.24 + iDRAC.Embedded.1#UserDomain.24#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 971 + iDRAC.Embedded.1 + User Domain + UserDomain.25 + iDRAC.Embedded.1#UserDomain.25#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 976 + iDRAC.Embedded.1 + User Domain + UserDomain.26 + iDRAC.Embedded.1#UserDomain.26#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 981 + iDRAC.Embedded.1 + User Domain + UserDomain.27 + iDRAC.Embedded.1#UserDomain.27#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 986 + iDRAC.Embedded.1 + User Domain + UserDomain.28 + iDRAC.Embedded.1#UserDomain.28#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 991 + iDRAC.Embedded.1 + User Domain + UserDomain.29 + iDRAC.Embedded.1#UserDomain.29#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 996 + iDRAC.Embedded.1 + User Domain + UserDomain.30 + iDRAC.Embedded.1#UserDomain.30#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 1001 + iDRAC.Embedded.1 + User Domain + UserDomain.31 + iDRAC.Embedded.1#UserDomain.31#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 1006 + iDRAC.Embedded.1 + User Domain + UserDomain.32 + iDRAC.Embedded.1#UserDomain.32#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 1011 + iDRAC.Embedded.1 + User Domain + UserDomain.33 + iDRAC.Embedded.1#UserDomain.33#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 1016 + iDRAC.Embedded.1 + User Domain + UserDomain.34 + iDRAC.Embedded.1#UserDomain.34#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 1021 + iDRAC.Embedded.1 + User Domain + UserDomain.35 + iDRAC.Embedded.1#UserDomain.35#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 1026 + iDRAC.Embedded.1 + User Domain + UserDomain.36 + iDRAC.Embedded.1#UserDomain.36#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 1031 + iDRAC.Embedded.1 + User Domain + UserDomain.37 + iDRAC.Embedded.1#UserDomain.37#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 1036 + iDRAC.Embedded.1 + User Domain + UserDomain.38 + iDRAC.Embedded.1#UserDomain.38#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 1041 + iDRAC.Embedded.1 + User Domain + UserDomain.39 + iDRAC.Embedded.1#UserDomain.39#Name + false + 255 + 0 + + + + User Domain Name + Name + + + + 1046 + iDRAC.Embedded.1 + User Domain + UserDomain.40 + iDRAC.Embedded.1#UserDomain.40#Name + false + 255 + 0 + + + + Sys Log Server 1 + Server1 + + + + 1073 + iDRAC.Embedded.1 + Sys Log + SysLog.1 + iDRAC.Embedded.1#SysLog.1#Server1 + false + 63 + 0 + + + + Sys Log Server 2 + Server2 + + + + 1074 + iDRAC.Embedded.1 + Sys Log + SysLog.1 + iDRAC.Embedded.1#SysLog.1#Server2 + false + 63 + 0 + + + + Sys Log Server 3 + Server3 + + + + 1075 + iDRAC.Embedded.1 + Sys Log + SysLog.1 + iDRAC.Embedded.1#SysLog.1#Server3 + false + 63 + 0 + + + + LDAP Role Group Domain Name + DN + + + + 1101 + iDRAC.Embedded.1 + LDAP Group + LDAPRoleGroup.1 + iDRAC.Embedded.1#LDAPRoleGroup.1#DN + false + 1024 + 0 + + + + LDAP Role Group Domain Name + DN + + + + 1111 + iDRAC.Embedded.1 + LDAP Group + LDAPRoleGroup.2 + iDRAC.Embedded.1#LDAPRoleGroup.2#DN + false + 1024 + 0 + + + + LDAP Role Group Domain Name + DN + + + + 1121 + iDRAC.Embedded.1 + LDAP Group + LDAPRoleGroup.3 + iDRAC.Embedded.1#LDAPRoleGroup.3#DN + false + 1024 + 0 + + + + LDAP Role Group Domain Name + DN + + + + 1131 + iDRAC.Embedded.1 + LDAP Group + LDAPRoleGroup.4 + iDRAC.Embedded.1#LDAPRoleGroup.4#DN + false + 1024 + 0 + + + + LDAP Role Group Domain Name + DN + + + + 1141 + iDRAC.Embedded.1 + LDAP Group + LDAPRoleGroup.5 + iDRAC.Embedded.1#LDAPRoleGroup.5#DN + false + 1024 + 0 + + + + Destination IPv6 Address + DestIPv6Addr + :: + :: + + 1153 + iDRAC.Embedded.1 + SNMP Trap IPv6 + SNMPTrapIPv6.1 + iDRAC.Embedded.1#SNMPTrapIPv6.1#DestIPv6Addr + false + 39 + 0 + + + + Destination IPv6 Address + DestIPv6Addr + :: + :: + + 1163 + iDRAC.Embedded.1 + SNMP Trap IPv6 + SNMPTrapIPv6.2 + iDRAC.Embedded.1#SNMPTrapIPv6.2#DestIPv6Addr + false + 39 + 0 + + + + Destination IPv6 Address + DestIPv6Addr + :: + :: + + 1173 + iDRAC.Embedded.1 + SNMP Trap IPv6 + SNMPTrapIPv6.3 + iDRAC.Embedded.1#SNMPTrapIPv6.3#DestIPv6Addr + false + 39 + 0 + + + + Destination IPv6 Address + DestIPv6Addr + :: + :: + + 1183 + iDRAC.Embedded.1 + SNMP Trap IPv6 + SNMPTrapIPv6.4 + iDRAC.Embedded.1#SNMPTrapIPv6.4#DestIPv6Addr + false + 39 + 0 + + + + Destination IPv4 Address + DestIPv4Addr + 0.0.0.0 + 0.0.0.0 + + 1193 + iDRAC.Embedded.1 + SNMP Trap IPv4 + SNMPTrapIPv4.1 + iDRAC.Embedded.1#SNMPTrapIPv4.1#DestIPv4Addr + false + 15 + 0 + + + + Destination IPv4 Address + DestIPv4Addr + 0.0.0.0 + 0.0.0.0 + + 1203 + iDRAC.Embedded.1 + SNMP Trap IPv4 + SNMPTrapIPv4.2 + iDRAC.Embedded.1#SNMPTrapIPv4.2#DestIPv4Addr + false + 15 + 0 + + + + Destination IPv4 Address + DestIPv4Addr + 0.0.0.0 + 0.0.0.0 + + 1213 + iDRAC.Embedded.1 + SNMP Trap IPv4 + SNMPTrapIPv4.3 + iDRAC.Embedded.1#SNMPTrapIPv4.3#DestIPv4Addr + false + 15 + 0 + + + + Destination IPv4 Address + DestIPv4Addr + 0.0.0.0 + 0.0.0.0 + + 1223 + iDRAC.Embedded.1 + SNMP Trap IPv4 + SNMPTrapIPv4.4 + iDRAC.Embedded.1#SNMPTrapIPv4.4#DestIPv4Addr + false + 15 + 0 + + + + iDRAC Remote File Share Image Path + Image + + + + 1233 + iDRAC.Embedded.1 + Remote File Share + RFS.1 + iDRAC.Embedded.1#RFS.1#Image + true + 255 + 0 + + + + OS-BMC PT HOST IP Address + OsIpAddress + 0.0.0.0 + 0.0.0.0 + + 1243 + iDRAC.Embedded.1 + OS-BMC Passthru Configuration + OS-BMC.1 + iDRAC.Embedded.1#OS-BMC.1#OsIpAddress + false + 16 + 0 + + + + USB NIC IP Address + UsbNicIpAddress + 169.254.0.1 + 169.254.0.1 + + 1245 + iDRAC.Embedded.1 + OS-BMC Passthru Configuration + OS-BMC.1 + iDRAC.Embedded.1#OS-BMC.1#UsbNicIpAddress + false + 16 + 0 + + + + Alert Destination + Destination + 0.0.0.0 + 0.0.0.0 + + 1601 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.1 + iDRAC.Embedded.1#SNMPAlert.1#Destination + false + 255 + 0 + + + + SNMP V3 Username + SNMPv3Username + + + + 1603 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.1 + iDRAC.Embedded.1#SNMPAlert.1#SNMPv3Username + false + 16 + 0 + + + + Alert Destination + Destination + 0.0.0.0 + 0.0.0.0 + + 1603 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.2 + iDRAC.Embedded.1#SNMPAlert.2#Destination + false + 255 + 0 + + + + SNMP V3 Username + SNMPv3Username + + + + 1603 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.2 + iDRAC.Embedded.1#SNMPAlert.2#SNMPv3Username + false + 16 + 0 + + + + Alert Destination + Destination + 0.0.0.0 + 0.0.0.0 + + 1605 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.3 + iDRAC.Embedded.1#SNMPAlert.3#Destination + false + 255 + 0 + + + + SNMP V3 Username + SNMPv3Username + + + + 1603 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.3 + iDRAC.Embedded.1#SNMPAlert.3#SNMPv3Username + false + 16 + 0 + + + + Alert Destination + Destination + 0.0.0.0 + 0.0.0.0 + + 1607 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.4 + iDRAC.Embedded.1#SNMPAlert.4#Destination + false + 255 + 0 + + + + SNMP V3 Username + SNMPv3Username + + + + 1609 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.4 + iDRAC.Embedded.1#SNMPAlert.4#SNMPv3Username + false + 16 + 0 + + + + Alert Destination + Destination + :: + :: + + 1609 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.5 + iDRAC.Embedded.1#SNMPAlert.5#Destination + false + 255 + 0 + + + + SNMP V3 Username + SNMPv3Username + + + + 1611 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.5 + iDRAC.Embedded.1#SNMPAlert.5#SNMPv3Username + false + 16 + 0 + + + + Alert Destination + Destination + :: + :: + + 1611 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.6 + iDRAC.Embedded.1#SNMPAlert.6#Destination + false + 255 + 0 + + + + SNMP V3 Username + SNMPv3Username + + + + 1613 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.6 + iDRAC.Embedded.1#SNMPAlert.6#SNMPv3Username + false + 16 + 0 + + + + Alert Destination + Destination + :: + :: + + 1613 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.7 + iDRAC.Embedded.1#SNMPAlert.7#Destination + false + 255 + 0 + + + + SNMP V3 Username + SNMPv3Username + + + + 1615 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.7 + iDRAC.Embedded.1#SNMPAlert.7#SNMPv3Username + false + 16 + 0 + + + + Alert Destination + Destination + :: + :: + + 1615 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.8 + iDRAC.Embedded.1#SNMPAlert.8#Destination + false + 255 + 0 + + + + SNMP V3 Username + SNMPv3Username + + + + 1617 + iDRAC.Embedded.1 + SNMP Alert Destination + SNMPAlert.8 + iDRAC.Embedded.1#SNMPAlert.8#SNMPv3Username + false + 16 + 0 + + + + NTP Server 1 + NTP1 + + + + 2001 + iDRAC.Embedded.1 + NTP Configuration Group + NTPConfigGroup.1 + iDRAC.Embedded.1#NTPConfigGroup.1#NTP1 + false + 254 + 0 + + + + NTP server 2 + NTP2 + + + + 2002 + iDRAC.Embedded.1 + NTP Configuration Group + NTPConfigGroup.1 + iDRAC.Embedded.1#NTPConfigGroup.1#NTP2 + false + 254 + 0 + + + + NTP server 3 + NTP3 + + + + 2003 + iDRAC.Embedded.1 + NTP Configuration Group + NTPConfigGroup.1 + iDRAC.Embedded.1#NTPConfigGroup.1#NTP3 + false + 254 + 0 + + + + CSC CSR Common Name + CSCCsrCommonName + + + + 2100 + iDRAC.Embedded.1 + iDRAC Custom Signing Certificate + SecurityCSC.1 + iDRAC.Embedded.1#SecurityCSC.1#CSCCsrCommonName + false + 64 + 0 + + + + CSC CSR Business Name + CSCCsrBusiness + + + + 2101 + iDRAC.Embedded.1 + iDRAC Custom Signing Certificate + SecurityCSC.1 + iDRAC.Embedded.1#SecurityCSC.1#CSCCsrBusiness + false + 64 + 0 + + + + CSC CSR Department Name + CSCCsrDeptName + + + + 2102 + iDRAC.Embedded.1 + iDRAC Custom Signing Certificate + SecurityCSC.1 + iDRAC.Embedded.1#SecurityCSC.1#CSCCsrDeptName + false + 64 + 0 + + + + CSC CSR City Name + CSCCsrCityName + + + + 2103 + iDRAC.Embedded.1 + iDRAC Custom Signing Certificate + SecurityCSC.1 + iDRAC.Embedded.1#SecurityCSC.1#CSCCsrCityName + false + 64 + 0 + + + + CSC CSR State Name + CSCCsrStateName + + + + 2104 + iDRAC.Embedded.1 + iDRAC Custom Signing Certificate + SecurityCSC.1 + iDRAC.Embedded.1#SecurityCSC.1#CSCCsrStateName + false + 64 + 0 + + + + CSC CSR Country Code + CSCCsrCountryCode + + + + 2105 + iDRAC.Embedded.1 + iDRAC Custom Signing Certificate + SecurityCSC.1 + iDRAC.Embedded.1#SecurityCSC.1#CSCCsrCountryCode + false + 2 + 0 + + + + CSC CSR Email Address + CSCCsrEmailAddr + + + + 2106 + iDRAC.Embedded.1 + iDRAC Custom Signing Certificate + SecurityCSC.1 + iDRAC.Embedded.1#SecurityCSC.1#CSCCsrEmailAddr + false + 64 + 0 + + + + IPv6 URL + URL + + + + 2120 + iDRAC.Embedded.1 + iDRAC IPv6 URL + IPv6URL.1 + iDRAC.Embedded.1#IPv6URL.1#URL + true + 80 + 0 + + + + Version of installed ServiceModule + ServiceModuleVersion + NA + NA + + 2158 + iDRAC.Embedded.1 + ServiceModule + ServiceModule.1 + iDRAC.Embedded.1#ServiceModule.1#ServiceModuleVersion + true + 256 + 0 + + + + First Boot Device + FirstBootDevice + Normal + + + 2190 + iDRAC.Embedded.1 + Server Boot + ServerBoot.1 + iDRAC.Embedded.1#ServerBoot.1#FirstBootDevice + false + 65 + 0 + + + + User Admin Password + Password + ****** + + + 252 + iDRAC.Embedded.1 + iDRAC Users + Users.1 + iDRAC.Embedded.1#Users.1#Password + true + 20 + 0 + + + + User Admin Password + Password + ****** + + + 262 + iDRAC.Embedded.1 + iDRAC Users + Users.2 + iDRAC.Embedded.1#Users.2#Password + false + 20 + 0 + + + + User Admin Password + Password + ****** + + + 272 + iDRAC.Embedded.1 + iDRAC Users + Users.3 + iDRAC.Embedded.1#Users.3#Password + false + 20 + 0 + + + + User Admin Password + Password + ****** + + + 282 + iDRAC.Embedded.1 + iDRAC Users + Users.4 + iDRAC.Embedded.1#Users.4#Password + false + 20 + 0 + + + + User Admin Password + Password + ****** + + + 292 + iDRAC.Embedded.1 + iDRAC Users + Users.5 + iDRAC.Embedded.1#Users.5#Password + false + 20 + 0 + + + + User Admin Password + Password + ****** + + + 302 + iDRAC.Embedded.1 + iDRAC Users + Users.6 + iDRAC.Embedded.1#Users.6#Password + false + 20 + 0 + + + + User Admin Password + Password + ****** + + + 312 + iDRAC.Embedded.1 + iDRAC Users + Users.7 + iDRAC.Embedded.1#Users.7#Password + false + 20 + 0 + + + + User Admin Password + Password + ****** + + + 322 + iDRAC.Embedded.1 + iDRAC Users + Users.8 + iDRAC.Embedded.1#Users.8#Password + false + 20 + 0 + + + + User Admin Password + Password + ****** + + + 332 + iDRAC.Embedded.1 + iDRAC Users + Users.9 + iDRAC.Embedded.1#Users.9#Password + false + 20 + 0 + + + + User Admin Password + Password + ****** + + + 342 + iDRAC.Embedded.1 + iDRAC Users + Users.10 + iDRAC.Embedded.1#Users.10#Password + false + 20 + 0 + + + + User Admin Password + Password + ****** + + + 352 + iDRAC.Embedded.1 + iDRAC Users + Users.11 + iDRAC.Embedded.1#Users.11#Password + false + 20 + 0 + + + + User Admin Password + Password + ****** + + + 362 + iDRAC.Embedded.1 + iDRAC Users + Users.12 + iDRAC.Embedded.1#Users.12#Password + false + 20 + 0 + + + + User Admin Password + Password + ****** + + + 372 + iDRAC.Embedded.1 + iDRAC Users + Users.13 + iDRAC.Embedded.1#Users.13#Password + false + 20 + 0 + + + + User Admin Password + Password + ****** + + + 382 + iDRAC.Embedded.1 + iDRAC Users + Users.14 + iDRAC.Embedded.1#Users.14#Password + false + 20 + 0 + + + + User Admin Password + Password + ****** + + + 392 + iDRAC.Embedded.1 + iDRAC Users + Users.15 + iDRAC.Embedded.1#Users.15#Password + false + 20 + 0 + + + + User Admin Password + Password + ****** + + + 402 + iDRAC.Embedded.1 + iDRAC Users + Users.16 + iDRAC.Embedded.1#Users.16#Password + false + 20 + 0 + + + + SMTP Password + SMTPPassword + ****** + + + 545 + iDRAC.Embedded.1 + RAC Remote Hosts + RemoteHosts.1 + iDRAC.Embedded.1#RemoteHosts.1#SMTPPassword + false + 50 + 0 + + + + LDAP Bind Password + BindPassword + ****** + + + 1089 + iDRAC.Embedded.1 + LDAP + LDAP.1 + iDRAC.Embedded.1#LDAP.1#BindPassword + false + 254 + 0 + + + + Password + Password + ****** + NULL + + 2163 + iDRAC.Embedded.1 + RAC VNC Server + VNCServer.1 + iDRAC.Embedded.1#VNCServer.1#Password + false + 8 + 0 + + + + + + + + diff --git a/dracclient/tests/wsman_mocks/job_service-delete-job-id-error.xml b/dracclient/tests/wsman_mocks/job_service-delete-job-id-error.xml new file mode 100644 index 0000000..1723f51 --- /dev/null +++ b/dracclient/tests/wsman_mocks/job_service-delete-job-id-error.xml @@ -0,0 +1,21 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + + http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_JobService/DeleteJobQueueResponse + + uuid:bd334a80-bd6f-4fc9-88cc-9c9cb79d41e8 + + uuid:ce21f862-70ac-10ac-b40d-64b5b4da6618 + + + + + Invalid Job ID + SUP011 + 2 + + + \ No newline at end of file diff --git a/dracclient/tests/wsman_mocks/job_service-delete-job-id-ok.xml b/dracclient/tests/wsman_mocks/job_service-delete-job-id-ok.xml new file mode 100644 index 0000000..319225a --- /dev/null +++ b/dracclient/tests/wsman_mocks/job_service-delete-job-id-ok.xml @@ -0,0 +1,21 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + + http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_JobService/DeleteJobQueueResponse + + uuid:5f1b62ee-19d4-4679-b083-477086856c79 + + uuid:07b2e831-70ae-10ae-b56f-64b5b4da6618 + + + + + The specified job was deleted + SUP020 + 0 + + + \ No newline at end of file diff --git a/dracclient/tests/wsman_mocks/lc_enumeration-enum-ok.xml b/dracclient/tests/wsman_mocks/lc_enumeration-enum-ok.xml new file mode 100644 index 0000000..3e1d30a --- /dev/null +++ b/dracclient/tests/wsman_mocks/lc_enumeration-enum-ok.xml @@ -0,0 +1,144 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + uuid:68f2fe2e-1424-4833-9ac0-756f24db2542 + uuid:3ae5f7b2-40a9-10a9-8061-de7e4e771814 + + + + + + Collect System Inventory on Restart + Enabled + Enabled + LC.emb.1 + LifecycleController.Embedded.1#LCAttributes.1#CollectSystemInventoryOnRestart + false + + Disabled + Enabled + + + Part Configuration Update + Apply always + Apply always + LC.emb.1 + LifecycleController.Embedded.1#LCAttributes.1#PartConfigurationUpdate + false + + Disabled + Apply always + Apply only if firmware match + + + Part Firmware Update + Match firmware of replaced part + Match firmware of replaced part + LC.emb.1 + LifecycleController.Embedded.1#LCAttributes.1#PartFirmwareUpdate + false + + Disable + Allow version upgrade only + Match firmware of replaced part + + + Lifecycle Controller State + Enabled + Enabled + LC.emb.1 + LifecycleController.Embedded.1#LCAttributes.1#LifecycleControllerState + false + + Disabled + Enabled + Recovery + + + Licensed + Yes + No + LC.emb.1 + LifecycleController.Embedded.1#LCAttributes.1#Licensed + true + + No + Yes + + + Auto Discovery + Off + Off + LC.emb.1 + LifecycleController.Embedded.1#LCAttributes.1#AutoDiscovery + true + + Off + On + + + Discovery Factory Defaults + Off + Off + LC.emb.1 + LifecycleController.Embedded.1#LCAttributes.1#DiscoveryFactoryDefaults + true + + Off + On + + + IPChangeNotifyPS + Off + Off + LC.emb.1 + LifecycleController.Embedded.1#LCAttributes.1#IPChangeNotifyPS + false + + Off + On + + + BIOS Reset To Defaults Requested + False + False + LC.emb.1 + LifecycleController.Embedded.1#LCAttributes.1#BIOSRTDRequested + false + + False + True + + + Automatic Update Feature + Enabled + Disabled + LC.emb.1 + LifecycleController.Embedded.1#LCAttributes.1#AutoUpdate + false + + Disabled + Enabled + + Automatic Backup Feature + Disabled + Disabled + LC.emb.1 + LifecycleController.Embedded.1#LCAttributes.1#AutoBackup + false + + Disabled + Enabled + + + + + + + diff --git a/dracclient/tests/wsman_mocks/lc_getremoteservicesapistatus_not_ready.xml b/dracclient/tests/wsman_mocks/lc_getremoteservicesapistatus_not_ready.xml new file mode 100644 index 0000000..accd14f --- /dev/null +++ b/dracclient/tests/wsman_mocks/lc_getremoteservicesapistatus_not_ready.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_LCService/GetRemoteServicesAPIStatusResponse + uuid:3ef0c018-3169-4184-9d81-ee1a73059940 + uuid:9d5ff7cc-4fc0-1fc0-8090-98d61742a844 + + + + 5 + Lifecycle Controller Remote Services is not ready. + LC060 + 0 + 0 + 2 + 1 + + + diff --git a/dracclient/tests/wsman_mocks/lc_getremoteservicesapistatus_ready.xml b/dracclient/tests/wsman_mocks/lc_getremoteservicesapistatus_ready.xml new file mode 100644 index 0000000..c7dd1c9 --- /dev/null +++ b/dracclient/tests/wsman_mocks/lc_getremoteservicesapistatus_ready.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_LCService/GetRemoteServicesAPIStatusResponse + uuid:18745811-2782-4d30-a288-8f001a895215 + uuid:9ec203ba-4fc0-1fc0-8094-98d61742a844 + + + + 0 + Lifecycle Controller Remote Services is ready. + LC061 + 0 + 0 + 2 + 0 + + + diff --git a/dracclient/tests/wsman_mocks/lc_getremoteservicesapistatus_recovery.xml b/dracclient/tests/wsman_mocks/lc_getremoteservicesapistatus_recovery.xml new file mode 100644 index 0000000..97b3a3a --- /dev/null +++ b/dracclient/tests/wsman_mocks/lc_getremoteservicesapistatus_recovery.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_LCService/GetRemoteServicesAPIStatusResponse + uuid:18745811-2782-4d30-a288-8f001a895215 + uuid:9ec203ba-4fc0-1fc0-8094-98d61742a844 + + + + 4 + Lifecycle Controller Remote Services is not ready. + LC060 + 0 + 0 + 7 + 1 + + + diff --git a/dracclient/tests/wsman_mocks/lc_service-invoke-create_config_job-error.xml b/dracclient/tests/wsman_mocks/lc_service-invoke-create_config_job-error.xml new file mode 100644 index 0000000..c375bb7 --- /dev/null +++ b/dracclient/tests/wsman_mocks/lc_service-invoke-create_config_job-error.xml @@ -0,0 +1,17 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_LCService/CreateConfigJobResponse + uuid:80cf5e1b-b109-4ef5-87c8-5b03ce6ba117 + uuid:e57fa514-2189-1189-8ec1-a36fc6fe83b0 + + + + Configuration job already created, cannot create another config job on specified target until existing job is completed or is cancelled + LC007 + 2 + + + diff --git a/dracclient/tests/wsman_mocks/lc_service-invoke-create_config_job-ok.xml b/dracclient/tests/wsman_mocks/lc_service-invoke-create_config_job-ok.xml new file mode 100644 index 0000000..b7ec83c --- /dev/null +++ b/dracclient/tests/wsman_mocks/lc_service-invoke-create_config_job-ok.xml @@ -0,0 +1,28 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_LCService/CreateConfigJobResponse + uuid:fc2fdae5-6ac2-4338-9b2e-e69b813af829 + uuid:d7d89957-2189-1189-8ec0-a36fc6fe83b0 + + + + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + + http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_LifecycleJob + + JID_442507917525 + root/dcim + + + + + 4096 + + + diff --git a/dracclient/tests/wsman_mocks/lc_service-invoke-set_attributes-error.xml b/dracclient/tests/wsman_mocks/lc_service-invoke-set_attributes-error.xml new file mode 100644 index 0000000..c2c0b75 --- /dev/null +++ b/dracclient/tests/wsman_mocks/lc_service-invoke-set_attributes-error.xml @@ -0,0 +1,21 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + + http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_LCService/SetAttributesResponse + + uuid:bf8adefe-6fc0-456d-b97c-fd8d4aca2d6c + + uuid:84abf7b9-7176-1176-a11c-a53ffbd9bed4 + + + + + Invalid AttributeName. + LC057 + 2 + + + diff --git a/dracclient/tests/wsman_mocks/lc_service-invoke-set_attributes-ok.xml b/dracclient/tests/wsman_mocks/lc_service-invoke-set_attributes-ok.xml new file mode 100644 index 0000000..7c4ff98 --- /dev/null +++ b/dracclient/tests/wsman_mocks/lc_service-invoke-set_attributes-ok.xml @@ -0,0 +1,24 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + + http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_LCService/SetAttributesResponse + + uuid:bf8adefe-6fc0-456d-b97c-fd8d4aca2d6c + + uuid:84abf7b9-7176-1176-a11c-a53ffbd9bed4 + + + + + LC001 + The command was successful + 0 + No + Set PendingValue + + + + diff --git a/dracclient/tests/wsman_mocks/lc_string-enum-ok.xml b/dracclient/tests/wsman_mocks/lc_string-enum-ok.xml new file mode 100644 index 0000000..95662b3 --- /dev/null +++ b/dracclient/tests/wsman_mocks/lc_string-enum-ok.xml @@ -0,0 +1,55 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + uuid:d0ede1a5-1f68-4bf6-a4ed-b528e92419db + uuid:159ae3a2-40aa-10aa-8171-de7e4e771814 + + + + + + SYSID + 639 + LC.emb.1 + LifecycleController.Embedded.1#LCAttributes.1#SystemID + true + 3 + 0 + + 3 + + + VirtualAddressManagementApplication + + + LC.emb.1 + LifecycleController.Embedded.1#LCAttributes.1#VirtualAddressManagementApplication + false + 32 + 0 + + 2 + + + Provisioning Server + + LC.emb.1 + LifecycleController.Embedded.1#LCAttributes.1#ProvisioningServer + false + 255 + 0 + + 2 + + + + + + + diff --git a/dracclient/tests/wsman_mocks/nic_enumeration-enum-ok.xml b/dracclient/tests/wsman_mocks/nic_enumeration-enum-ok.xml new file mode 100644 index 0000000..a6ebf09 --- /dev/null +++ b/dracclient/tests/wsman_mocks/nic_enumeration-enum-ok.xml @@ -0,0 +1,767 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + + uuid:608d7722-0302-4feb-8080-4652e0e0ab48 + + uuid:07820ac0-71f0-11f0-a4a1-a53ffbd9bed4 + + + + + + + Link Status + LinkStatus + Connected + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:LinkStatus + true + + Disconnected + Connected + Disconnected + + Connected + + + + TCP/IP Parameters via DHCP + + TcpIpViaDHCP + Enabled + IPv6Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-3-1:TcpIpViaDHCP + false + + Disabled + Enabled + Disabled + + Enabled + + + + IP Autoconfiguration + + IpAutoConfig + Enabled + IPv4Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-3-1:IpAutoConfig + true + + Disabled + Enabled + Disabled + + Enabled + + + + iSCSI Parameters via DHCP + + IscsiViaDHCP + Enabled + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-3-1:IscsiViaDHCP + false + + Disabled + Enabled + Disabled + + Enabled + + + + CHAP Authentication + + ChapAuthEnable + Disabled + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-3-1:ChapAuthEnable + false + + Disabled + Enabled + Disabled + + Enabled + + + + Boot to iSCSI Target + + IscsiTgtBoot + Enabled + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-3-1:IscsiTgtBoot + false + + Disabled + Enabled + OneTimeDisabled + Disabled + + Enabled + + One Time Disabled + + + + Use TCP Timestamp + + TcpTimestmp + Disabled + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-3-1:TcpTimestmp + false + + Disabled + Enabled + Disabled + + Enabled + + + + Target as First HDD + + FirstHddTarget + Disabled + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-3-1:FirstHddTarget + false + + Disabled + Enabled + Disabled + + Enabled + + + + IP Version + IpVer + IPv4 + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-3-1:IpVer + false + + IPv4 + IPv6 + IPv4 + IPv6 + + + Connect + ConnectFirstTgt + Disabled + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI First Target Parameters + + IscsiFirstTgtParams + NIC.Integrated.1-3-1:ConnectFirstTgt + false + + Disabled + Enabled + Disabled + + Enabled + + + + Connect + ConnectSecondTgt + Disabled + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Second Target Parameters + + IscsiSecondTgtParams + NIC.Integrated.1-3-1:ConnectSecondTgt + + false + + Disabled + Enabled + Disabled + + Enabled + + + + Legacy Boot Protocol + + LegacyBootProto + PXE + + NIC.Integrated.1-3-1 + MBA Configuration Menu + NICConfig + NIC.Integrated.1-3-1:LegacyBootProto + false + NONE + PXE + iSCSI + NONE + PXE + iSCSI + NONE + + + Boot Strap Type + BootStrapType + AutoDetect + + NIC.Integrated.1-3-1 + MBA Configuration Menu + NICConfig + NIC.Integrated.1-3-1:BootStrapType + false + + AutoDetect + BBS + Int18h + Int19h + Auto Detect + + BBS + Int 18h + + Int 19h + + + + Hide Setup Prompt + + HideSetupPrompt + Disabled + + NIC.Integrated.1-3-1 + MBA Configuration Menu + NICConfig + NIC.Integrated.1-3-1:HideSetupPrompt + false + + Disabled + Enabled + Disabled + + Enabled + + + + Link Speed + LnkSpeed + AutoNeg + + NIC.Integrated.1-3-1 + MBA Configuration Menu + NICConfig + NIC.Integrated.1-3-1:LnkSpeed + false + + AutoNeg + 10MbpsHalf + 10MbpsFull + 100MbpsHalf + 100MbpsFull + AutoNeg + + 10Mbps Half + + 10Mbps Full + + 100Mbps Half + + 100Mbps Full + + + + Pre-boot Wake On LAN + + WakeOnLan + Disabled + + NIC.Integrated.1-3-1 + MBA Configuration Menu + NICConfig + NIC.Integrated.1-3-1:WakeOnLan + false + + Disabled + Enabled + Disabled + + Enabled + + + + VLAN Mode + VLanMode + Disabled + + NIC.Integrated.1-3-1 + MBA Configuration Menu + NICConfig + NIC.Integrated.1-3-1:VLanMode + false + + Disabled + Enabled + Disabled + + Enabled + + + + Use Independent Target Portal + + UseIndTgtPortal + Disabled + Unavailable]]> + NIC.Integrated.1-3-1 + Secondary Device + SecondaryDevice + NIC.Integrated.1-3-1:UseIndTgtPortal + false + + Disabled + Enabled + Disabled + + Enabled + + + + Use Independent Target Name + + UseIndTgtName + Disabled + Unavailable]]> + NIC.Integrated.1-3-1 + Secondary Device + SecondaryDevice + NIC.Integrated.1-3-1:UseIndTgtName + false + + Disabled + Enabled + Disabled + + Enabled + + + + Link Status + LinkStatus + Disconnected + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:LinkStatus + true + + Disconnected + Connected + Disconnected + + Connected + + + + TCP/IP Parameters via DHCP + + TcpIpViaDHCP + Enabled + IPv6Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-4-1:TcpIpViaDHCP + false + + Disabled + Enabled + Disabled + + Enabled + + + + IP Autoconfiguration + + IpAutoConfig + Enabled + IPv4Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-4-1:IpAutoConfig + true + + Disabled + Enabled + Disabled + + Enabled + + + + iSCSI Parameters via DHCP + + IscsiViaDHCP + Enabled + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-4-1:IscsiViaDHCP + false + + Disabled + Enabled + Disabled + + Enabled + + + + CHAP Authentication + + ChapAuthEnable + Disabled + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-4-1:ChapAuthEnable + false + + Disabled + Enabled + Disabled + + Enabled + + + + Boot to iSCSI Target + + IscsiTgtBoot + Enabled + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-4-1:IscsiTgtBoot + false + + Disabled + Enabled + OneTimeDisabled + Disabled + + Enabled + + One Time Disabled + + + + Use TCP Timestamp + + TcpTimestmp + Disabled + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-4-1:TcpTimestmp + false + + Disabled + Enabled + Disabled + + Enabled + + + + Target as First HDD + + FirstHddTarget + Disabled + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-4-1:FirstHddTarget + false + + Disabled + Enabled + Disabled + + Enabled + + + + IP Version + IpVer + IPv4 + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-4-1:IpVer + false + + IPv4 + IPv6 + IPv4 + IPv6 + + + Connect + ConnectFirstTgt + Disabled + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI First Target Parameters + + IscsiFirstTgtParams + NIC.Integrated.1-4-1:ConnectFirstTgt + false + + Disabled + Enabled + Disabled + + Enabled + + + + Connect + ConnectSecondTgt + Disabled + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Second Target Parameters + + IscsiSecondTgtParams + NIC.Integrated.1-4-1:ConnectSecondTgt + + false + + Disabled + Enabled + Disabled + + Enabled + + + + Legacy Boot Protocol + + LegacyBootProto + NONE + + NIC.Integrated.1-4-1 + MBA Configuration Menu + NICConfig + NIC.Integrated.1-4-1:LegacyBootProto + false + + PXE + iSCSI + NONE + PXE + iSCSI + NONE + + + Boot Strap Type + BootStrapType + AutoDetect + + NIC.Integrated.1-4-1 + MBA Configuration Menu + NICConfig + NIC.Integrated.1-4-1:BootStrapType + false + + AutoDetect + BBS + Int18h + Int19h + Auto Detect + + BBS + Int 18h + + Int 19h + + + + Hide Setup Prompt + + HideSetupPrompt + Disabled + + NIC.Integrated.1-4-1 + MBA Configuration Menu + NICConfig + NIC.Integrated.1-4-1:HideSetupPrompt + false + + Disabled + Enabled + Disabled + + Enabled + + + + Link Speed + LnkSpeed + AutoNeg + + NIC.Integrated.1-4-1 + MBA Configuration Menu + NICConfig + NIC.Integrated.1-4-1:LnkSpeed + false + + AutoNeg + 10MbpsHalf + 10MbpsFull + 100MbpsHalf + 100MbpsFull + AutoNeg + + 10Mbps Half + + 10Mbps Full + + 100Mbps Half + + 100Mbps Full + + + + Pre-boot Wake On LAN + + WakeOnLan + Disabled + + NIC.Integrated.1-4-1 + MBA Configuration Menu + NICConfig + NIC.Integrated.1-4-1:WakeOnLan + false + + Disabled + Enabled + Disabled + + Enabled + + + + VLAN Mode + VLanMode + Disabled + + NIC.Integrated.1-4-1 + MBA Configuration Menu + NICConfig + NIC.Integrated.1-4-1:VLanMode + false + + Disabled + Enabled + Disabled + + Enabled + + + + Use Independent Target Portal + + UseIndTgtPortal + Disabled + Unavailable]]> + NIC.Integrated.1-4-1 + Secondary Device + SecondaryDevice + NIC.Integrated.1-4-1:UseIndTgtPortal + false + + Disabled + Enabled + Disabled + + Enabled + + + + Use Independent Target Name + + UseIndTgtName + Disabled + Unavailable]]> + NIC.Integrated.1-4-1 + Secondary Device + SecondaryDevice + NIC.Integrated.1-4-1:UseIndTgtName + false + + Disabled + Enabled + Disabled + + Enabled + + + + + + \ No newline at end of file diff --git a/dracclient/tests/wsman_mocks/nic_integer-enum-ok.xml b/dracclient/tests/wsman_mocks/nic_integer-enum-ok.xml new file mode 100644 index 0000000..b61485b --- /dev/null +++ b/dracclient/tests/wsman_mocks/nic_integer-enum-ok.xml @@ -0,0 +1,298 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + + uuid:b37882c2-0355-4b03-b3b8-1cb69bf00a74 + + uuid:8473faf6-71f0-11f0-a53f-a53ffbd9bed4 + + + + + + + Blink LEDs + BlnkLeds + 0 + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:BlnkLeds + false + 0 + + 15 + + + Link Up Delay Time + + LnkUpDelayTime + 0 + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-3-1:LnkUpDelayTime + false + 0 + + 255 + + + LUN Busy Retry Count + + LunBusyRetryCnt + 0 + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-3-1:LunBusyRetryCnt + false + 0 + + 60 + + + TCP Port + FirstTgtTcpPort + 3260 + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI First Target Parameters + + IscsiFirstTgtParams + NIC.Integrated.1-3-1:FirstTgtTcpPort + false + 1 + + 65535 + + + Boot LUN + FirstTgtBootLun + 0 + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI First Target Parameters + + IscsiFirstTgtParams + NIC.Integrated.1-3-1:FirstTgtBootLun + false + 0 + + 255 + + + TCP Port + SecondTgtTcpPort + 3260 + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Second Target Parameters + + IscsiSecondTgtParams + NIC.Integrated.1-3-1:SecondTgtTcpPort + + false + 1 + + 65535 + + + Boot LUN + SecondTgtBootLun + 0 + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Second Target Parameters + + IscsiSecondTgtParams + NIC.Integrated.1-3-1:SecondTgtBootLun + + false + 0 + + 255 + + + Banner Message Timeout + + BannerMessageTimeout + 5 + + NIC.Integrated.1-3-1 + MBA Configuration Menu + NICConfig + NIC.Integrated.1-3-1:BannerMessageTimeout + + false + 0 + + 14 + + + VLAN ID (1..4094) + + VLanId + 1 + Disabled]]> + NIC.Integrated.1-3-1 + MBA Configuration Menu + NICConfig + NIC.Integrated.1-3-1:VLanId + true + 1 + + 4094 + + + Blink LEDs + BlnkLeds + 0 + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:BlnkLeds + false + 0 + + 15 + + + Link Up Delay Time + + LnkUpDelayTime + 0 + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-4-1:LnkUpDelayTime + false + 0 + + 255 + + + LUN Busy Retry Count + + LunBusyRetryCnt + 0 + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-4-1:LunBusyRetryCnt + false + 0 + + 60 + + + TCP Port + FirstTgtTcpPort + 3260 + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI First Target Parameters + + IscsiFirstTgtParams + NIC.Integrated.1-4-1:FirstTgtTcpPort + false + 1 + + 65535 + + + Boot LUN + FirstTgtBootLun + 0 + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI First Target Parameters + + IscsiFirstTgtParams + NIC.Integrated.1-4-1:FirstTgtBootLun + false + 0 + + 255 + + + TCP Port + SecondTgtTcpPort + 3260 + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Second Target Parameters + + IscsiSecondTgtParams + NIC.Integrated.1-4-1:SecondTgtTcpPort + + false + 1 + + 65535 + + + Boot LUN + SecondTgtBootLun + 0 + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Second Target Parameters + + IscsiSecondTgtParams + NIC.Integrated.1-4-1:SecondTgtBootLun + + false + 0 + 2 + + 255 + + + Banner Message Timeout + + BannerMessageTimeout + 5 + + NIC.Integrated.1-4-1 + MBA Configuration Menu + NICConfig + NIC.Integrated.1-4-1:BannerMessageTimeout + + false + 0 + + 14 + + + VLAN ID (1..4094) + + VLanId + 1 + Disabled]]> + NIC.Integrated.1-4-1 + MBA Configuration Menu + NICConfig + NIC.Integrated.1-4-1:VLanId + true + 1 + + 4094 + + + + + \ No newline at end of file diff --git a/dracclient/tests/wsman_mocks/nic_service-invoke-set_attributes-error.xml b/dracclient/tests/wsman_mocks/nic_service-invoke-set_attributes-error.xml new file mode 100644 index 0000000..2d18ed8 --- /dev/null +++ b/dracclient/tests/wsman_mocks/nic_service-invoke-set_attributes-error.xml @@ -0,0 +1,22 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + + http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_NICService/SetAttributesResponse + + uuid:e24aa9e2-28f3-487d-8f69-ab4234a2c9ba + + uuid:d3770d92-7202-1202-b927-a53ffbd9bed4 + + + + + Invalid parameter value for Target + Target + NIC004 + 2 + + + diff --git a/dracclient/tests/wsman_mocks/nic_service-invoke-set_attributes-ok.xml b/dracclient/tests/wsman_mocks/nic_service-invoke-set_attributes-ok.xml new file mode 100644 index 0000000..66ae03f --- /dev/null +++ b/dracclient/tests/wsman_mocks/nic_service-invoke-set_attributes-ok.xml @@ -0,0 +1,23 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + + http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_NICService/SetAttributesResponse + + uuid:bf8adefe-6fc0-456d-b97c-fd8d4aca2d6c + + uuid:84abf7b9-7176-1176-a11c-a53ffbd9bed4 + + + + + The command was successful. + NIC001 + Yes + 0 + Set PendingValue + + + \ No newline at end of file diff --git a/dracclient/tests/wsman_mocks/nic_string-enum-colliding.xml b/dracclient/tests/wsman_mocks/nic_string-enum-colliding.xml new file mode 100644 index 0000000..0aa8268 --- /dev/null +++ b/dracclient/tests/wsman_mocks/nic_string-enum-colliding.xml @@ -0,0 +1,1185 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + + uuid:48fa32d6-5bdb-4080-a9cb-040fdd600ece + + uuid:66b00908-71f0-11f0-a516-a53ffbd9bed4 + + + + + + + Link Status + LinkStatus + BCM5720 A0 + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:ChipMdl + true + 0 + 0 + + + + + PCI Device ID + PCIDeviceID + 165F + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:PCIDeviceID + true + 0 + 0 + + + + + Bus:Dev:Func + BusDeviceFunction + 02:00:00 + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:BusDeviceFunction + + true + 0 + 0 + + + + + Permanent MAC Address + + MacAddr + D4:AE:52:A5:B1:EA + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:MacAddr + true + 17 + 17 + + + + + Virtual MAC Address + + VirtMacAddr + D4:AE:52:A5:B1:EA + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:VirtMacAddr + false + 17 + 17 + + ^([0-9a-fA-F]{2}:){5}([0-9a-fA-F]{2})$ + + + + FCoE Offload Support + + FCoEOffloadSupport + Unavailable + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:FCoEOffloadSupport + + true + 12 + 0 + + + + + iSCSI Offload Support + + iSCSIOffloadSupport + Unavailable + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:iSCSIOffloadSupport + + true + 12 + 0 + + + + + IBS + iSCSIBootSupport + Available + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:iSCSIBootSupport + + true + 12 + 0 + + + + + PBS + PXEBootSupport + Available + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:PXEBootSupport + true + 12 + 0 + + + + + FBS + FCoEBootSupport + Unavailable + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:FCoEBootSupport + true + 12 + 0 + + + + + NPS + NicPartitioningSupport + Unavailable + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:NicPartitioningSupport + + true + 12 + 0 + + + + + TBMax + TXBandwidthControlMaximum + Unavailable + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:TXBandwidthControlMaximum + + true + 12 + 0 + + + + + TBMin + TXBandwidthControlMinimum + Unavailable + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:TXBandwidthControlMinimum + + true + 12 + 0 + + + + + DHCP Vendor ID + DhcpVendId + BRCM ISAN + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-3-1:DhcpVendId + false + 32 + 0 + + + + + IP Address + IscsiInitiatorIpAddr + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-3-1:IscsiInitiatorIpAddr + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + Subnet Mask + IscsiInitiatorSubnet + 0.0.0.0 + UnavailableIPv6]]> + NIC.Integrated.1-3-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-3-1:IscsiInitiatorSubnet + + false + 15 + 7 + + ^([0-9]{1,3}.){3}[0-9]{1,3}$ + + + + Subnet Mask Prefix + + IscsiInitiatorSubnetPrefix + + UnavailableIPv4]]> + NIC.Integrated.1-3-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-3-1:IscsiInitiatorSubnetPrefix + + true + 3 + 1 + + + + + Default Gateway + IscsiInitiatorGateway + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-3-1:IscsiInitiatorGateway + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + Primary DNS + IscsiInitiatorPrimDns + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-3-1:IscsiInitiatorPrimDns + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + Secondary DNS + IscsiInitiatorSecDns + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-3-1:IscsiInitiatorSecDns + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + iSCSI Name + IscsiInitiatorName + iqn.1995-05.com.broadcom.iscsiboot + + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-3-1:IscsiInitiatorName + + false + 128 + 0 + + ^[-0-9a-zA-Z.:_]{0,128}$ + + + CHAP ID + IscsiInitiatorChapId + + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-3-1:IscsiInitiatorChapId + + false + 128 + 0 + + ^[x20-~]{0,128}$ + + + CHAP Secret + IscsiInitiatorChapPwd + + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-3-1:IscsiInitiatorChapPwd + + false + 16 + 0 + + ^[x20-~]{0,16}$ + + + IP Address + FirstTgtIpAddress + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI First Target Parameters + + IscsiFirstTgtParams + NIC.Integrated.1-3-1:FirstTgtIpAddress + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + iSCSI Name + FirstTgtIscsiName + + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI First Target Parameters + + IscsiFirstTgtParams + NIC.Integrated.1-3-1:FirstTgtIscsiName + + false + 128 + 0 + + ^[-0-9a-zA-Z.:_]{0,128}$ + + + CHAP ID + FirstTgtChapId + + + NIC.Integrated.1-3-1 + iSCSI First Target Parameters + + IscsiFirstTgtParams + NIC.Integrated.1-3-1:FirstTgtChapId + false + 128 + 0 + + ^[x20-~]{0,128}$ + + + CHAP Secret + FirstTgtChapPwd + + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI First Target Parameters + + IscsiFirstTgtParams + NIC.Integrated.1-3-1:FirstTgtChapPwd + false + 16 + 0 + + ^[x20-~]{0,16}$ + + + IP Address + SecondTgtIpAddress + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Second Target Parameters + + IscsiSecondTgtParams + NIC.Integrated.1-3-1:SecondTgtIpAddress + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + iSCSI Name + SecondTgtIscsiName + + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Second Target Parameters + + IscsiSecondTgtParams + NIC.Integrated.1-3-1:SecondTgtIscsiName + + false + 128 + 0 + + ^[-0-9a-zA-Z.:_]{0,128}$ + + + CHAP ID + SecondTgtChapId + + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Second Target Parameters + + IscsiSecondTgtParams + NIC.Integrated.1-3-1:SecondTgtChapId + false + 128 + 0 + + ^[x20-~]{0,128}$ + + + CHAP Secret + SecondTgtChapPwd + + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Second Target Parameters + + IscsiSecondTgtParams + NIC.Integrated.1-3-1:SecondTgtChapPwd + + false + 16 + 0 + + ^[x20-~]{0,16}$ + + + Firmware Family Version + + FamilyVersion + 7.4.8 + + NIC.Integrated.1-3-1 + Firmware Image Menu + FrmwImgMenu + NIC.Integrated.1-3-1:FamilyVersion + true + 20 + 0 + + + + + Bootcode + ControllerBIOSVersion + 1.30 + + NIC.Integrated.1-3-1 + Firmware Image Menu + FrmwImgMenu + NIC.Integrated.1-3-1:ControllerBIOSVersion + + true + 9 + 0 + + + + + EFI + EFIVersion + 15.4.6 + + NIC.Integrated.1-3-1 + Firmware Image Menu + FrmwImgMenu + NIC.Integrated.1-3-1:EFIVersion + true + 9 + 0 + + + + + Secondary Device + SecondaryDeviceMacAddr + 00:00:00:00:00:00 + Unavailable]]> + NIC.Integrated.1-3-1 + Secondary Device + SecondaryDevice + NIC.Integrated.1-3-1:SecondaryDeviceMacAddr + + false + 17 + 17 + + ^([0-9a-fA-F]{2}:){5}([0-9a-fA-F]{2})$ + + + + Chip Type + ChipMdl + BCM5720 A0 + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:ChipMdl + true + 0 + 0 + + + + + PCI Device ID + PCIDeviceID + 165F + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:PCIDeviceID + true + 0 + 0 + + + + + Bus:Dev:Func + BusDeviceFunction + 02:00:01 + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:BusDeviceFunction + + true + 0 + 0 + + + + + Permanent MAC Address + + MacAddr + D4:AE:52:A5:B1:EB + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:MacAddr + true + 17 + 17 + + + + + Virtual MAC Address + + VirtMacAddr + D4:AE:52:A5:B1:EB + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:VirtMacAddr + false + 17 + 17 + + ^([0-9a-fA-F]{2}:){5}([0-9a-fA-F]{2})$ + + + + FCoE Offload Support + + FCoEOffloadSupport + Unavailable + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:FCoEOffloadSupport + + true + 12 + 0 + + + + + iSCSI Offload Support + + iSCSIOffloadSupport + Unavailable + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:iSCSIOffloadSupport + + true + 12 + 0 + + + + + IBS + iSCSIBootSupport + Available + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:iSCSIBootSupport + + true + 12 + 0 + + + + + PBS + PXEBootSupport + Available + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:PXEBootSupport + true + 12 + 0 + + + + + FBS + FCoEBootSupport + Unavailable + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:FCoEBootSupport + true + 12 + 0 + + + + + NPS + NicPartitioningSupport + Unavailable + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:NicPartitioningSupport + + true + 12 + 0 + + + + + TBMax + TXBandwidthControlMaximum + Unavailable + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:TXBandwidthControlMaximum + + true + 12 + 0 + + + + + TBMin + TXBandwidthControlMinimum + Unavailable + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:TXBandwidthControlMinimum + + true + 12 + 0 + + + + + DHCP Vendor ID + DhcpVendId + BRCM ISAN + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-4-1:DhcpVendId + false + 32 + 0 + + + + + IP Address + IscsiInitiatorIpAddr + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-4-1:IscsiInitiatorIpAddr + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + Subnet Mask + IscsiInitiatorSubnet + 0.0.0.0 + UnavailableIPv6]]> + NIC.Integrated.1-4-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-4-1:IscsiInitiatorSubnet + + false + 15 + 7 + + ^([0-9]{1,3}.){3}[0-9]{1,3}$ + + + + Subnet Mask Prefix + + IscsiInitiatorSubnetPrefix + + UnavailableIPv4]]> + NIC.Integrated.1-4-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-4-1:IscsiInitiatorSubnetPrefix + + true + 3 + 1 + + + + + Default Gateway + IscsiInitiatorGateway + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-4-1:IscsiInitiatorGateway + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + Primary DNS + IscsiInitiatorPrimDns + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-4-1:IscsiInitiatorPrimDns + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + Secondary DNS + IscsiInitiatorSecDns + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-4-1:IscsiInitiatorSecDns + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + iSCSI Name + IscsiInitiatorName + iqn.1995-05.com.broadcom.iscsiboot + + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-4-1:IscsiInitiatorName + + false + 128 + 0 + + ^[-0-9a-zA-Z.:_]{0,128}$ + + + CHAP ID + IscsiInitiatorChapId + + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-4-1:IscsiInitiatorChapId + + false + 128 + 0 + + ^[x20-~]{0,128}$ + + + CHAP Secret + IscsiInitiatorChapPwd + + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-4-1:IscsiInitiatorChapPwd + + false + 16 + 0 + + ^[x20-~]{0,16}$ + + + IP Address + FirstTgtIpAddress + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI First Target Parameters + + IscsiFirstTgtParams + NIC.Integrated.1-4-1:FirstTgtIpAddress + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + iSCSI Name + FirstTgtIscsiName + + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI First Target Parameters + + IscsiFirstTgtParams + NIC.Integrated.1-4-1:FirstTgtIscsiName + + false + 128 + 0 + + ^[-0-9a-zA-Z.:_]{0,128}$ + + + CHAP ID + FirstTgtChapId + + + NIC.Integrated.1-4-1 + iSCSI First Target Parameters + + IscsiFirstTgtParams + NIC.Integrated.1-4-1:FirstTgtChapId + false + 128 + 0 + + ^[x20-~]{0,128}$ + + + CHAP Secret + FirstTgtChapPwd + + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI First Target Parameters + + IscsiFirstTgtParams + NIC.Integrated.1-4-1:FirstTgtChapPwd + false + 16 + 0 + + ^[x20-~]{0,16}$ + + + IP Address + SecondTgtIpAddress + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Second Target Parameters + + IscsiSecondTgtParams + NIC.Integrated.1-4-1:SecondTgtIpAddress + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + iSCSI Name + SecondTgtIscsiName + + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Second Target Parameters + + IscsiSecondTgtParams + NIC.Integrated.1-4-1:SecondTgtIscsiName + + false + 128 + 0 + + ^[-0-9a-zA-Z.:_]{0,128}$ + + + CHAP ID + SecondTgtChapId + + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Second Target Parameters + + IscsiSecondTgtParams + NIC.Integrated.1-4-1:SecondTgtChapId + false + 128 + 0 + + ^[x20-~]{0,128}$ + + + CHAP Secret + SecondTgtChapPwd + + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Second Target Parameters + + IscsiSecondTgtParams + NIC.Integrated.1-4-1:SecondTgtChapPwd + + false + 16 + 0 + + ^[x20-~]{0,16}$ + + + Firmware Family Version + + FamilyVersion + 7.4.8 + + NIC.Integrated.1-4-1 + Firmware Image Menu + FrmwImgMenu + NIC.Integrated.1-4-1:FamilyVersion + true + 20 + 0 + + + + + Bootcode + ControllerBIOSVersion + 1.30 + + NIC.Integrated.1-4-1 + Firmware Image Menu + FrmwImgMenu + NIC.Integrated.1-4-1:ControllerBIOSVersion + + true + 9 + 0 + + + + + EFI + EFIVersion + 15.4.6 + + NIC.Integrated.1-4-1 + Firmware Image Menu + FrmwImgMenu + NIC.Integrated.1-4-1:EFIVersion + true + 9 + 0 + + + + + Secondary Device + SecondaryDeviceMacAddr + 00:00:00:00:00:00 + Unavailable]]> + NIC.Integrated.1-4-1 + Secondary Device + SecondaryDevice + NIC.Integrated.1-4-1:SecondaryDeviceMacAddr + + false + 17 + 17 + + ^([0-9a-fA-F]{2}:){5}([0-9a-fA-F]{2})$ + + + + + + \ No newline at end of file diff --git a/dracclient/tests/wsman_mocks/nic_string-enum-ok.xml b/dracclient/tests/wsman_mocks/nic_string-enum-ok.xml new file mode 100644 index 0000000..1059b33 --- /dev/null +++ b/dracclient/tests/wsman_mocks/nic_string-enum-ok.xml @@ -0,0 +1,1185 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + + uuid:48fa32d6-5bdb-4080-a9cb-040fdd600ece + + uuid:66b00908-71f0-11f0-a516-a53ffbd9bed4 + + + + + + + Chip Type + ChipMdl + BCM5720 A0 + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:ChipMdl + true + 0 + 0 + + + + + PCI Device ID + PCIDeviceID + 165F + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:PCIDeviceID + true + 0 + 0 + + + + + Bus:Dev:Func + BusDeviceFunction + 02:00:00 + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:BusDeviceFunction + + true + 0 + 0 + + + + + Permanent MAC Address + + MacAddr + D4:AE:52:A5:B1:EA + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:MacAddr + true + 17 + 17 + + + + + Virtual MAC Address + + VirtMacAddr + D4:AE:52:A5:B1:EA + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:VirtMacAddr + false + 17 + 17 + + ^([0-9a-fA-F]{2}:){5}([0-9a-fA-F]{2})$ + + + + FCoE Offload Support + + FCoEOffloadSupport + Unavailable + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:FCoEOffloadSupport + + true + 12 + 0 + + + + + iSCSI Offload Support + + iSCSIOffloadSupport + Unavailable + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:iSCSIOffloadSupport + + true + 12 + 0 + + + + + IBS + iSCSIBootSupport + Available + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:iSCSIBootSupport + + true + 12 + 0 + + + + + PBS + PXEBootSupport + Available + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:PXEBootSupport + true + 12 + 0 + + + + + FBS + FCoEBootSupport + Unavailable + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:FCoEBootSupport + true + 12 + 0 + + + + + NPS + NicPartitioningSupport + Unavailable + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:NicPartitioningSupport + + true + 12 + 0 + + + + + TBMax + TXBandwidthControlMaximum + Unavailable + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:TXBandwidthControlMaximum + + true + 12 + 0 + + + + + TBMin + TXBandwidthControlMinimum + Unavailable + + NIC.Integrated.1-3-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-3-1:TXBandwidthControlMinimum + + true + 12 + 0 + + + + + DHCP Vendor ID + DhcpVendId + BRCM ISAN + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-3-1:DhcpVendId + false + 32 + 0 + + + + + IP Address + IscsiInitiatorIpAddr + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-3-1:IscsiInitiatorIpAddr + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + Subnet Mask + IscsiInitiatorSubnet + 0.0.0.0 + UnavailableIPv6]]> + NIC.Integrated.1-3-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-3-1:IscsiInitiatorSubnet + + false + 15 + 7 + + ^([0-9]{1,3}.){3}[0-9]{1,3}$ + + + + Subnet Mask Prefix + + IscsiInitiatorSubnetPrefix + + UnavailableIPv4]]> + NIC.Integrated.1-3-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-3-1:IscsiInitiatorSubnetPrefix + + true + 3 + 1 + + + + + Default Gateway + IscsiInitiatorGateway + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-3-1:IscsiInitiatorGateway + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + Primary DNS + IscsiInitiatorPrimDns + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-3-1:IscsiInitiatorPrimDns + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + Secondary DNS + IscsiInitiatorSecDns + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-3-1:IscsiInitiatorSecDns + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + iSCSI Name + IscsiInitiatorName + iqn.1995-05.com.broadcom.iscsiboot + + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-3-1:IscsiInitiatorName + + false + 128 + 0 + + ^[-0-9a-zA-Z.:_]{0,128}$ + + + CHAP ID + IscsiInitiatorChapId + + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-3-1:IscsiInitiatorChapId + + false + 128 + 0 + + ^[x20-~]{0,128}$ + + + CHAP Secret + IscsiInitiatorChapPwd + + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-3-1:IscsiInitiatorChapPwd + + false + 16 + 0 + + ^[x20-~]{0,16}$ + + + IP Address + FirstTgtIpAddress + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI First Target Parameters + + IscsiFirstTgtParams + NIC.Integrated.1-3-1:FirstTgtIpAddress + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + iSCSI Name + FirstTgtIscsiName + + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI First Target Parameters + + IscsiFirstTgtParams + NIC.Integrated.1-3-1:FirstTgtIscsiName + + false + 128 + 0 + + ^[-0-9a-zA-Z.:_]{0,128}$ + + + CHAP ID + FirstTgtChapId + + + NIC.Integrated.1-3-1 + iSCSI First Target Parameters + + IscsiFirstTgtParams + NIC.Integrated.1-3-1:FirstTgtChapId + false + 128 + 0 + + ^[x20-~]{0,128}$ + + + CHAP Secret + FirstTgtChapPwd + + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI First Target Parameters + + IscsiFirstTgtParams + NIC.Integrated.1-3-1:FirstTgtChapPwd + false + 16 + 0 + + ^[x20-~]{0,16}$ + + + IP Address + SecondTgtIpAddress + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Second Target Parameters + + IscsiSecondTgtParams + NIC.Integrated.1-3-1:SecondTgtIpAddress + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + iSCSI Name + SecondTgtIscsiName + + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Second Target Parameters + + IscsiSecondTgtParams + NIC.Integrated.1-3-1:SecondTgtIscsiName + + false + 128 + 0 + + ^[-0-9a-zA-Z.:_]{0,128}$ + + + CHAP ID + SecondTgtChapId + + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Second Target Parameters + + IscsiSecondTgtParams + NIC.Integrated.1-3-1:SecondTgtChapId + false + 128 + 0 + + ^[x20-~]{0,128}$ + + + CHAP Secret + SecondTgtChapPwd + + Unavailable]]> + NIC.Integrated.1-3-1 + iSCSI Second Target Parameters + + IscsiSecondTgtParams + NIC.Integrated.1-3-1:SecondTgtChapPwd + + false + 16 + 0 + + ^[x20-~]{0,16}$ + + + Firmware Family Version + + FamilyVersion + 7.4.8 + + NIC.Integrated.1-3-1 + Firmware Image Menu + FrmwImgMenu + NIC.Integrated.1-3-1:FamilyVersion + true + 20 + 0 + + + + + Bootcode + ControllerBIOSVersion + 1.30 + + NIC.Integrated.1-3-1 + Firmware Image Menu + FrmwImgMenu + NIC.Integrated.1-3-1:ControllerBIOSVersion + + true + 9 + 0 + + + + + EFI + EFIVersion + 15.4.6 + + NIC.Integrated.1-3-1 + Firmware Image Menu + FrmwImgMenu + NIC.Integrated.1-3-1:EFIVersion + true + 9 + 0 + + + + + Secondary Device + SecondaryDeviceMacAddr + 00:00:00:00:00:00 + Unavailable]]> + NIC.Integrated.1-3-1 + Secondary Device + SecondaryDevice + NIC.Integrated.1-3-1:SecondaryDeviceMacAddr + + false + 17 + 17 + + ^([0-9a-fA-F]{2}:){5}([0-9a-fA-F]{2})$ + + + + Chip Type + ChipMdl + BCM5720 A0 + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:ChipMdl + true + 0 + 0 + + + + + PCI Device ID + PCIDeviceID + 165F + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:PCIDeviceID + true + 0 + 0 + + + + + Bus:Dev:Func + BusDeviceFunction + 02:00:01 + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:BusDeviceFunction + + true + 0 + 0 + + + + + Permanent MAC Address + + MacAddr + D4:AE:52:A5:B1:EB + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:MacAddr + true + 17 + 17 + + + + + Virtual MAC Address + + VirtMacAddr + D4:AE:52:A5:B1:EB + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:VirtMacAddr + false + 17 + 17 + + ^([0-9a-fA-F]{2}:){5}([0-9a-fA-F]{2})$ + + + + FCoE Offload Support + + FCoEOffloadSupport + Unavailable + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:FCoEOffloadSupport + + true + 12 + 0 + + + + + iSCSI Offload Support + + iSCSIOffloadSupport + Unavailable + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:iSCSIOffloadSupport + + true + 12 + 0 + + + + + IBS + iSCSIBootSupport + Available + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:iSCSIBootSupport + + true + 12 + 0 + + + + + PBS + PXEBootSupport + Available + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:PXEBootSupport + true + 12 + 0 + + + + + FBS + FCoEBootSupport + Unavailable + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:FCoEBootSupport + true + 12 + 0 + + + + + NPS + NicPartitioningSupport + Unavailable + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:NicPartitioningSupport + + true + 12 + 0 + + + + + TBMax + TXBandwidthControlMaximum + Unavailable + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:TXBandwidthControlMaximum + + true + 12 + 0 + + + + + TBMin + TXBandwidthControlMinimum + Unavailable + + NIC.Integrated.1-4-1 + Main Configuration Page + VndrConfigPage + NIC.Integrated.1-4-1:TXBandwidthControlMinimum + + true + 12 + 0 + + + + + DHCP Vendor ID + DhcpVendId + BRCM ISAN + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI General Parameters + IscsiGenParams + NIC.Integrated.1-4-1:DhcpVendId + false + 32 + 0 + + + + + IP Address + IscsiInitiatorIpAddr + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-4-1:IscsiInitiatorIpAddr + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + Subnet Mask + IscsiInitiatorSubnet + 0.0.0.0 + UnavailableIPv6]]> + NIC.Integrated.1-4-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-4-1:IscsiInitiatorSubnet + + false + 15 + 7 + + ^([0-9]{1,3}.){3}[0-9]{1,3}$ + + + + Subnet Mask Prefix + + IscsiInitiatorSubnetPrefix + + UnavailableIPv4]]> + NIC.Integrated.1-4-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-4-1:IscsiInitiatorSubnetPrefix + + true + 3 + 1 + + + + + Default Gateway + IscsiInitiatorGateway + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-4-1:IscsiInitiatorGateway + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + Primary DNS + IscsiInitiatorPrimDns + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-4-1:IscsiInitiatorPrimDns + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + Secondary DNS + IscsiInitiatorSecDns + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-4-1:IscsiInitiatorSecDns + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + iSCSI Name + IscsiInitiatorName + iqn.1995-05.com.broadcom.iscsiboot + + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-4-1:IscsiInitiatorName + + false + 128 + 0 + + ^[-0-9a-zA-Z.:_]{0,128}$ + + + CHAP ID + IscsiInitiatorChapId + + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-4-1:IscsiInitiatorChapId + + false + 128 + 0 + + ^[x20-~]{0,128}$ + + + CHAP Secret + IscsiInitiatorChapPwd + + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Initiator Parameters + + IscsiInitiatorParams + NIC.Integrated.1-4-1:IscsiInitiatorChapPwd + + false + 16 + 0 + + ^[x20-~]{0,16}$ + + + IP Address + FirstTgtIpAddress + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI First Target Parameters + + IscsiFirstTgtParams + NIC.Integrated.1-4-1:FirstTgtIpAddress + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + iSCSI Name + FirstTgtIscsiName + + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI First Target Parameters + + IscsiFirstTgtParams + NIC.Integrated.1-4-1:FirstTgtIscsiName + + false + 128 + 0 + + ^[-0-9a-zA-Z.:_]{0,128}$ + + + CHAP ID + FirstTgtChapId + + + NIC.Integrated.1-4-1 + iSCSI First Target Parameters + + IscsiFirstTgtParams + NIC.Integrated.1-4-1:FirstTgtChapId + false + 128 + 0 + + ^[x20-~]{0,128}$ + + + CHAP Secret + FirstTgtChapPwd + + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI First Target Parameters + + IscsiFirstTgtParams + NIC.Integrated.1-4-1:FirstTgtChapPwd + false + 16 + 0 + + ^[x20-~]{0,16}$ + + + IP Address + SecondTgtIpAddress + 0.0.0.0 + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Second Target Parameters + + IscsiSecondTgtParams + NIC.Integrated.1-4-1:SecondTgtIpAddress + + false + 39 + 2 + + ^([0-9]{1,3}.){3}[0-9]{1,3}|[0-9a-fA-F:]{2,39}$ + + + + iSCSI Name + SecondTgtIscsiName + + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Second Target Parameters + + IscsiSecondTgtParams + NIC.Integrated.1-4-1:SecondTgtIscsiName + + false + 128 + 0 + + ^[-0-9a-zA-Z.:_]{0,128}$ + + + CHAP ID + SecondTgtChapId + + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Second Target Parameters + + IscsiSecondTgtParams + NIC.Integrated.1-4-1:SecondTgtChapId + false + 128 + 0 + + ^[x20-~]{0,128}$ + + + CHAP Secret + SecondTgtChapPwd + + Unavailable]]> + NIC.Integrated.1-4-1 + iSCSI Second Target Parameters + + IscsiSecondTgtParams + NIC.Integrated.1-4-1:SecondTgtChapPwd + + false + 16 + 0 + + ^[x20-~]{0,16}$ + + + Firmware Family Version + + FamilyVersion + 7.4.8 + + NIC.Integrated.1-4-1 + Firmware Image Menu + FrmwImgMenu + NIC.Integrated.1-4-1:FamilyVersion + true + 20 + 0 + + + + + Bootcode + ControllerBIOSVersion + 1.30 + + NIC.Integrated.1-4-1 + Firmware Image Menu + FrmwImgMenu + NIC.Integrated.1-4-1:ControllerBIOSVersion + + true + 9 + 0 + + + + + EFI + EFIVersion + 15.4.6 + + NIC.Integrated.1-4-1 + Firmware Image Menu + FrmwImgMenu + NIC.Integrated.1-4-1:EFIVersion + true + 9 + 0 + + + + + Secondary Device + SecondaryDeviceMacAddr + 00:00:00:00:00:00 + Unavailable]]> + NIC.Integrated.1-4-1 + Secondary Device + SecondaryDevice + NIC.Integrated.1-4-1:SecondaryDeviceMacAddr + + false + 17 + 17 + + ^([0-9a-fA-F]{2}:){5}([0-9a-fA-F]{2})$ + + + + + + \ No newline at end of file diff --git a/dracclient/tests/wsman_mocks/physical_disk_view-enum-ok.xml b/dracclient/tests/wsman_mocks/physical_disk_view-enum-ok.xml index bf3633b..791fa59 100644 --- a/dracclient/tests/wsman_mocks/physical_disk_view-enum-ok.xml +++ b/dracclient/tests/wsman_mocks/physical_disk_view-enum-ok.xml @@ -2,7 +2,9 @@ xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsen="http://schemas.xmlsoap.org/ws/2004/09/enumeration" xmlns:wsman="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" - xmlns:n1="http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_PhysicalDiskView"> + xmlns:n1="http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_PhysicalDiskView" + xmlns:n2="http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_PCIeSSDView" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse @@ -123,6 +125,108 @@ 0 0 + + 512 + 5 + 0 + Disk 1 on Integrated BOSS Controller 1 + 2 + Disk.Bay.0:Enclosure.Internal.0-1:AHCI.Integrated.1-1 + 599550590976 + 0 + Disk.Bay.0:Enclosure.Internal.0-1:AHCI.Integrated.1-1 + 20150226180025.000000+000 + 20150226180025.000000+000 + ATA + 2 + 33 + 2014 + 3 + 1 + ST600MM0007 + None + 0 + CN07YX587262248G01PZA02 + 0 + 1 + 1 + 255 + LS0B + 1 + 5000C5007764F409 + 0 + S0M3EY3Z + 599550590976 + 1 + None + 0 + 0 + + + 512 + 5 + 0 + Disk 2 on Integrated BOSS Controller 1 + 2 + Disk.Bay.1:Enclosure.Internal.0-1:AHCI.Integrated.1-1 + 599550590976 + 0 + Disk.Bay.1:Enclosure.Internal.0-1:AHCI.Integrated.1-1 + 20150226180025.000000+000 + 20150226180025.000000+000 + ATA + 2 + 33 + 2014 + 3 + 1 + ST600MM0007 + None + 0 + CN07YX587262248G01PZA02 + 0 + 1 + 1 + 255 + LS0B + 1 + 5000C5007764F409 + 0 + S0M3EY3Z + 599550590976 + 2 + None + 0 + 0 + + + 7 + 3E + PCIe SSD in Slot 20 in Bay 1 + NVMe-MI1.0 + 2 + Disk.Bay.20:Enclosure.Internal.0-1:PCIeExtender.Slot.1 + NO + + + Disk.Bay.20:Enclosure.Internal.0-1:PCIeExtender.Slot.1 + SAMSUNG + 8 GT/s + 1 + Dell Express Flash PM1725a 800GB SFF + 8 GT/s + x4 + x4 + 0 + a822 + 0 + + 100 + 1.0.4 + S39YNX0JB02343 + 800166076416 + 1 + diff --git a/dracclient/tests/wsman_mocks/raid_enumeration-enum-ok.xml b/dracclient/tests/wsman_mocks/raid_enumeration-enum-ok.xml new file mode 100644 index 0000000..f031e64 --- /dev/null +++ b/dracclient/tests/wsman_mocks/raid_enumeration-enum-ok.xml @@ -0,0 +1,2347 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + uuid:41a4f623-7f99-43b9-b240-4a773aa39860 + uuid:3b204fe0-9caa-1caa-a2f1-614a498fd94c + + + + + + RAIDSupportedRAIDLevels + 2(RAID-0) + 4(RAID-1) + 64(RAID-5) + 128(RAID-6) + 2048(RAID-10) + 8192(RAID-50) + 16384(RAID-60) + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDSupportedRAIDLevels + true + + 2(RAID-0) + 4(RAID-1) + 64(RAID-5) + 128(RAID-6) + 2048(RAID-10) + 8192(RAID-50) + 16384(RAID-60) + + + RAIDSupportedDiskProt + SAS + SATA + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDSupportedDiskProt + true + + SAS + SATA + + + RAIDSupportedInitTypes + Fast + Full + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDSupportedInitTypes + true + + Fast + Full + + + RAIDloadBalancedMode + Automatic + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDloadBalancedMode + false + + Automatic + Disabled + + + RAIDccMode + Normal + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDccMode + false + + Normal + Stop on Error + + + RAIDprMode + Automatic + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDprMode + false + + Disabled + Automatic + Manual + + + RAIDPatrolReadUnconfiguredArea + Enabled + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDPatrolReadUnconfiguredArea + false + + Disabled + Enabled + + + RAIDcopybackMode + On + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDcopybackMode + false + + On + On with SMART + Off + + + RAIDEnhancedAutoImportForeignConfig + Disabled + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDEnhancedAutoImportForeignConfig + false + + Disabled + Enabled + + + RAIDControllerBootMode + Headless Mode Continue On Error + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDControllerBootMode + false + + User Mode + Continue Boot On Error + Headless Mode Continue On Error + Headless Safe Mode + + + RAIDCurrentControllerMode + RAID + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDCurrentControllerMode + true + + RAID + Enhanced HBA + + + RAIDRequestedControllerMode + None + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDRequestedControllerMode + false + + RAID + Enhanced HBA + None + + + RAIDMode + None + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDMode + true + + None + Linux + Windows + Mixed + + + RAIDpersistentHotspare + Disabled + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDpersistentHotspare + false + + Disabled + Enabled + + + RAIDMaxCapableSpeed + 12_GBS + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDMaxCapableSpeed + true + + 1_5_GBS + 3_GBS + 6_GBS + 12_GBS + + + RAIDSupportedInitTypes + None + AHCI.Embedded.1-1 + AHCI.Embedded.1-1:RAIDSupportedInitTypes + true + + None + + + RAIDMode + None + AHCI.Embedded.1-1 + AHCI.Embedded.1-1:RAIDMode + true + + None + Linux + Windows + Mixed + + + RAIDSupportedInitTypes + None + AHCI.Embedded.2-1 + AHCI.Embedded.2-1:RAIDSupportedInitTypes + true + + None + + + RAIDMode + None + AHCI.Embedded.2-1 + AHCI.Embedded.2-1:RAIDMode + true + + None + Linux + Windows + Mixed + + + RAIDdefaultWritePolicy + WriteBack + Disk.Virtual.0:RAID.Integrated.1-1 + Disk.Virtual.0:RAID.Integrated.1-1:RAIDdefaultWritePolicy + false + + WriteThrough + WriteBack + WriteBackForce + + + RAIDdefaultReadPolicy + ReadAhead + Disk.Virtual.0:RAID.Integrated.1-1 + Disk.Virtual.0:RAID.Integrated.1-1:RAIDdefaultReadPolicy + false + + NoReadAhead + ReadAhead + AdaptiveReadAhead + + + DiskCachePolicy + Disabled + Disk.Virtual.0:RAID.Integrated.1-1 + Disk.Virtual.0:RAID.Integrated.1-1:DiskCachePolicy + false + + Default + Enabled + Disabled + + + T10PIStatus + Disabled + Disk.Virtual.0:RAID.Integrated.1-1 + Disk.Virtual.0:RAID.Integrated.1-1:T10PIStatus + true + + Disabled + Enabled + + + RAIDStripeSize + 512(256 KB) + Disk.Virtual.0:RAID.Integrated.1-1 + Disk.Virtual.0:RAID.Integrated.1-1:RAIDStripeSize + true + + 0 + 1(512 Bytes) + 2(1 KB) + 4(2 KB) + 8(4 KB) + 16(8 KB) + 32(16 KB) + 64(32 KB) + 128(64 KB) + 256(128 KB) + 512(256 KB) + 1024(512 KB) + 2048(1024 KB) + 4096(2048 KB) + 8192(4096 KB) + 16384(8192 KB) + 32768(16384 KB) + + + RAIDdefaultWritePolicy + WriteBack + Disk.Virtual.1:RAID.Integrated.1-1 + Disk.Virtual.1:RAID.Integrated.1-1:RAIDdefaultWritePolicy + false + + WriteThrough + WriteBack + WriteBackForce + + + RAIDdefaultReadPolicy + ReadAhead + Disk.Virtual.1:RAID.Integrated.1-1 + Disk.Virtual.1:RAID.Integrated.1-1:RAIDdefaultReadPolicy + false + + NoReadAhead + ReadAhead + AdaptiveReadAhead + + + DiskCachePolicy + Disabled + Disk.Virtual.1:RAID.Integrated.1-1 + Disk.Virtual.1:RAID.Integrated.1-1:DiskCachePolicy + false + + Default + Enabled + Disabled + + + T10PIStatus + Disabled + Disk.Virtual.1:RAID.Integrated.1-1 + Disk.Virtual.1:RAID.Integrated.1-1:T10PIStatus + true + + Disabled + Enabled + + + RAIDStripeSize + 512(256 KB) + Disk.Virtual.1:RAID.Integrated.1-1 + Disk.Virtual.1:RAID.Integrated.1-1:RAIDStripeSize + true + + 0 + 1(512 Bytes) + 2(1 KB) + 4(2 KB) + 8(4 KB) + 16(8 KB) + 32(16 KB) + 64(32 KB) + 128(64 KB) + 256(128 KB) + 512(256 KB) + 1024(512 KB) + 2048(1024 KB) + 4096(2048 KB) + 8192(4096 KB) + 16384(8192 KB) + 32768(16384 KB) + + + RAIDdefaultWritePolicy + WriteBack + Disk.Virtual.2:RAID.Integrated.1-1 + Disk.Virtual.2:RAID.Integrated.1-1:RAIDdefaultWritePolicy + false + + WriteThrough + WriteBack + WriteBackForce + + + RAIDdefaultReadPolicy + ReadAhead + Disk.Virtual.2:RAID.Integrated.1-1 + Disk.Virtual.2:RAID.Integrated.1-1:RAIDdefaultReadPolicy + false + + NoReadAhead + ReadAhead + AdaptiveReadAhead + + + DiskCachePolicy + Disabled + Disk.Virtual.2:RAID.Integrated.1-1 + Disk.Virtual.2:RAID.Integrated.1-1:DiskCachePolicy + false + + Default + Enabled + Disabled + + + T10PIStatus + Disabled + Disk.Virtual.2:RAID.Integrated.1-1 + Disk.Virtual.2:RAID.Integrated.1-1:T10PIStatus + true + + Disabled + Enabled + + + RAIDStripeSize + 512(256 KB) + Disk.Virtual.2:RAID.Integrated.1-1 + Disk.Virtual.2:RAID.Integrated.1-1:RAIDStripeSize + true + + 0 + 1(512 Bytes) + 2(1 KB) + 4(2 KB) + 8(4 KB) + 16(8 KB) + 32(16 KB) + 64(32 KB) + 128(64 KB) + 256(128 KB) + 512(256 KB) + 1024(512 KB) + 2048(1024 KB) + 4096(2048 KB) + 8192(4096 KB) + 16384(8192 KB) + 32768(16384 KB) + + + RAIDdefaultWritePolicy + WriteBack + Disk.Virtual.3:RAID.Integrated.1-1 + Disk.Virtual.3:RAID.Integrated.1-1:RAIDdefaultWritePolicy + false + + WriteThrough + WriteBack + WriteBackForce + + + RAIDdefaultReadPolicy + ReadAhead + Disk.Virtual.3:RAID.Integrated.1-1 + Disk.Virtual.3:RAID.Integrated.1-1:RAIDdefaultReadPolicy + false + + NoReadAhead + ReadAhead + AdaptiveReadAhead + + + DiskCachePolicy + Disabled + Disk.Virtual.3:RAID.Integrated.1-1 + Disk.Virtual.3:RAID.Integrated.1-1:DiskCachePolicy + false + + Default + Enabled + Disabled + + + T10PIStatus + Disabled + Disk.Virtual.3:RAID.Integrated.1-1 + Disk.Virtual.3:RAID.Integrated.1-1:T10PIStatus + true + + Disabled + Enabled + + + RAIDStripeSize + 512(256 KB) + Disk.Virtual.3:RAID.Integrated.1-1 + Disk.Virtual.3:RAID.Integrated.1-1:RAIDStripeSize + true + + 0 + 1(512 Bytes) + 2(1 KB) + 4(2 KB) + 8(4 KB) + 16(8 KB) + 32(16 KB) + 64(32 KB) + 128(64 KB) + 256(128 KB) + 512(256 KB) + 1024(512 KB) + 2048(1024 KB) + 4096(2048 KB) + 8192(4096 KB) + 16384(8192 KB) + 32768(16384 KB) + + + RAIDdefaultWritePolicy + WriteBack + Disk.Virtual.4:RAID.Integrated.1-1 + Disk.Virtual.4:RAID.Integrated.1-1:RAIDdefaultWritePolicy + false + + WriteThrough + WriteBack + WriteBackForce + + + RAIDdefaultReadPolicy + ReadAhead + Disk.Virtual.4:RAID.Integrated.1-1 + Disk.Virtual.4:RAID.Integrated.1-1:RAIDdefaultReadPolicy + false + + NoReadAhead + ReadAhead + AdaptiveReadAhead + + + DiskCachePolicy + Disabled + Disk.Virtual.4:RAID.Integrated.1-1 + Disk.Virtual.4:RAID.Integrated.1-1:DiskCachePolicy + false + + Default + Enabled + Disabled + + + T10PIStatus + Disabled + Disk.Virtual.4:RAID.Integrated.1-1 + Disk.Virtual.4:RAID.Integrated.1-1:T10PIStatus + true + + Disabled + Enabled + + + RAIDStripeSize + 512(256 KB) + Disk.Virtual.4:RAID.Integrated.1-1 + Disk.Virtual.4:RAID.Integrated.1-1:RAIDStripeSize + true + + 0 + 1(512 Bytes) + 2(1 KB) + 4(2 KB) + 8(4 KB) + 16(8 KB) + 32(16 KB) + 64(32 KB) + 128(64 KB) + 256(128 KB) + 512(256 KB) + 1024(512 KB) + 2048(1024 KB) + 4096(2048 KB) + 8192(4096 KB) + 16384(8192 KB) + 32768(16384 KB) + + + RAIDdefaultWritePolicy + WriteBack + Disk.Virtual.5:RAID.Integrated.1-1 + Disk.Virtual.5:RAID.Integrated.1-1:RAIDdefaultWritePolicy + false + + WriteThrough + WriteBack + WriteBackForce + + + RAIDdefaultReadPolicy + ReadAhead + Disk.Virtual.5:RAID.Integrated.1-1 + Disk.Virtual.5:RAID.Integrated.1-1:RAIDdefaultReadPolicy + false + + NoReadAhead + ReadAhead + AdaptiveReadAhead + + + DiskCachePolicy + Disabled + Disk.Virtual.5:RAID.Integrated.1-1 + Disk.Virtual.5:RAID.Integrated.1-1:DiskCachePolicy + false + + Default + Enabled + Disabled + + + T10PIStatus + Disabled + Disk.Virtual.5:RAID.Integrated.1-1 + Disk.Virtual.5:RAID.Integrated.1-1:T10PIStatus + true + + Disabled + Enabled + + + RAIDStripeSize + 512(256 KB) + Disk.Virtual.5:RAID.Integrated.1-1 + Disk.Virtual.5:RAID.Integrated.1-1:RAIDStripeSize + true + + 0 + 1(512 Bytes) + 2(1 KB) + 4(2 KB) + 8(4 KB) + 16(8 KB) + 32(16 KB) + 64(32 KB) + 128(64 KB) + 256(128 KB) + 512(256 KB) + 1024(512 KB) + 2048(1024 KB) + 4096(2048 KB) + 8192(4096 KB) + 16384(8192 KB) + 32768(16384 KB) + + + RAIDdefaultWritePolicy + WriteBack + Disk.Virtual.6:RAID.Integrated.1-1 + Disk.Virtual.6:RAID.Integrated.1-1:RAIDdefaultWritePolicy + false + + WriteThrough + WriteBack + WriteBackForce + + + RAIDdefaultReadPolicy + ReadAhead + Disk.Virtual.6:RAID.Integrated.1-1 + Disk.Virtual.6:RAID.Integrated.1-1:RAIDdefaultReadPolicy + false + + NoReadAhead + ReadAhead + AdaptiveReadAhead + + + DiskCachePolicy + Disabled + Disk.Virtual.6:RAID.Integrated.1-1 + Disk.Virtual.6:RAID.Integrated.1-1:DiskCachePolicy + false + + Default + Enabled + Disabled + + + T10PIStatus + Disabled + Disk.Virtual.6:RAID.Integrated.1-1 + Disk.Virtual.6:RAID.Integrated.1-1:T10PIStatus + true + + Disabled + Enabled + + + RAIDStripeSize + 512(256 KB) + Disk.Virtual.6:RAID.Integrated.1-1 + Disk.Virtual.6:RAID.Integrated.1-1:RAIDStripeSize + true + + 0 + 1(512 Bytes) + 2(1 KB) + 4(2 KB) + 8(4 KB) + 16(8 KB) + 32(16 KB) + 64(32 KB) + 128(64 KB) + 256(128 KB) + 512(256 KB) + 1024(512 KB) + 2048(1024 KB) + 4096(2048 KB) + 8192(4096 KB) + 16384(8192 KB) + 32768(16384 KB) + + + RAIDdefaultWritePolicy + WriteBack + Disk.Virtual.7:RAID.Integrated.1-1 + Disk.Virtual.7:RAID.Integrated.1-1:RAIDdefaultWritePolicy + false + + WriteThrough + WriteBack + WriteBackForce + + + RAIDdefaultReadPolicy + ReadAhead + Disk.Virtual.7:RAID.Integrated.1-1 + Disk.Virtual.7:RAID.Integrated.1-1:RAIDdefaultReadPolicy + false + + NoReadAhead + ReadAhead + AdaptiveReadAhead + + + DiskCachePolicy + Disabled + Disk.Virtual.7:RAID.Integrated.1-1 + Disk.Virtual.7:RAID.Integrated.1-1:DiskCachePolicy + false + + Default + Enabled + Disabled + + + T10PIStatus + Disabled + Disk.Virtual.7:RAID.Integrated.1-1 + Disk.Virtual.7:RAID.Integrated.1-1:T10PIStatus + true + + Disabled + Enabled + + + RAIDStripeSize + 512(256 KB) + Disk.Virtual.7:RAID.Integrated.1-1 + Disk.Virtual.7:RAID.Integrated.1-1:RAIDStripeSize + true + + 0 + 1(512 Bytes) + 2(1 KB) + 4(2 KB) + 8(4 KB) + 16(8 KB) + 32(16 KB) + 64(32 KB) + 128(64 KB) + 256(128 KB) + 512(256 KB) + 1024(512 KB) + 2048(1024 KB) + 4096(2048 KB) + 8192(4096 KB) + 16384(8192 KB) + 32768(16384 KB) + + + RAIDdefaultWritePolicy + WriteBack + Disk.Virtual.8:RAID.Integrated.1-1 + Disk.Virtual.8:RAID.Integrated.1-1:RAIDdefaultWritePolicy + false + + WriteThrough + WriteBack + WriteBackForce + + + RAIDdefaultReadPolicy + ReadAhead + Disk.Virtual.8:RAID.Integrated.1-1 + Disk.Virtual.8:RAID.Integrated.1-1:RAIDdefaultReadPolicy + false + + NoReadAhead + ReadAhead + AdaptiveReadAhead + + + DiskCachePolicy + Disabled + Disk.Virtual.8:RAID.Integrated.1-1 + Disk.Virtual.8:RAID.Integrated.1-1:DiskCachePolicy + false + + Default + Enabled + Disabled + + + T10PIStatus + Disabled + Disk.Virtual.8:RAID.Integrated.1-1 + Disk.Virtual.8:RAID.Integrated.1-1:T10PIStatus + true + + Disabled + Enabled + + + RAIDStripeSize + 512(256 KB) + Disk.Virtual.8:RAID.Integrated.1-1 + Disk.Virtual.8:RAID.Integrated.1-1:RAIDStripeSize + true + + 0 + 1(512 Bytes) + 2(1 KB) + 4(2 KB) + 8(4 KB) + 16(8 KB) + 32(16 KB) + 64(32 KB) + 128(64 KB) + 256(128 KB) + 512(256 KB) + 1024(512 KB) + 2048(1024 KB) + 4096(2048 KB) + 8192(4096 KB) + 16384(8192 KB) + 32768(16384 KB) + + + RAIDdefaultWritePolicy + WriteBack + Disk.Virtual.9:RAID.Integrated.1-1 + Disk.Virtual.9:RAID.Integrated.1-1:RAIDdefaultWritePolicy + false + + WriteThrough + WriteBack + WriteBackForce + + + RAIDdefaultReadPolicy + ReadAhead + Disk.Virtual.9:RAID.Integrated.1-1 + Disk.Virtual.9:RAID.Integrated.1-1:RAIDdefaultReadPolicy + false + + NoReadAhead + ReadAhead + AdaptiveReadAhead + + + DiskCachePolicy + Disabled + Disk.Virtual.9:RAID.Integrated.1-1 + Disk.Virtual.9:RAID.Integrated.1-1:DiskCachePolicy + false + + Default + Enabled + Disabled + + + T10PIStatus + Disabled + Disk.Virtual.9:RAID.Integrated.1-1 + Disk.Virtual.9:RAID.Integrated.1-1:T10PIStatus + true + + Disabled + Enabled + + + RAIDStripeSize + 512(256 KB) + Disk.Virtual.9:RAID.Integrated.1-1 + Disk.Virtual.9:RAID.Integrated.1-1:RAIDStripeSize + true + + 0 + 1(512 Bytes) + 2(1 KB) + 4(2 KB) + 8(4 KB) + 16(8 KB) + 32(16 KB) + 64(32 KB) + 128(64 KB) + 256(128 KB) + 512(256 KB) + 1024(512 KB) + 2048(1024 KB) + 4096(2048 KB) + 8192(4096 KB) + 16384(8192 KB) + 32768(16384 KB) + + + RAIDdefaultWritePolicy + WriteBack + Disk.Virtual.10:RAID.Integrated.1-1 + Disk.Virtual.10:RAID.Integrated.1-1:RAIDdefaultWritePolicy + false + + WriteThrough + WriteBack + WriteBackForce + + + RAIDdefaultReadPolicy + ReadAhead + Disk.Virtual.10:RAID.Integrated.1-1 + Disk.Virtual.10:RAID.Integrated.1-1:RAIDdefaultReadPolicy + false + + NoReadAhead + ReadAhead + AdaptiveReadAhead + + + DiskCachePolicy + Disabled + Disk.Virtual.10:RAID.Integrated.1-1 + Disk.Virtual.10:RAID.Integrated.1-1:DiskCachePolicy + false + + Default + Enabled + Disabled + + + T10PIStatus + Disabled + Disk.Virtual.10:RAID.Integrated.1-1 + Disk.Virtual.10:RAID.Integrated.1-1:T10PIStatus + true + + Disabled + Enabled + + + RAIDStripeSize + 512(256 KB) + Disk.Virtual.10:RAID.Integrated.1-1 + Disk.Virtual.10:RAID.Integrated.1-1:RAIDStripeSize + true + + 0 + 1(512 Bytes) + 2(1 KB) + 4(2 KB) + 8(4 KB) + 16(8 KB) + 32(16 KB) + 64(32 KB) + 128(64 KB) + 256(128 KB) + 512(256 KB) + 1024(512 KB) + 2048(1024 KB) + 4096(2048 KB) + 8192(4096 KB) + 16384(8192 KB) + 32768(16384 KB) + + + RAIDdefaultWritePolicy + WriteBack + Disk.Virtual.11:RAID.Integrated.1-1 + Disk.Virtual.11:RAID.Integrated.1-1:RAIDdefaultWritePolicy + false + + WriteThrough + WriteBack + WriteBackForce + + + RAIDdefaultReadPolicy + ReadAhead + Disk.Virtual.11:RAID.Integrated.1-1 + Disk.Virtual.11:RAID.Integrated.1-1:RAIDdefaultReadPolicy + false + + NoReadAhead + ReadAhead + AdaptiveReadAhead + + + DiskCachePolicy + Disabled + Disk.Virtual.11:RAID.Integrated.1-1 + Disk.Virtual.11:RAID.Integrated.1-1:DiskCachePolicy + false + + Default + Enabled + Disabled + + + T10PIStatus + Disabled + Disk.Virtual.11:RAID.Integrated.1-1 + Disk.Virtual.11:RAID.Integrated.1-1:T10PIStatus + true + + Disabled + Enabled + + + RAIDStripeSize + 512(256 KB) + Disk.Virtual.11:RAID.Integrated.1-1 + Disk.Virtual.11:RAID.Integrated.1-1:RAIDStripeSize + true + + 0 + 1(512 Bytes) + 2(1 KB) + 4(2 KB) + 8(4 KB) + 16(8 KB) + 32(16 KB) + 64(32 KB) + 128(64 KB) + 256(128 KB) + 512(256 KB) + 1024(512 KB) + 2048(1024 KB) + 4096(2048 KB) + 8192(4096 KB) + 16384(8192 KB) + 32768(16384 KB) + + + RAIDdefaultWritePolicy + WriteBack + Disk.Virtual.12:RAID.Integrated.1-1 + Disk.Virtual.12:RAID.Integrated.1-1:RAIDdefaultWritePolicy + false + + WriteThrough + WriteBack + WriteBackForce + + + RAIDdefaultReadPolicy + ReadAhead + Disk.Virtual.12:RAID.Integrated.1-1 + Disk.Virtual.12:RAID.Integrated.1-1:RAIDdefaultReadPolicy + false + + NoReadAhead + ReadAhead + AdaptiveReadAhead + + + DiskCachePolicy + Disabled + Disk.Virtual.12:RAID.Integrated.1-1 + Disk.Virtual.12:RAID.Integrated.1-1:DiskCachePolicy + false + + Default + Enabled + Disabled + + + T10PIStatus + Disabled + Disk.Virtual.12:RAID.Integrated.1-1 + Disk.Virtual.12:RAID.Integrated.1-1:T10PIStatus + true + + Disabled + Enabled + + + RAIDStripeSize + 512(256 KB) + Disk.Virtual.12:RAID.Integrated.1-1 + Disk.Virtual.12:RAID.Integrated.1-1:RAIDStripeSize + true + + 0 + 1(512 Bytes) + 2(1 KB) + 4(2 KB) + 8(4 KB) + 16(8 KB) + 32(16 KB) + 64(32 KB) + 128(64 KB) + 256(128 KB) + 512(256 KB) + 1024(512 KB) + 2048(1024 KB) + 4096(2048 KB) + 8192(4096 KB) + 16384(8192 KB) + 32768(16384 KB) + + + RAIDdefaultWritePolicy + WriteBack + Disk.Virtual.13:RAID.Integrated.1-1 + Disk.Virtual.13:RAID.Integrated.1-1:RAIDdefaultWritePolicy + false + + WriteThrough + WriteBack + WriteBackForce + + + RAIDdefaultReadPolicy + ReadAhead + Disk.Virtual.13:RAID.Integrated.1-1 + Disk.Virtual.13:RAID.Integrated.1-1:RAIDdefaultReadPolicy + false + + NoReadAhead + ReadAhead + AdaptiveReadAhead + + + DiskCachePolicy + Enabled + Disk.Virtual.13:RAID.Integrated.1-1 + Disk.Virtual.13:RAID.Integrated.1-1:DiskCachePolicy + false + + Default + Enabled + Disabled + + + T10PIStatus + Disabled + Disk.Virtual.13:RAID.Integrated.1-1 + Disk.Virtual.13:RAID.Integrated.1-1:T10PIStatus + true + + Disabled + Enabled + + + RAIDStripeSize + 512(256 KB) + Disk.Virtual.13:RAID.Integrated.1-1 + Disk.Virtual.13:RAID.Integrated.1-1:RAIDStripeSize + true + + 0 + 1(512 Bytes) + 2(1 KB) + 4(2 KB) + 8(4 KB) + 16(8 KB) + 32(16 KB) + 64(32 KB) + 128(64 KB) + 256(128 KB) + 512(256 KB) + 1024(512 KB) + 2048(1024 KB) + 4096(2048 KB) + 8192(4096 KB) + 16384(8192 KB) + 32768(16384 KB) + + + RAIDdefaultWritePolicy + WriteBack + Disk.Virtual.14:RAID.Integrated.1-1 + Disk.Virtual.14:RAID.Integrated.1-1:RAIDdefaultWritePolicy + false + + WriteThrough + WriteBack + WriteBackForce + + + RAIDdefaultReadPolicy + ReadAhead + Disk.Virtual.14:RAID.Integrated.1-1 + Disk.Virtual.14:RAID.Integrated.1-1:RAIDdefaultReadPolicy + false + + NoReadAhead + ReadAhead + AdaptiveReadAhead + + + DiskCachePolicy + Enabled + Disk.Virtual.14:RAID.Integrated.1-1 + Disk.Virtual.14:RAID.Integrated.1-1:DiskCachePolicy + false + + Default + Enabled + Disabled + + + T10PIStatus + Disabled + Disk.Virtual.14:RAID.Integrated.1-1 + Disk.Virtual.14:RAID.Integrated.1-1:T10PIStatus + true + + Disabled + Enabled + + + RAIDStripeSize + 512(256 KB) + Disk.Virtual.14:RAID.Integrated.1-1 + Disk.Virtual.14:RAID.Integrated.1-1:RAIDStripeSize + true + + 0 + 1(512 Bytes) + 2(1 KB) + 4(2 KB) + 8(4 KB) + 16(8 KB) + 32(16 KB) + 64(32 KB) + 128(64 KB) + 256(128 KB) + 512(256 KB) + 1024(512 KB) + 2048(1024 KB) + 4096(2048 KB) + 8192(4096 KB) + 16384(8192 KB) + 32768(16384 KB) + + + RAIDdefaultWritePolicy + WriteBack + Disk.Virtual.15:RAID.Integrated.1-1 + Disk.Virtual.15:RAID.Integrated.1-1:RAIDdefaultWritePolicy + false + + WriteThrough + WriteBack + WriteBackForce + + + RAIDdefaultReadPolicy + ReadAhead + Disk.Virtual.15:RAID.Integrated.1-1 + Disk.Virtual.15:RAID.Integrated.1-1:RAIDdefaultReadPolicy + false + + NoReadAhead + ReadAhead + AdaptiveReadAhead + + + DiskCachePolicy + Enabled + Disk.Virtual.15:RAID.Integrated.1-1 + Disk.Virtual.15:RAID.Integrated.1-1:DiskCachePolicy + false + + Default + Enabled + Disabled + + + T10PIStatus + Disabled + Disk.Virtual.15:RAID.Integrated.1-1 + Disk.Virtual.15:RAID.Integrated.1-1:T10PIStatus + true + + Disabled + Enabled + + + RAIDStripeSize + 512(256 KB) + Disk.Virtual.15:RAID.Integrated.1-1 + Disk.Virtual.15:RAID.Integrated.1-1:RAIDStripeSize + true + + 0 + 1(512 Bytes) + 2(1 KB) + 4(2 KB) + 8(4 KB) + 16(8 KB) + 32(16 KB) + 64(32 KB) + 128(64 KB) + 256(128 KB) + 512(256 KB) + 1024(512 KB) + 2048(1024 KB) + 4096(2048 KB) + 8192(4096 KB) + 16384(8192 KB) + 32768(16384 KB) + + + RAIDdefaultWritePolicy + WriteBack + Disk.Virtual.16:RAID.Integrated.1-1 + Disk.Virtual.16:RAID.Integrated.1-1:RAIDdefaultWritePolicy + false + + WriteThrough + WriteBack + WriteBackForce + + + RAIDdefaultReadPolicy + ReadAhead + Disk.Virtual.16:RAID.Integrated.1-1 + Disk.Virtual.16:RAID.Integrated.1-1:RAIDdefaultReadPolicy + false + + NoReadAhead + ReadAhead + AdaptiveReadAhead + + + DiskCachePolicy + Enabled + Disk.Virtual.16:RAID.Integrated.1-1 + Disk.Virtual.16:RAID.Integrated.1-1:DiskCachePolicy + false + + Default + Enabled + Disabled + + + T10PIStatus + Disabled + Disk.Virtual.16:RAID.Integrated.1-1 + Disk.Virtual.16:RAID.Integrated.1-1:T10PIStatus + true + + Disabled + Enabled + + + RAIDStripeSize + 512(256 KB) + Disk.Virtual.16:RAID.Integrated.1-1 + Disk.Virtual.16:RAID.Integrated.1-1:RAIDStripeSize + true + + 0 + 1(512 Bytes) + 2(1 KB) + 4(2 KB) + 8(4 KB) + 16(8 KB) + 32(16 KB) + 64(32 KB) + 128(64 KB) + 256(128 KB) + 512(256 KB) + 1024(512 KB) + 2048(1024 KB) + 4096(2048 KB) + 8192(4096 KB) + 16384(8192 KB) + 32768(16384 KB) + + + RAIDdefaultWritePolicy + WriteBack + Disk.Virtual.17:RAID.Integrated.1-1 + Disk.Virtual.17:RAID.Integrated.1-1:RAIDdefaultWritePolicy + false + + WriteThrough + WriteBack + WriteBackForce + + + RAIDdefaultReadPolicy + ReadAhead + Disk.Virtual.17:RAID.Integrated.1-1 + Disk.Virtual.17:RAID.Integrated.1-1:RAIDdefaultReadPolicy + false + + NoReadAhead + ReadAhead + AdaptiveReadAhead + + + DiskCachePolicy + Disabled + Disk.Virtual.17:RAID.Integrated.1-1 + Disk.Virtual.17:RAID.Integrated.1-1:DiskCachePolicy + false + + Default + Enabled + Disabled + + + T10PIStatus + Disabled + Disk.Virtual.17:RAID.Integrated.1-1 + Disk.Virtual.17:RAID.Integrated.1-1:T10PIStatus + true + + Disabled + Enabled + + + RAIDStripeSize + 512(256 KB) + Disk.Virtual.17:RAID.Integrated.1-1 + Disk.Virtual.17:RAID.Integrated.1-1:RAIDStripeSize + true + + 0 + 1(512 Bytes) + 2(1 KB) + 4(2 KB) + 8(4 KB) + 16(8 KB) + 32(16 KB) + 64(32 KB) + 128(64 KB) + 256(128 KB) + 512(256 KB) + 1024(512 KB) + 2048(1024 KB) + 4096(2048 KB) + 8192(4096 KB) + 16384(8192 KB) + 32768(16384 KB) + + + RAIDdefaultWritePolicy + WriteBack + Disk.Virtual.18:RAID.Integrated.1-1 + Disk.Virtual.18:RAID.Integrated.1-1:RAIDdefaultWritePolicy + false + + WriteThrough + WriteBack + WriteBackForce + + + RAIDdefaultReadPolicy + ReadAhead + Disk.Virtual.18:RAID.Integrated.1-1 + Disk.Virtual.18:RAID.Integrated.1-1:RAIDdefaultReadPolicy + false + + NoReadAhead + ReadAhead + AdaptiveReadAhead + + + DiskCachePolicy + Disabled + Disk.Virtual.18:RAID.Integrated.1-1 + Disk.Virtual.18:RAID.Integrated.1-1:DiskCachePolicy + false + + Default + Enabled + Disabled + + + T10PIStatus + Disabled + Disk.Virtual.18:RAID.Integrated.1-1 + Disk.Virtual.18:RAID.Integrated.1-1:T10PIStatus + true + + Disabled + Enabled + + + RAIDStripeSize + 512(256 KB) + Disk.Virtual.18:RAID.Integrated.1-1 + Disk.Virtual.18:RAID.Integrated.1-1:RAIDStripeSize + true + + 0 + 1(512 Bytes) + 2(1 KB) + 4(2 KB) + 8(4 KB) + 16(8 KB) + 32(16 KB) + 64(32 KB) + 128(64 KB) + 256(128 KB) + 512(256 KB) + 1024(512 KB) + 2048(1024 KB) + 4096(2048 KB) + 8192(4096 KB) + 16384(8192 KB) + 32768(16384 KB) + + + RAIDMultipath + Off + Enclosure.Internal.0-1:RAID.Integrated.1-1 + Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDMultipath + true + + Off + On + + + BackplaneType + Not Shared + Enclosure.Internal.0-1:RAID.Integrated.1-1 + Enclosure.Internal.0-1:RAID.Integrated.1-1:BackplaneType + true + + Not Shared + Shared + + + RAIDPDState + Online + Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDPDState + true + + Unknown + Ready + Online + Foreign + Blocked + Failed + Non-RAID + Missing + Offline + + + RAIDHotSpareStatus + No + Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDHotSpareStatus + true + + No + Dedicated + Global + + + RAIDNegotiatedSpeed + 12_GBS + Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNegotiatedSpeed + true + + 1_5_GBS + 3_GBS + 6_GBS + 12_GBS + + + RAIDPDState + Online + Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDPDState + true + + Unknown + Ready + Online + Foreign + Blocked + Failed + Non-RAID + Missing + Offline + + + RAIDHotSpareStatus + No + Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDHotSpareStatus + true + + No + Dedicated + Global + + + RAIDNegotiatedSpeed + 12_GBS + Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNegotiatedSpeed + true + + 1_5_GBS + 3_GBS + 6_GBS + 12_GBS + + + RAIDPDState + Online + Disk.Bay.2:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.2:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDPDState + true + + Unknown + Ready + Online + Foreign + Blocked + Failed + Non-RAID + Missing + Offline + + + RAIDHotSpareStatus + No + Disk.Bay.2:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.2:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDHotSpareStatus + true + + No + Dedicated + Global + + + RAIDNegotiatedSpeed + 12_GBS + Disk.Bay.2:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.2:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNegotiatedSpeed + true + + 1_5_GBS + 3_GBS + 6_GBS + 12_GBS + + + RAIDPDState + Online + Disk.Bay.3:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.3:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDPDState + true + + Unknown + Ready + Online + Foreign + Blocked + Failed + Non-RAID + Missing + Offline + + + RAIDHotSpareStatus + No + Disk.Bay.3:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.3:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDHotSpareStatus + true + + No + Dedicated + Global + + + RAIDNegotiatedSpeed + 12_GBS + Disk.Bay.3:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.3:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNegotiatedSpeed + true + + 1_5_GBS + 3_GBS + 6_GBS + 12_GBS + + + RAIDPDState + Online + Disk.Bay.4:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.4:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDPDState + true + + Unknown + Ready + Online + Foreign + Blocked + Failed + Non-RAID + Missing + Offline + + + RAIDHotSpareStatus + No + Disk.Bay.4:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.4:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDHotSpareStatus + + true + + No + Dedicated + Global + + + RAIDNegotiatedSpeed + 12_GBS + Disk.Bay.4:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.4:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNegotiatedSpeed + true + + 1_5_GBS + 3_GBS + 6_GBS + 12_GBS + + + RAIDPDState + Online + Disk.Bay.5:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.5:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDPDState + true + + Unknown + Ready + Online + Foreign + Blocked + Failed + Non-RAID + Missing + Offline + + + RAIDHotSpareStatus + No + Disk.Bay.5:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.5:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDHotSpareStatus + true + + No + Dedicated + Global + + + RAIDNegotiatedSpeed + 12_GBS + Disk.Bay.5:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.5:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNegotiatedSpeed + true + + 1_5_GBS + 3_GBS + 6_GBS + 12_GBS + + + RAIDPDState + Online + Disk.Bay.6:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.6:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDPDState + true + + Unknown + Ready + Online + Foreign + Blocked + Failed + Non-RAID + Missing + Offline + + + RAIDHotSpareStatus + No + Disk.Bay.6:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.6:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDHotSpareStatus + true + + No + Dedicated + Global + + + RAIDNegotiatedSpeed + 12_GBS + Disk.Bay.6:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.6:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNegotiatedSpeed + true + + 1_5_GBS + 3_GBS + 6_GBS + 12_GBS + + + RAIDPDState + Online + Disk.Bay.7:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.7:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDPDState + true + + Unknown + Ready + Online + Foreign + Blocked + Failed + Non-RAID + Missing + Offline + + + RAIDHotSpareStatus + No + Disk.Bay.7:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.7:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDHotSpareStatus + true + + No + Dedicated + Global + + + RAIDNegotiatedSpeed + 12_GBS + Disk.Bay.7:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.7:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNegotiatedSpeed + true + + 1_5_GBS + 3_GBS + 6_GBS + 12_GBS + + + RAIDPDState + Online + Disk.Bay.8:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.8:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDPDState + true + + Unknown + Ready + Online + Foreign + Blocked + Failed + Non-RAID + Missing + Offline + + + RAIDHotSpareStatus + No + Disk.Bay.8:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.8:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDHotSpareStatus + true + + No + Dedicated + Global + + + RAIDNegotiatedSpeed + 12_GBS + Disk.Bay.8:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.8:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNegotiatedSpeed + true + + 1_5_GBS + 3_GBS + 6_GBS + 12_GBS + + + RAIDPDState + Online + Disk.Bay.9:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.9:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDPDState + true + + Unknown + Ready + Online + Foreign + Blocked + Failed + Non-RAID + Missing + Offline + + + RAIDHotSpareStatus + No + Disk.Bay.9:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.9:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDHotSpareStatus + true + + No + Dedicated + Global + + + RAIDNegotiatedSpeed + 12_GBS + Disk.Bay.9:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.9:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNegotiatedSpeed + true + + 1_5_GBS + 3_GBS + 6_GBS + 12_GBS + + + RAIDPDState + Online + Disk.Bay.10:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.10:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDPDState + true + + Unknown + Ready + Online + Foreign + Blocked + Failed + Non-RAID + Missing + Offline + + + RAIDHotSpareStatus + No + Disk.Bay.10:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.10:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDHotSpareStatus + true + + No + Dedicated + Global + + + RAIDNegotiatedSpeed + 12_GBS + Disk.Bay.10:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.10:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNegotiatedSpeed + true + + 1_5_GBS + 3_GBS + 6_GBS + 12_GBS + + + RAIDPDState + Online + Disk.Bay.11:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.11:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDPDState + true + + Unknown + Ready + Online + Foreign + Blocked + Failed + Non-RAID + Missing + Offline + + + RAIDHotSpareStatus + No + Disk.Bay.11:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.11:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDHotSpareStatus + true + + No + Dedicated + Global + + + RAIDNegotiatedSpeed + 12_GBS + Disk.Bay.11:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.11:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNegotiatedSpeed + true + + 1_5_GBS + 3_GBS + 6_GBS + 12_GBS + + + RAIDPDState + Online + Disk.Bay.12:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.12:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDPDState + true + + Unknown + Ready + Online + Foreign + Blocked + Failed + Non-RAID + Missing + Offline + + + RAIDHotSpareStatus + No + Disk.Bay.12:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.12:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDHotSpareStatus + true + + No + Dedicated + Global + + + RAIDNegotiatedSpeed + 6_GBS + Disk.Bay.12:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.12:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNegotiatedSpeed + true + + 1_5_GBS + 3_GBS + 6_GBS + 12_GBS + + + RAIDPDState + Online + Disk.Bay.13:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.13:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDPDState + true + + Unknown + Ready + Online + Foreign + Blocked + Failed + Non-RAID + Missing + Offline + + + RAIDHotSpareStatus + No + Disk.Bay.13:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.13:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDHotSpareStatus + true + + No + Dedicated + Global + + + RAIDNegotiatedSpeed + 6_GBS + Disk.Bay.13:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.13:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNegotiatedSpeed + true + + 1_5_GBS + 3_GBS + 6_GBS + 12_GBS + + + RAIDPDState + Online + Disk.Bay.14:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.14:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDPDState + true + + Unknown + Ready + Online + Foreign + Blocked + Failed + Non-RAID + Missing + Offline + + + RAIDHotSpareStatus + No + Disk.Bay.14:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.14:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDHotSpareStatus + true + + No + Dedicated + Global + + + RAIDNegotiatedSpeed + 6_GBS + Disk.Bay.14:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.14:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNegotiatedSpeed + true + + 1_5_GBS + 3_GBS + 6_GBS + 12_GBS + + + RAIDPDState + Online + Disk.Bay.15:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.15:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDPDState + true + + Unknown + Ready + Online + Foreign + Blocked + Failed + Non-RAID + Missing + Offline + + + RAIDHotSpareStatus + No + Disk.Bay.15:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.15:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDHotSpareStatus + true + + No + Dedicated + Global + + + RAIDNegotiatedSpeed + 6_GBS + Disk.Bay.15:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.15:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNegotiatedSpeed + true + + 1_5_GBS + 3_GBS + 6_GBS + 12_GBS + + + RAIDPDState + Online + Disk.Bay.16:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.16:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDPDState + true + + Unknown + Ready + Online + Foreign + Blocked + Failed + Non-RAID + Missing + Offline + + + RAIDHotSpareStatus + No + Disk.Bay.16:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.16:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDHotSpareStatus + true + + No + Dedicated + Global + + + RAIDNegotiatedSpeed + 12_GBS + Disk.Bay.16:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.16:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNegotiatedSpeed + true + + 1_5_GBS + 3_GBS + 6_GBS + 12_GBS + + + RAIDPDState + Online + Disk.Bay.17:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.17:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDPDState + true + + Unknown + Ready + Online + Foreign + Blocked + Failed + Non-RAID + Missing + Offline + + + RAIDHotSpareStatus + No + Disk.Bay.17:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.17:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDHotSpareStatus + true + + No + Dedicated + Global + + + RAIDNegotiatedSpeed + 12_GBS + Disk.Bay.17:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.17:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNegotiatedSpeed + true + + 1_5_GBS + 3_GBS + 6_GBS + 12_GBS + + + RAIDPDState + Online + Disk.Bay.18:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.18:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDPDState + true + + Unknown + Ready + Online + Foreign + Blocked + Failed + Non-RAID + Missing + Offline + + + RAIDHotSpareStatus + No + Disk.Bay.18:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.18:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDHotSpareStatus + true + + No + Dedicated + Global + + + RAIDNegotiatedSpeed + 12_GBS + Disk.Bay.18:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.18:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNegotiatedSpeed + true + + 1_5_GBS + 3_GBS + 6_GBS + 12_GBS + + + RAIDPDState + Online + Disk.Bay.19:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.19:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDPDState + true + + Unknown + Ready + Online + Foreign + Blocked + Failed + Non-RAID + Missing + Offline + + + RAIDHotSpareStatus + No + Disk.Bay.19:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.19:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDHotSpareStatus + true + + No + Dedicated + Global + + + RAIDNegotiatedSpeed + 12_GBS + Disk.Bay.19:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.19:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNegotiatedSpeed + true + + 1_5_GBS + 3_GBS + 6_GBS + 12_GBS + + + + + + diff --git a/dracclient/tests/wsman_mocks/raid_integer-enum-ok.xml b/dracclient/tests/wsman_mocks/raid_integer-enum-ok.xml new file mode 100644 index 0000000..27c610c --- /dev/null +++ b/dracclient/tests/wsman_mocks/raid_integer-enum-ok.xml @@ -0,0 +1,416 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + uuid:40206465-1566-46e3-bf05-9952ba57ec3c + uuid:6af777f7-9ef1-1ef1-b067-84d3878fd94c + + + + + + RAIDmaxSupportedVD + 240 + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDmaxSupportedVD + true + 0 + + 0 + + + RAIDmaxPDsInSpan + 32 + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDmaxPDsInSpan + true + 0 + + 0 + + + RAIDmaxSpansInVD + 8 + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDmaxSpansInVD + true + 0 + + 0 + + + RAIDrebuildRate + 30 + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDrebuildRate + false + 0 + + 100 + + + RAIDccRate + 30 + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDccRate + false + 0 + + 100 + + + RAIDreconstructRate + 30 + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDreconstructRate + false + 0 + + 100 + + + RAIDbgiRate + 30 + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDbgiRate + false + 0 + + 100 + + + RAIDprRate + 30 + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDprRate + true + 0 + + 100 + + + RAIDspinDownIdleTime + 30 + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDspinDownIdleTime + true + 0 + + 65535 + + + RAIDprIterations + 0 + RAID.Integrated.1-1 + RAID.Integrated.1-1:RAIDprIterations + true + 1 + + 4294967295 + + + RAIDmaxSupportedVD + 0 + AHCI.Embedded.2-1 + AHCI.Embedded.2-1:RAIDmaxSupportedVD + true + 0 + + 0 + + + RAIDmaxPDsInSpan + 0 + AHCI.Embedded.2-1 + AHCI.Embedded.2-1:RAIDmaxPDsInSpan + true + 0 + + 0 + + + RAIDmaxSpansInVD + 0 + AHCI.Embedded.2-1 + AHCI.Embedded.2-1:RAIDmaxSpansInVD + true + 0 + + 0 + + + RAIDrebuildRate + 255 + AHCI.Embedded.2-1 + AHCI.Embedded.2-1:RAIDrebuildRate + true + 0 + + 100 + + + RAIDccRate + 255 + AHCI.Embedded.2-1 + AHCI.Embedded.2-1:RAIDccRate + true + 0 + + 100 + + + RAIDreconstructRate + 255 + AHCI.Embedded.2-1 + AHCI.Embedded.2-1:RAIDreconstructRate + true + 0 + + 100 + + + RAIDbgiRate + 255 + AHCI.Embedded.2-1 + AHCI.Embedded.2-1:RAIDbgiRate + true + 0 + + 100 + + + RAIDprRate + 255 + AHCI.Embedded.2-1 + AHCI.Embedded.2-1:RAIDprRate + true + 0 + + 100 + + + RAIDspinDownIdleTime + 0 + AHCI.Embedded.2-1 + AHCI.Embedded.2-1:RAIDspinDownIdleTime + true + 0 + + 65535 + + + RAIDprIterations + 0 + AHCI.Embedded.2-1 + AHCI.Embedded.2-1:RAIDprIterations + true + 1 + + 4294967295 + + + RAIDmaxSupportedVD + 0 + AHCI.Embedded.1-1 + AHCI.Embedded.1-1:RAIDmaxSupportedVD + true + 0 + + 0 + + + RAIDmaxPDsInSpan + 0 + AHCI.Embedded.1-1 + AHCI.Embedded.1-1:RAIDmaxPDsInSpan + true + 0 + + 0 + + + RAIDmaxSpansInVD + 0 + AHCI.Embedded.1-1 + AHCI.Embedded.1-1:RAIDmaxSpansInVD + true + 0 + + 0 + + + RAIDrebuildRate + 255 + AHCI.Embedded.1-1 + AHCI.Embedded.1-1:RAIDrebuildRate + true + 0 + + 100 + + + RAIDccRate + 255 + AHCI.Embedded.1-1 + AHCI.Embedded.1-1:RAIDccRate + true + 0 + + 100 + + + RAIDreconstructRate + 255 + AHCI.Embedded.1-1 + AHCI.Embedded.1-1:RAIDreconstructRate + true + 0 + + 100 + + + RAIDbgiRate + 255 + AHCI.Embedded.1-1 + AHCI.Embedded.1-1:RAIDbgiRate + true + 0 + + 100 + + + RAIDprRate + 255 + AHCI.Embedded.1-1 + AHCI.Embedded.1-1:RAIDprRate + true + 0 + + 100 + + + RAIDspinDownIdleTime + 0 + AHCI.Embedded.1-1 + AHCI.Embedded.1-1:RAIDspinDownIdleTime + true + 0 + + 65535 + + + RAIDprIterations + 0 + AHCI.Embedded.1-1 + AHCI.Embedded.1-1:RAIDprIterations + true + 1 + + 4294967295 + + + RAIDNominalMediumRotationRate + 10000 + Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNominalMediumRotationRate + true + 2 + + 4294967295 + + + RAIDNominalMediumRotationRate + 10000 + Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNominalMediumRotationRate + true + 2 + + 4294967295 + + + RAIDNominalMediumRotationRate + 10000 + Disk.Bay.2:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.2:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNominalMediumRotationRate + true + 2 + + 4294967295 + + + RAIDNominalMediumRotationRate + 10000 + Disk.Bay.3:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.3:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNominalMediumRotationRate + true + 2 + + 4294967295 + + + RAIDNominalMediumRotationRate + 10000 + Disk.Bay.4:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.4:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNominalMediumRotationRate + true + 2 + + 4294967295 + + + RAIDNominalMediumRotationRate + 10000 + Disk.Bay.5:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.5:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNominalMediumRotationRate + true + 2 + + 4294967295 + + + RAIDNominalMediumRotationRate + 10000 + Disk.Bay.6:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.6:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNominalMediumRotationRate + true + 2 + + 4294967295 + + + RAIDNominalMediumRotationRate + 10000 + Disk.Bay.7:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.7:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNominalMediumRotationRate + true + 2 + + 4294967295 + + + RAIDNominalMediumRotationRate + 10000 + Disk.Bay.8:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.8:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNominalMediumRotationRate + true + 2 + + 4294967295 + + + RAIDNominalMediumRotationRate + 10000 + Disk.Bay.9:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.9:Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDNominalMediumRotationRate + true + 2 + + 4294967295 + + + + + + + diff --git a/dracclient/tests/wsman_mocks/raid_service-invoke-clear_foreign_config-invalid_controller.xml b/dracclient/tests/wsman_mocks/raid_service-invoke-clear_foreign_config-invalid_controller.xml new file mode 100644 index 0000000..d60acb2 --- /dev/null +++ b/dracclient/tests/wsman_mocks/raid_service-invoke-clear_foreign_config-invalid_controller.xml @@ -0,0 +1,17 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_RAIDService/ClearForeignConfigResponse + uuid:f9487fcf-103a-103a-8002-fd0aa2bdb228 + uuid:000852e6-1040-1040-8997-a36fc6fe83b0 + + + + Controller not found + STOR030 + 2 + + + diff --git a/dracclient/tests/wsman_mocks/raid_service-invoke-clear_foreign_config-no_foreign_drive.xml b/dracclient/tests/wsman_mocks/raid_service-invoke-clear_foreign_config-no_foreign_drive.xml new file mode 100644 index 0000000..6ab74d7 --- /dev/null +++ b/dracclient/tests/wsman_mocks/raid_service-invoke-clear_foreign_config-no_foreign_drive.xml @@ -0,0 +1,17 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_RAIDService/ClearForeignConfigResponse + uuid:f9487fcf-103a-103a-8002-fd0aa2bdb228 + uuid:000852e6-1040-1040-8997-a36fc6fe83b0 + + + + No foreign drives detected + STOR018 + 2 + + + diff --git a/dracclient/tests/wsman_mocks/raid_service-invoke-clear_foreign_config-not_supported.xml b/dracclient/tests/wsman_mocks/raid_service-invoke-clear_foreign_config-not_supported.xml new file mode 100644 index 0000000..898e739 --- /dev/null +++ b/dracclient/tests/wsman_mocks/raid_service-invoke-clear_foreign_config-not_supported.xml @@ -0,0 +1,18 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_RAIDService/ClearForeignConfigResponse + uuid:473f8ede-9a1a-441a-aaf6-699c1476aa97 + uuid:55d91de0-90a1-10a1-8147-8c0c498fd94c + + + + The operation cannot be completed either because the operation is not supported on the target device, + or the RAIDType of "MD Software RAID" does not allow the operation. + STOR058 + 2 + + + diff --git a/dracclient/tests/wsman_mocks/raid_service-invoke-clear_foreign_config-ok.xml b/dracclient/tests/wsman_mocks/raid_service-invoke-clear_foreign_config-ok.xml new file mode 100644 index 0000000..dc303c5 --- /dev/null +++ b/dracclient/tests/wsman_mocks/raid_service-invoke-clear_foreign_config-ok.xml @@ -0,0 +1,16 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_RAIDService/ClearForeignConfigResponse + uuid:fefa06de-103a-103a-8002-fd0aa2bdb228 + uuid:05bc00f4-1040-1040-899d-a36fc6fe83b0 + + + + OPTIONAL + 0 + + + diff --git a/dracclient/tests/wsman_mocks/raid_service-invoke-delete_virtual_disk-error.xml b/dracclient/tests/wsman_mocks/raid_service-invoke-delete_virtual_disk-error.xml index c964a6b..37d5da2 100644 --- a/dracclient/tests/wsman_mocks/raid_service-invoke-delete_virtual_disk-error.xml +++ b/dracclient/tests/wsman_mocks/raid_service-invoke-delete_virtual_disk-error.xml @@ -14,4 +14,4 @@ 2 - \ No newline at end of file + diff --git a/dracclient/tests/wsman_mocks/raid_service-invoke-delete_virtual_disk-ok.xml b/dracclient/tests/wsman_mocks/raid_service-invoke-delete_virtual_disk-ok.xml index 0b3eff2..b1035c3 100644 --- a/dracclient/tests/wsman_mocks/raid_service-invoke-delete_virtual_disk-ok.xml +++ b/dracclient/tests/wsman_mocks/raid_service-invoke-delete_virtual_disk-ok.xml @@ -13,4 +13,4 @@ 0 - \ No newline at end of file + diff --git a/dracclient/tests/wsman_mocks/raid_service-invoke-reset_raid_config-error.xml b/dracclient/tests/wsman_mocks/raid_service-invoke-reset_raid_config-error.xml new file mode 100644 index 0000000..cad10be --- /dev/null +++ b/dracclient/tests/wsman_mocks/raid_service-invoke-reset_raid_config-error.xml @@ -0,0 +1,17 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_RAIDService/ResetConfigResponse + uuid:f9487fcf-103a-103a-8002-fd0aa2bdb228 + uuid:000852e6-1040-1040-8997-a36fc6fe83b0 + + + + Virtual Disk not found + STOR028 + 2 + + + diff --git a/dracclient/tests/wsman_mocks/raid_service-invoke-reset_raid_config-ok.xml b/dracclient/tests/wsman_mocks/raid_service-invoke-reset_raid_config-ok.xml new file mode 100644 index 0000000..867f54a --- /dev/null +++ b/dracclient/tests/wsman_mocks/raid_service-invoke-reset_raid_config-ok.xml @@ -0,0 +1,16 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_RAIDService/ResetConfigResponse + uuid:fefa06de-103a-103a-8002-fd0aa2bdb228 + uuid:05bc00f4-1040-1040-899d-a36fc6fe83b0 + + + + OPTIONAL + 0 + + + diff --git a/dracclient/tests/wsman_mocks/raid_service-invoke-set_attributes-error.xml b/dracclient/tests/wsman_mocks/raid_service-invoke-set_attributes-error.xml new file mode 100644 index 0000000..e79807b --- /dev/null +++ b/dracclient/tests/wsman_mocks/raid_service-invoke-set_attributes-error.xml @@ -0,0 +1,21 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + + http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_RAIDService/SetAttributesResponse + + uuid:bf8adefe-6fc0-456d-b97c-fd8d4aca2d6c + + uuid:84abf7b9-7176-1176-a11c-a53ffbd9bed4 + + + + + Invalid parameter value + STOR004 + 2 + + + diff --git a/dracclient/tests/wsman_mocks/raid_service-invoke-set_attributes-ok.xml b/dracclient/tests/wsman_mocks/raid_service-invoke-set_attributes-ok.xml new file mode 100644 index 0000000..50d5fd4 --- /dev/null +++ b/dracclient/tests/wsman_mocks/raid_service-invoke-set_attributes-ok.xml @@ -0,0 +1,24 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + + http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_RAIDService/SetAttributesResponse + + uuid:bf8adefe-6fc0-456d-b97c-fd8d4aca2d6c + + uuid:84abf7b9-7176-1176-a11c-a53ffbd9bed4 + + + + + STOR001 + The command was successful for all attributes + 0 + Yes + Set PendingValue + + + + diff --git a/dracclient/tests/wsman_mocks/raid_string-enum-ok.xml b/dracclient/tests/wsman_mocks/raid_string-enum-ok.xml new file mode 100644 index 0000000..866961f --- /dev/null +++ b/dracclient/tests/wsman_mocks/raid_string-enum-ok.xml @@ -0,0 +1,49 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + uuid:6f1e7eae-511a-4268-9913-c1ce1bb414be + uuid:6da65cf0-9cbb-1cbb-9773-deda878fd94c + + + + + + Name + Virtual Disk 0 + Disk.Virtual.0:RAID.Integrated.1-1 + Disk.Virtual.0:RAID.Integrated.1-1:Name + true + 129 + 0 + + + + Name + Virtual Disk 1 + Disk.Virtual.1:RAID.Integrated.1-1 + Disk.Virtual.1:RAID.Integrated.1-1:Name + true + 129 + 0 + + + + RAIDEffectiveSASAddress + 500056B3239C1AFD + Enclosure.Internal.0-1:RAID.Integrated.1-1 + Enclosure.Internal.0-1:RAID.Integrated.1-1:RAIDEffectiveSASAddress + true + 16 + 16 + + + + + + diff --git a/dracclient/tests/wsman_mocks/system_enumeration-enum-ok.xml b/dracclient/tests/wsman_mocks/system_enumeration-enum-ok.xml new file mode 100644 index 0000000..a790951 --- /dev/null +++ b/dracclient/tests/wsman_mocks/system_enumeration-enum-ok.xml @@ -0,0 +1,294 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + uuid:f150770f-b5b7-4b08-9572-b5225e7c668b + uuid:7c41ce96-41ee-11ee-a839-de7e4e771814 + + + + + + Power Cap Setting + PowerCapSetting + Disabled + Disabled + + 1401 + System.Embedded.1 + Server Power + ServerPwr.1 + System.Embedded.1#ServerPwr.1#PowerCapSetting + false + + Enabled + Disabled + + + Power Supply Redundancy Policy + PSRedPolicy + Input Power Redundant + Not Redundant + + 1405 + System.Embedded.1 + Server Power + ServerPwr.1 + System.Embedded.1#ServerPwr.1#PSRedPolicy + false + + Not Redundant + Input Power Redundant + + + Power Supply PFC Enable + PSPFCEnabled + Disabled + Disabled + + 1406 + System.Embedded.1 + Server Power + ServerPwr.1 + System.Embedded.1#ServerPwr.1#PSPFCEnabled + false + + Enabled + Disabled + + + Power Supply Rapid On Enable + PSRapidOn + Disabled + Enabled + + 1408 + System.Embedded.1 + Server Power + ServerPwr.1 + System.Embedded.1#ServerPwr.1#PSRapidOn + false + + Enabled + Disabled + + + Rapid on Primary PSU + RapidOnPrimaryPSU + PSU1 + PSU1 + + 1411 + System.Embedded.1 + Server Power + ServerPwr.1 + System.Embedded.1#ServerPwr.1#RapidOnPrimaryPSU + false + + PSU1 + PSU2 + + + LCD Configuration + Configuration + Service Tag + Service Tag + + 1432 + System.Embedded.1 + LCD + LCD.1 + System.Embedded.1#LCD.1#Configuration + false + + User Defined + Model Name + None + iDRAC IPv4 Address + iDRAC MAC Address + OS System Name + Service Tag + IPv6 Address + Ambient Temperature + System Watts + Asset Tag + + + vConsole Indication + vConsoleIndication + Disabled + Disabled + + 1434 + System.Embedded.1 + LCD + LCD.1 + System.Embedded.1#LCD.1#vConsoleIndication + false + + Enabled + Disabled + + + System Watt Qualifier + QualifierWatt + Watts + Watts + + 1435 + System.Embedded.1 + LCD + LCD.1 + System.Embedded.1#LCD.1#QualifierWatt + false + + Watts + BTU/hr + + + Ambient Temperature Qualifier + QualifierTemp + F + C + + 1436 + System.Embedded.1 + LCD + LCD.1 + System.Embedded.1#LCD.1#QualifierTemp + false + + C + F + + + Fresh Air Compliant Configuration + FreshAirCompliantConfiguration + Yes + Yes + + 1441 + System.Embedded.1 + Thermal Configuration + ThermalConfig.1 + System.Embedded.1#ThermalConfig.1#FreshAirCompliantConfiguration + true + + Not Applicable + Yes + No + + + Thermal Profile + ThermalProfile + Maximum Performance + Default Thermal Profile Settings + + 1470 + System.Embedded.1 + Thermal Settings + ThermalSettings.1 + System.Embedded.1#ThermalSettings.1#ThermalProfile + false + + Default Thermal Profile Settings + Maximum Performance + Minimum Power + + + Fan Speed Offset + FanSpeedOffset + Off + Off + + 1472 + System.Embedded.1 + Thermal Settings + ThermalSettings.1 + System.Embedded.1#ThermalSettings.1#FanSpeedOffset + false + + Off + Low Fan Speed + High Fan Speed + Medium Fan Speed + Max Fan Speed + + + Fan Speed Response for Third-Party PCI Cards + ThirdPartyPCIFanResponse + Enabled + Enabled + + 1480 + System.Embedded.1 + Thermal Settings + ThermalSettings.1 + System.Embedded.1#ThermalSettings.1#ThirdPartyPCIFanResponse + false + + Disabled + Enabled + + + Quick Sync Presence + Presence + Not Supported + Not Supported + + 2300 + System.Embedded.1 + Quick Sync + QuickSync.1 + System.Embedded.1#QuickSync.1#Presence + true + + Not Supported + Absent + Present + + + Backplane Bus Mode + BackplaneBusMode + I2C + Unknown + + 2330 + System.Embedded.1 + Backplane + Backplane.1 + System.Embedded.1#Backplane.1#BackplaneBusMode + true + + Unknown + I2C + SGPIO + + + LED State + ChassisLEDState + Off + Unknown + + 2372 + System.Embedded.1 + Powerstate + ChassisPwrState.1 + System.Embedded.1#ChassisPwrState.1#ChassisLEDState + false + + Unknown + Blinking + Off + + + + + + + diff --git a/dracclient/tests/wsman_mocks/system_integer-enum-ok.xml b/dracclient/tests/wsman_mocks/system_integer-enum-ok.xml new file mode 100644 index 0000000..5d6efaa --- /dev/null +++ b/dracclient/tests/wsman_mocks/system_integer-enum-ok.xml @@ -0,0 +1,277 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + uuid:9ce6b8f8-cd0e-4994-8db6-758ef8da9d8c + uuid:7c9354bc-41ee-11ee-a83d-de7e4e771814 + + + + + + Power Cap Value + PowerCapValue + 555 + 32767 + + 1402 + System.Embedded.1 + Server Power + ServerPwr.1 + System.Embedded.1#ServerPwr.1#PowerCapValue + false + 302 + + 578 + + + Power Cap Max Threshold + PowerCapMaxThres + 578 + 0 + + 1403 + System.Embedded.1 + Server Power + ServerPwr.1 + System.Embedded.1#ServerPwr.1#PowerCapMaxThres + true + + + + + + Power Cap Min Threshold + PowerCapMinThres + 302 + 0 + + 1404 + System.Embedded.1 + Server Power + ServerPwr.1 + System.Embedded.1#ServerPwr.1#PowerCapMinThres + true + + + + + + Active Power Cap Value + ActivePowerCapVal + 555 + 32767 + + 1409 + System.Embedded.1 + Server Power + ServerPwr.1 + System.Embedded.1#ServerPwr.1#ActivePowerCapVal + true + 302 + + 578 + + + Rack Slot + RackSlot + 1 + 1 + + 1424 + System.Embedded.1 + Server Topology + ServerTopology.1 + System.Embedded.1#ServerTopology.1#RackSlot + false + 1 + + 255 + + + Size of Managed System in U + SizeOfManagedSystemInU + 1 + 0 + + 1425 + System.Embedded.1 + Server Topology + ServerTopology.1 + System.Embedded.1#ServerTopology.1#SizeOfManagedSystemInU + true + + + + + + Event Generation Interval + EventGenerationInterval + 30 + 30 + + 1440 + System.Embedded.1 + Thermal Configuration + ThermalConfig.1 + System.Embedded.1#ThermalConfig.1#EventGenerationInterval + false + 0 + + 365 + + + Critical Event Generation Interval + CriticalEventGenerationInterval + 30 + 30 + + 1440 + System.Embedded.1 + Thermal Configuration + ThermalConfig.1 + System.Embedded.1#ThermalConfig.1#CriticalEventGenerationInterval + false + 0 + + 365 + + + Server Powered On Time Duration + ServerPoweredOnTime + 123456 + 0 + + 1453 + System.Embedded.1 + Server Operating System + ServerOS.1 + System.Embedded.1#ServerOS.1#ServerPoweredOnTime + true + + + + + + Minimum Fan Speed + MinimumFanSpeed + 255 + 0 + + 1473 + System.Embedded.1 + Thermal Settings + ThermalSettings.1 + System.Embedded.1#ThermalSettings.1#MinimumFanSpeed + false + 0 + + 65535 + + + MFS Minimum Limit + MFSMinimumLimit + 9 + 0 + + 1474 + System.Embedded.1 + Thermal Settings + ThermalSettings.1 + System.Embedded.1#ThermalSettings.1#MFSMinimumLimit + true + + + + + + MFS Maximum Limit + MFSMaximumLimit + 100 + 0 + + 1475 + System.Embedded.1 + Thermal Settings + ThermalSettings.1 + System.Embedded.1#ThermalSettings.1#MFSMaximumLimit + true + + + + + + Fan Speed Low Offset Value + FanSpeedLowOffsetVal + 35 + 0 + + 1476 + System.Embedded.1 + Thermal Settings + ThermalSettings.1 + System.Embedded.1#ThermalSettings.1#FanSpeedLowOffsetVal + true + + + + + + Fan Speed Medium Offset Value + FanSpeedMediumOffsetVal + 50 + 0 + + 1477 + System.Embedded.1 + Thermal Settings + ThermalSettings.1 + System.Embedded.1#ThermalSettings.1#FanSpeedMediumOffsetVal + true + + + + + + Fan Speed High Offset Value + FanSpeedHighOffsetVal + 55 + 0 + + 1478 + System.Embedded.1 + Thermal Settings + ThermalSettings.1 + System.Embedded.1#ThermalSettings.1#FanSpeedHighOffsetVal + true + + + + + + Fan Speed Maximum Offset Value + FanSpeedMaxOffsetVal + 100 + 0 + + 1479 + System.Embedded.1 + Thermal Settings + ThermalSettings.1 + System.Embedded.1#ThermalSettings.1#FanSpeedMaxOffsetVal + true + + + + + + + + + + diff --git a/dracclient/tests/wsman_mocks/system_string-enum-ok.xml b/dracclient/tests/wsman_mocks/system_string-enum-ok.xml new file mode 100644 index 0000000..8086367 --- /dev/null +++ b/dracclient/tests/wsman_mocks/system_string-enum-ok.xml @@ -0,0 +1,213 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + uuid:2c1819b5-9c87-44ee-bde1-88e43cd73edd + uuid:7c734ea8-41ee-11ee-a83b-de7e4e771814 + + + + + + Active Power Cap Policy Name + ActivePolicyName + iDRAC + + + 1410 + System.Embedded.1 + Server Power + ServerPwr.1 + System.Embedded.1#ServerPwr.1#ActivePolicyName + true + 128 + 0 + + + + Data Center Name + DataCenterName + + + + 1421 + System.Embedded.1 + Server Topology + ServerTopology.1 + System.Embedded.1#ServerTopology.1#DataCenterName + false + 128 + 0 + + + + Aisle Name + AisleName + + + + 1422 + System.Embedded.1 + Server Topology + ServerTopology.1 + System.Embedded.1#ServerTopology.1#AisleName + false + 128 + 0 + + + + Rack Name + RackName + + + + 1423 + System.Embedded.1 + Server Topology + ServerTopology.1 + System.Embedded.1#ServerTopology.1#RackName + false + 128 + 0 + + + + Room Name + RoomName + + + + 1428 + System.Embedded.1 + Server Topology + ServerTopology.1 + System.Embedded.1#ServerTopology.1#RoomName + false + 128 + 0 + + + + Current LCD Display String + CurrentDisplay + ST: 1234567 + + + 1431 + System.Embedded.1 + LCD + LCD.1 + System.Embedded.1#LCD.1#CurrentDisplay + true + 62 + 0 + + + + User Defined String for LCD + UserDefinedString + + + + 1433 + System.Embedded.1 + LCD + LCD.1 + System.Embedded.1#LCD.1#UserDefinedString + false + 62 + 0 + + + + Host Name + HostName + test-host1-1-dc.ops.domain.net + + + 1450 + System.Embedded.1 + Server Operating System + ServerOS.1 + System.Embedded.1#ServerOS.1#HostName + false + 62 + 0 + + + + Operating System Name + OSName + CentOS + + + 1451 + System.Embedded.1 + Server Operating System + ServerOS.1 + System.Embedded.1#ServerOS.1#OSName + false + 62 + 0 + + + + Operating System Version + OSVersion + release 6.8 (Final) Kernel 2.6.32-642.3.1.el6.x86_64 (x86_64) + + + 1452 + System.Embedded.1 + Server Operating System + ServerOS.1 + System.Embedded.1#ServerOS.1#OSVersion + true + 62 + 0 + + + + OEM Operating System Version + OEMOSVersion + release 6.8 (Final) Kernel 2.6.32-642.3.1.el6.x86_64 (x86_64) + + + 1454 + System.Embedded.1 + Server Operating System + ServerOS.1 + System.Embedded.1#ServerOS.1#OEMOSVersion + true + 62 + 0 + + + + OS App Collection Time + OSAppCollectionTime + N/A + + + 2310 + System.Embedded.1 + Server Information + Diagnostics.1 + System.Embedded.1#Diagnostics.1#OSAppCollectionTime + true + 64 + 0 + + + + + + + + diff --git a/dracclient/tests/wsman_mocks/system_view-enum-ok.xml b/dracclient/tests/wsman_mocks/system_view-enum-ok.xml index ad2d5a5..c10054b 100644 --- a/dracclient/tests/wsman_mocks/system_view-enum-ok.xml +++ b/dracclient/tests/wsman_mocks/system_view-enum-ok.xml @@ -15,9 +15,12 @@ System.Embedded.1 2.1.0 + PowerEdge R630 + A1B2C3D + ebd4edd3-dfd7-4c7d-a2c8-562b3c23b811 - \ No newline at end of file + diff --git a/dracclient/tests/wsman_mocks/virtual_disk_view-enum-ok.xml b/dracclient/tests/wsman_mocks/virtual_disk_view-enum-ok.xml index 1777050..ee507f2 100644 --- a/dracclient/tests/wsman_mocks/virtual_disk_view-enum-ok.xml +++ b/dracclient/tests/wsman_mocks/virtual_disk_view-enum-ok.xml @@ -30,7 +30,8 @@ Background Intialization 8 0 - + Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1 1 2 4 @@ -51,4 +52,4 @@ - \ No newline at end of file + diff --git a/dracclient/tests/wsman_mocks/virtual_disk_view-enum-with-raid-status-ok.xml b/dracclient/tests/wsman_mocks/virtual_disk_view-enum-with-raid-status-ok.xml new file mode 100644 index 0000000..c8e3151 --- /dev/null +++ b/dracclient/tests/wsman_mocks/virtual_disk_view-enum-with-raid-status-ok.xml @@ -0,0 +1,55 @@ + + + http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse + uuid:b182f1ee-103a-103a-8002-fd0aa2bdb228 + uuid:b80f21ed-103f-103f-8992-a36fc6fe83b0 + + + + + + 512 + 6 + 0 + Virtual Disk 0 on Integrated RAID Controller 1 + 1024 + Disk.Virtual.0:RAID.Integrated.1-1 + Disk.Virtual.0:RAID.Integrated.1-1 + 20150301200527.000000+000 + 20150301200527.000000+000 + 0 + 1 + disk 0 + 0 + Background Intialization + 8 + 0 + Disk.Bay.4:Enclosure.Internal.0-1:RAID.Integrated.1-1 + Disk.Bay.5:Enclosure.Internal.0-1:RAID.Integrated.1-1 + 1 + 2 + 4 + 16 + 1 + 1 + 599550590976 + 1 + 2 + 0 + 128 + 0 + 0 + 2 + + + + + + + diff --git a/dracclient/tests/wsman_mocks/wsman-enum_context-1.xml b/dracclient/tests/wsman_mocks/wsman-enum_context-1.xml index e9b265b..002cb69 100644 --- a/dracclient/tests/wsman_mocks/wsman-enum_context-1.xml +++ b/dracclient/tests/wsman_mocks/wsman-enum_context-1.xml @@ -1,6 +1,8 @@ + xmlns:wsen="http://schemas.xmlsoap.org/ws/2004/09/enumeration" + xmlns:wsman="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" + xmlns:n1="http://FooResource"> http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse @@ -10,6 +12,11 @@ enum-context-uuid + + + 1 + + diff --git a/dracclient/tests/wsman_mocks/wsman-enum_context-2.xml b/dracclient/tests/wsman_mocks/wsman-enum_context-2.xml index cab5e11..a2ae36c 100644 --- a/dracclient/tests/wsman_mocks/wsman-enum_context-2.xml +++ b/dracclient/tests/wsman_mocks/wsman-enum_context-2.xml @@ -14,7 +14,7 @@ enum-context-uuid - 1 + 2 diff --git a/dracclient/tests/wsman_mocks/wsman-enum_context-3.xml b/dracclient/tests/wsman_mocks/wsman-enum_context-3.xml index 38190c7..1516a9a 100644 --- a/dracclient/tests/wsman_mocks/wsman-enum_context-3.xml +++ b/dracclient/tests/wsman_mocks/wsman-enum_context-3.xml @@ -13,10 +13,10 @@ enum-context-uuid - 2 + 3 - 3 + 4 diff --git a/dracclient/tests/wsman_mocks/wsman-enum_context-4.xml b/dracclient/tests/wsman_mocks/wsman-enum_context-4.xml index 15e0490..81ddbf5 100644 --- a/dracclient/tests/wsman_mocks/wsman-enum_context-4.xml +++ b/dracclient/tests/wsman_mocks/wsman-enum_context-4.xml @@ -12,7 +12,7 @@ - 4 + 5 diff --git a/dracclient/utils.py b/dracclient/utils.py index 935cdb4..387f5b2 100644 --- a/dracclient/utils.py +++ b/dracclient/utils.py @@ -15,7 +15,13 @@ Common functionalities shared between different DRAC modules. """ +from dracclient import constants +import logging + from dracclient import exceptions +from dracclient import wsman + +LOG = logging.getLogger(__name__) NS_XMLSchema_Instance = 'http://www.w3.org/2001/XMLSchema-instance' @@ -24,6 +30,12 @@ RET_ERROR = '2' RET_CREATED = '4096' +REBOOT_REQUIRED = { + 'yes': constants.RebootRequired.true, + 'no': constants.RebootRequired.false, + 'optional': constants.RebootRequired.optional +} + def find_xml(doc, item, namespace, find_all=False): """Find the first or all elements in an ElementTree object. @@ -46,6 +58,15 @@ def find_xml(doc, item, namespace, find_all=False): return doc.find(query) +def _is_attr_non_nil(elem): + """Return whether an element is non-nil. + + :param elem: the element object. + :returns: whether the element is nil. + """ + return elem.attrib.get('{%s}nil' % NS_XMLSchema_Instance) != 'true' + + def get_wsman_resource_attr(doc, resource_uri, attr_name, nullable=False, allow_missing=False): """Find an attribute of a resource in an ElementTree object. @@ -78,11 +99,94 @@ def get_wsman_resource_attr(doc, resource_uri, attr_name, nullable=False, raise exceptions.DRACEmptyResponseField(attr=attr_name) return item.text.strip() else: - nil_attr = item.attrib.get('{%s}nil' % NS_XMLSchema_Instance) - if nil_attr != 'true': + if _is_attr_non_nil(item): return item.text.strip() +def get_all_wsman_resource_attrs(doc, resource_uri, attr_name, nullable=False): + """Find all instances of an attribute of a resource in an ElementTree. + + :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 any of the elements contain an + XMLSchema-instance namespaced nil attribute that has a + value of True. In this case, these elements will not be + returned. + :raises: DRACEmptyResponseField if any of the attributes in the XML doc + have no text and nullable is False. + :returns: a list containing the value of each of the instances of the + attribute. + """ + items = find_xml(doc, attr_name, resource_uri, find_all=True) + + if not nullable: + for item in items: + if item.text is None: + raise exceptions.DRACEmptyResponseField(attr=attr_name) + return [item.text.strip() for item in items] + else: + + return [item.text.strip() for item in items if _is_attr_non_nil(item)] + + +def build_return_dict(doc, resource_uri, + is_commit_required_value=None, + is_reboot_required_value=None): + """Builds a dictionary to be returned + + Build a dictionary to be returned from WSMAN operations that are not + read-only. + + :param doc: the element tree object. + :param resource_uri: the resource URI of the namespace. + :param is_commit_required_value: The value to be returned for + is_commit_required, or None if the value should be determined + from the doc. + :param is_reboot_required_value: The value to be returned for + is_reboot_required, or None if the value should be determined + from the doc. + :returns: a dictionary containing: + - is_commit_required: indicates if a commit is required. + - is_reboot_required: indicates if a reboot is required. + """ + + if is_reboot_required_value is not None and \ + is_reboot_required_value not in constants.RebootRequired.all(): + msg = ("is_reboot_required_value must be a member of the " + "RebootRequired enumeration or None. The passed value was " + "%(is_reboot_required_value)s" % { + 'is_reboot_required_value': is_reboot_required_value}) + raise exceptions.InvalidParameterValue(reason=msg) + + result = {} + if is_commit_required_value is None: + is_commit_required_value = is_commit_required(doc, resource_uri) + + result['is_commit_required'] = is_commit_required_value + + if is_reboot_required_value is None: + is_reboot_required_value = reboot_required(doc, resource_uri) + + result['is_reboot_required'] = is_reboot_required_value + + return result + + +def is_commit_required(doc, resource_uri): + """Check the response document if commit is required. + + If SetResult contains "pending" in the response then a commit is required. + + :param doc: the element tree object. + :param resource_uri: the resource URI of the namespace. + :returns: a boolean value indicating commit is required or not. + """ + + commit_required = find_xml(doc, 'SetResult', resource_uri) + return "pendingvalue" in commit_required.text.lower() + + def is_reboot_required(doc, resource_uri): """Check the response document if reboot is requested. @@ -99,6 +203,22 @@ def is_reboot_required(doc, resource_uri): return reboot_required.text.lower() == 'yes' +def reboot_required(doc, resource_uri): + """Check the response document if reboot is requested. + + RebootRequired attribute in the response indicates whether node needs to + be rebooted, so that the pending changes can be committed. + + :param doc: the element tree object. + :param resource_uri: the resource URI of the namespace. + :returns: True if reboot is required, False if it is not, and the string + "optional" if reboot is optional. + """ + + reboot_required_value = find_xml(doc, 'RebootRequired', resource_uri) + return REBOOT_REQUIRED[reboot_required_value.text.lower()] + + def validate_integer_value(value, attr_name, error_msgs): """Validate integer value""" @@ -110,3 +230,209 @@ def validate_integer_value(value, attr_name, error_msgs): int(value) except ValueError: error_msgs.append("'%s' is not an integer value" % attr_name) + + +def list_settings(client, namespaces, by_name=True, fqdd_filter=None, + name_formatter=None, wait_for_idrac=True): + """List the configuration settings + + :param client: an instance of WSManClient. + :param namespaces: a list of URI/class pairs to retrieve. + :param by_name: controls whether returned dictionary uses + attribute name or instance_id as key. + :param fqdd_filter: An FQDD used to filter the instances. Note that + this is only used when by_name is True. + :param name_formatter: a method used to format the keys in the + returned dictionary. By default, + attribute.name will be used. + :param wait_for_idrac: indicates whether or not to wait for the + iDRAC to be ready to accept commands before + issuing the command. + :returns: a dictionary with the settings using name or instance_id as + the key. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on error reported back by the DRAC + interface + """ + + result = {} + for (namespace, attr_cls) in namespaces: + attribs = _get_config(client, namespace, attr_cls, by_name, + fqdd_filter, name_formatter, wait_for_idrac) + 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(client, resource, attr_cls, by_name, fqdd_filter, + name_formatter, wait_for_idrac): + result = {} + + doc = client.enumerate(resource, wait_for_idrac=wait_for_idrac) + items = doc.find('.//{%s}Items' % wsman.NS_WSMAN) + + for item in items: + attribute = attr_cls.parse(item) + if by_name: + # Filter out all instances without a matching FQDD + if fqdd_filter is None or fqdd_filter == attribute.fqdd: + if name_formatter is None: + name = attribute.name + else: + name = name_formatter(attribute) + + result[name] = attribute + else: + result[attribute.instance_id] = attribute + + return result + + +def set_settings(settings_type, + client, + namespaces, + new_settings, + resource_uri, + cim_creation_class_name, + cim_name, + target, + name_formatter=None, + wait_for_idrac=True, + by_name=True): + """Generically handles setting various types of settings on the iDRAC + + This method pulls the current list of settings from the iDRAC then compares + that list against the passed new settings to determine if there are any + errors. If no errors exist then the settings are sent to the iDRAC using + the passed resource, target, etc. + + :param settings_type: a string indicating the settings type + :param client: an instance of WSManClient + :param namespaces: a list of URI/class pairs to retrieve. + :param new_settings: a dictionary containing the proposed values, with + each key being the name of attribute and the + value being the proposed value. + :param resource_uri: URI of resource to invoke + :param cim_creation_class_name: creation class name of the CIM object + :param cim_name: name of the CIM object + :param target: target device + :param name_formatter: a method used to format the keys in the + returned dictionary. By default, + attribute.name will be used. + :param wait_for_idrac: indicates whether or not to wait for the + iDRAC to be ready to accept commands before issuing + the command + :param by_name: Controls whether returned dictionary uses RAID + attribute name or instance_id as key. + :returns: a dictionary containing: + - The is_commit_required key with a boolean value indicating + whether a config job must be created for the values to be + applied. + - The is_reboot_required key with a RebootRequired enumerated + value indicating whether the server must be rebooted for the + values to be applied. Possible values are true and false. + :raises: WSManRequestFailure on request failures + :raises: WSManInvalidResponse when receiving invalid response + :raises: DRACOperationFailed on new settings with invalid values or + attempting to set read-only settings or when an error is reported + back by the iDRAC interface + :raises: DRACUnexpectedReturnValue on return value mismatch + :raises: InvalidParameterValue on invalid new setting + """ + current_settings = list_settings(client, namespaces, by_name=by_name, + name_formatter=name_formatter, + wait_for_idrac=wait_for_idrac) + + unknown_keys = set(new_settings) - set(current_settings) + if unknown_keys: + msg = ('Unknown %(settings_type)s attributes found: %(unknown_keys)r' % + {'settings_type': settings_type, '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: + # There are RAID settings that can have multiple values, + # however these are all read-only attributes. + # Filter out all read-only attributes first so that we exclude + # these settings from further consideration + current_setting_value = current_settings[attr].current_value + if type(current_setting_value) is list: + current_setting_value = current_setting_value[0] + + unchanged_attribute = str(new_settings[attr]) == str( + current_setting_value) + + # check if read-only attribute is unchanged + if current_settings[attr].read_only and not unchanged_attribute: + read_only_keys.append(attr) + + if unchanged_attribute: + unchanged_attribs.append(attr) + else: + validation_msg = current_settings[attr].validate( + new_settings[attr]) + if not validation_msg: + attrib_names.append(attr) + else: + invalid_attribs_msgs.append(validation_msg) + + if unchanged_attribs: + LOG.debug('Ignoring unchanged %(settings_type)s attributes: ' + '%(unchanged_attribs)r' % + {'settings_type': settings_type, + 'unchanged_attribs': unchanged_attribs}) + + if invalid_attribs_msgs or read_only_keys: + if read_only_keys: + read_only_msg = ['Cannot set read-only %(settings_type)s ' + 'attributes: %(read_only_keys)r.' % + {'settings_type': settings_type, + 'read_only_keys': 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 build_return_dict( + None, + resource_uri, + is_commit_required_value=False, + is_reboot_required_value=constants.RebootRequired.false) + + selectors = {'CreationClassName': cim_creation_class_name, + 'Name': cim_name, + 'SystemCreationClassName': 'DCIM_ComputerSystem', + 'SystemName': 'DCIM:ComputerSystem'} + + properties = {'Target': target, + 'AttributeValue': [new_settings[attr] for attr + in attrib_names]} + # To set RAID settings, above we fetched list raid settings using + # instance_id to retrieve attribute values. When we pass instance_id in + # setattribute method for setting any new RAID settings, wsman raises + # an error. So another approach to set those settings is to list raid + # settings using instance_id and for settings new settings, pass the + # attribute names in list to SetAttributes method along with the target. + # That's the reason, we need to handle RAID specific settings like below + if settings_type == 'RAID': + properties['AttributeName'] = [current_settings[attr].name for + attr in attrib_names] + else: + properties['AttributeName'] = attrib_names + doc = client.invoke(resource_uri, 'SetAttributes', + selectors, properties, + wait_for_idrac=wait_for_idrac) + + return build_return_dict(doc, resource_uri) diff --git a/dracclient/wsman.py b/dracclient/wsman.py index 737df72..55cf548 100644 --- a/dracclient/wsman.py +++ b/dracclient/wsman.py @@ -12,12 +12,15 @@ # under the License. import logging +import re +import six +import time import uuid from lxml import etree as ElementTree -import requests import requests.exceptions +from dracclient import constants from dracclient import exceptions LOG = logging.getLogger(__name__) @@ -41,13 +44,31 @@ class Client(object): """Simple client for talking over WSMan protocol.""" def __init__(self, host, username, password, port=443, path='/wsman', - protocol='https'): + protocol='https', + ssl_retries=constants.DEFAULT_WSMAN_SSL_ERROR_RETRIES, + ssl_retry_delay=( + constants.DEFAULT_WSMAN_SSL_ERROR_RETRY_DELAY_SEC)): + """Creates client object + + :param host: hostname or IP of the DRAC interface + :param username: username for accessing the DRAC interface + :param password: password for accessing the DRAC interface + :param port: port for accessing the DRAC interface + :param path: path for accessing the DRAC interface + :param protocol: protocol for accessing the DRAC interface + :param ssl_retries: number of resends to attempt on SSL failures + :param ssl_retry_delay: number of seconds to wait between + retries on SSL failures + """ + self.host = host self.username = username self.password = password self.port = port self.path = path self.protocol = protocol + self.ssl_retries = ssl_retries + self.ssl_retry_delay = ssl_retry_delay self.endpoint = ('%(protocol)s://%(host)s:%(port)s%(path)s' % { 'protocol': self.protocol, 'host': self.host, @@ -58,16 +79,52 @@ def _do_request(self, payload): payload = payload.build() LOG.debug('Sending request to %(endpoint)s: %(payload)s', {'endpoint': self.endpoint, 'payload': payload}) - try: - resp = requests.post( - self.endpoint, - auth=requests.auth.HTTPBasicAuth(self.username, self.password), - data=payload, - # TODO(ifarkas): enable cert verification - verify=False) - except requests.exceptions.RequestException: - LOG.exception('Request failed') - raise exceptions.WSManRequestFailure() + + num_tries = 1 + while num_tries <= self.ssl_retries: + try: + resp = requests.post( + self.endpoint, + auth=requests.auth.HTTPBasicAuth(self.username, + self.password), + data=payload, + # TODO(ifarkas): enable cert verification + verify=False) + break + except (requests.exceptions.ConnectionError, + requests.exceptions.SSLError) as ex: + + error_msg = "A {error_type} error occurred while " \ + " communicating with {host}, attempt {num_tries} of " \ + "{retries}".format( + error_type=type(ex).__name__, + host=self.host, + num_tries=num_tries, + retries=self.ssl_retries) + + if num_tries == self.ssl_retries: + LOG.error(error_msg) + raise exceptions.WSManRequestFailure( + "A {error_type} error occurred while communicating " + "with {host}: {error}".format( + error_type=type(ex).__name__, + host=self.host, + error=ex)) + else: + LOG.warning(error_msg) + + num_tries += 1 + if self.ssl_retry_delay > 0 and num_tries <= self.ssl_retries: + time.sleep(self.ssl_retry_delay) + + except requests.exceptions.RequestException as ex: + error_msg = "A {error_type} error occurred while " \ + "communicating with {host}: {error}".format( + error_type=type(ex).__name__, + host=self.host, + error=ex) + LOG.error(error_msg) + raise exceptions.WSManRequestFailure(error_msg) LOG.debug('Received response from %(endpoint)s: %(payload)s', {'endpoint': self.endpoint, 'payload': resp.content}) @@ -102,24 +159,36 @@ def enumerate(self, resource_uri, optimization=True, max_elems=100, filter_query, filter_dialect) resp = self._do_request(payload) - resp_xml = ElementTree.fromstring(resp.content) + try: + resp_xml = ElementTree.fromstring(resp.content) + except ElementTree.XMLSyntaxError: + LOG.warning('Received invalid content from iDRAC. Filtering out ' + 'unprintable characters: ' + repr(resp.content)) + + # Filter out everything except for printable ASCII characters and + # tab + resp_xml = ElementTree.fromstring(re.sub(six.b('[^\x20-\x7e\t]'), + six.b(''), + resp.content)) if auto_pull: - find_items_query = './/{%s}Items' % NS_WSMAN_ENUM + # The first response returns "" + find_items_wsman_query = './/{%s}Items' % NS_WSMAN + + # Successive pulls return "" + find_items_enum_query = './/{%s}Items' % NS_WSMAN_ENUM + full_resp_xml = resp_xml + items_xml = full_resp_xml.find(find_items_wsman_query) context = self._enum_context(full_resp_xml) while context is not None: resp_xml = self.pull(resource_uri, context, max_elems) context = self._enum_context(resp_xml) - items_xml = full_resp_xml.find(find_items_query) - if items_xml is not None: - # merge enumeration items - for item in resp_xml.find(find_items_query): - items_xml.append(item) - else: - full_resp_xml = resp_xml + # Merge in next batch of enumeration items + for item in resp_xml.find(find_items_enum_query): + items_xml.append(item) # remove enumeration context because items are already merged enum_context_elem = full_resp_xml.find('.//{%s}EnumerationContext' diff --git a/setup.cfg b/setup.cfg index 1b0414d..94d0507 100644 --- a/setup.cfg +++ b/setup.cfg @@ -3,7 +3,7 @@ name = python-dracclient summary = Library for managing machines with Dell iDRAC cards description-file = README.rst maintainer = DracClient Team -maintainer_email = openstack-dev@lists.openstack.org +author-email = openstack-discuss@lists.openstack.org home-page = https://launchpad.net/python-dracclient license = Apache-2 classifier = @@ -12,11 +12,10 @@ classifier = License :: OSI Approved :: Apache Software License Operating System :: POSIX Programming Language :: Python - Programming Language :: Python :: 2 - Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 - Programming Language :: Python :: 3.4 - Programming Language :: Python :: 3.5 + Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 [files] packages = diff --git a/test-requirements.txt b/test-requirements.txt index 89121f4..d87015c 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -4,8 +4,5 @@ coverage>=3.6 doc8 -hacking>=0.11.0,<0.12 -mock>=2.0 +hacking>=1.1.0,<1.2.0 # Apache-2.0 requests-mock>=1.0 -sphinx>=1.2.1,!=1.3b1,<1.3 -oslosphinx>=2.5.0,!=3.4.0 diff --git a/tox.ini b/tox.ini index 135f431..552504e 100644 --- a/tox.ini +++ b/tox.ini @@ -1,12 +1,15 @@ [tox] -envlist = py35,py34,pep8,py27 +minversion = 3.1.0 +envlist = py38,py36,pep8 +ignore_basepython_conflict=true [testenv] usedevelop = True -install_command = pip install -U -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages} +install_command = pip install -U -c{env:UPPER_CONSTRAINTS_FILE:https://opendev.org/openstack/requirements/raw/branch/master/upper-constraints.txt} {opts} {packages} deps = -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt +basepython = python3 setenv = PYTHONDONTWRITEBYTECODE=1 commands = coverage run --branch --source dracclient --omit "dracclient/tests*" -m unittest discover dracclient.tests @@ -16,13 +19,17 @@ commands = commands = {posargs} [testenv:pep8] -basepython = python2.7 commands = flake8 dracclient doc8 README.rst CONTRIBUTING.rst doc/source [testenv:docs] -commands = python setup.py build_sphinx +deps = + -c{env:UPPER_CONSTRAINTS_FILE:https://opendev.org/openstack/requirements/raw/branch/master/upper-constraints.txt} + -r{toxinidir}/requirements.txt + -r{toxinidir}/doc/requirements.txt +commands = + sphinx-build -b html doc/source doc/build/html [flake8] max-complexity=15 diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml new file mode 100644 index 0000000..cab1fe4 --- /dev/null +++ b/zuul.d/project.yaml @@ -0,0 +1,3 @@ +- project: + templates: + - openstack-python3-victoria-jobs