Take Lifecycle Controller out of recovery mode
This patch is to check if a node is in recovery mode and take it out of recovery mode by setting LifecycleControllerState attribute value to 'Enabled'. Modified list_lifecycle_settings() method to use utils.list_settings() for retrieving lifecycle settings. Change-Id: I4287f317b2413b70cd00fd4cf8aa69bff6ae5e2f
This commit is contained in:
parent
bcce3bdc6b
commit
ceef78a938
@ -383,9 +383,12 @@ class DRACClient(object):
|
|||||||
cim_name='DCIM:iDRACCardService',
|
cim_name='DCIM:iDRACCardService',
|
||||||
target=idrac_fqdd)
|
target=idrac_fqdd)
|
||||||
|
|
||||||
def list_lifecycle_settings(self):
|
def list_lifecycle_settings(self, by_name=False):
|
||||||
"""List the Lifecycle Controller configuration settings
|
"""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
|
:returns: a dictionary with the Lifecycle Controller settings using its
|
||||||
InstanceID as the key. The attributes are either
|
InstanceID as the key. The attributes are either
|
||||||
LCEnumerableAttribute or LCStringAttribute objects.
|
LCEnumerableAttribute or LCStringAttribute objects.
|
||||||
@ -394,7 +397,49 @@ class DRACClient(object):
|
|||||||
:raises: DRACOperationFailed on error reported back by the DRAC
|
:raises: DRACOperationFailed on error reported back by the DRAC
|
||||||
interface
|
interface
|
||||||
"""
|
"""
|
||||||
return self._lifecycle_cfg.list_lifecycle_settings()
|
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):
|
def list_system_settings(self):
|
||||||
"""List the System configuration settings
|
"""List the System configuration settings
|
||||||
@ -464,7 +509,9 @@ class DRACClient(object):
|
|||||||
cim_system_name='DCIM:ComputerSystem',
|
cim_system_name='DCIM:ComputerSystem',
|
||||||
reboot=False,
|
reboot=False,
|
||||||
start_time='TIME_NOW',
|
start_time='TIME_NOW',
|
||||||
realtime=False):
|
realtime=False,
|
||||||
|
wait_for_idrac=True,
|
||||||
|
method_name='CreateTargetedConfigJob'):
|
||||||
"""Creates a configuration job.
|
"""Creates a configuration job.
|
||||||
|
|
||||||
In CIM (Common Information Model), weak association is used to name an
|
In CIM (Common Information Model), weak association is used to name an
|
||||||
@ -490,6 +537,10 @@ class DRACClient(object):
|
|||||||
schedule_job_execution is called
|
schedule_job_execution is called
|
||||||
:param realtime: Indicates if reatime mode should be used.
|
:param realtime: Indicates if reatime mode should be used.
|
||||||
Valid values are True and False.
|
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
|
:returns: id of the created job
|
||||||
:raises: WSManRequestFailure on request failures
|
:raises: WSManRequestFailure on request failures
|
||||||
:raises: WSManInvalidResponse when receiving invalid response
|
:raises: WSManInvalidResponse when receiving invalid response
|
||||||
@ -507,7 +558,9 @@ class DRACClient(object):
|
|||||||
cim_system_name=cim_system_name,
|
cim_system_name=cim_system_name,
|
||||||
reboot=reboot,
|
reboot=reboot,
|
||||||
start_time=start_time,
|
start_time=start_time,
|
||||||
realtime=realtime)
|
realtime=realtime,
|
||||||
|
wait_for_idrac=wait_for_idrac,
|
||||||
|
method_name=method_name)
|
||||||
|
|
||||||
def create_nic_config_job(
|
def create_nic_config_job(
|
||||||
self,
|
self,
|
||||||
@ -646,6 +699,37 @@ class DRACClient(object):
|
|||||||
cim_creation_class_name='DCIM_BIOSService',
|
cim_creation_class_name='DCIM_BIOSService',
|
||||||
cim_name='DCIM:BIOSService', target=self.BIOS_DEVICE_FQDD)
|
cim_name='DCIM:BIOSService', target=self.BIOS_DEVICE_FQDD)
|
||||||
|
|
||||||
|
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):
|
def get_lifecycle_controller_version(self):
|
||||||
"""Returns the Lifecycle controller version
|
"""Returns the Lifecycle controller version
|
||||||
|
|
||||||
|
@ -37,6 +37,9 @@ PRIMARY_STATUS = {
|
|||||||
# binary unit constants
|
# binary unit constants
|
||||||
UNITS_KI = 2 ** 10
|
UNITS_KI = 2 ** 10
|
||||||
|
|
||||||
|
# Lifecycle Controller status constant
|
||||||
|
LC_IN_RECOVERY = '4'
|
||||||
|
|
||||||
|
|
||||||
# Reboot required indicator
|
# Reboot required indicator
|
||||||
# Note: When the iDRAC returns optional for this value, this indicates that
|
# Note: When the iDRAC returns optional for this value, this indicates that
|
||||||
|
@ -102,7 +102,9 @@ class JobManagement(object):
|
|||||||
cim_system_name='DCIM:ComputerSystem',
|
cim_system_name='DCIM:ComputerSystem',
|
||||||
reboot=False,
|
reboot=False,
|
||||||
start_time='TIME_NOW',
|
start_time='TIME_NOW',
|
||||||
realtime=False):
|
realtime=False,
|
||||||
|
wait_for_idrac=True,
|
||||||
|
method_name='CreateTargetedConfigJob'):
|
||||||
"""Creates a config job
|
"""Creates a config job
|
||||||
|
|
||||||
In CIM (Common Information Model), weak association is used to name an
|
In CIM (Common Information Model), weak association is used to name an
|
||||||
@ -129,6 +131,10 @@ class JobManagement(object):
|
|||||||
job id.
|
job id.
|
||||||
:param realtime: Indicates if reatime mode should be used.
|
:param realtime: Indicates if reatime mode should be used.
|
||||||
Valid values are True and False. Default value is False.
|
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
|
:returns: id of the created job
|
||||||
:raises: WSManRequestFailure on request failures
|
:raises: WSManRequestFailure on request failures
|
||||||
:raises: WSManInvalidResponse when receiving invalid response
|
:raises: WSManInvalidResponse when receiving invalid response
|
||||||
@ -153,10 +159,10 @@ class JobManagement(object):
|
|||||||
if start_time is not None:
|
if start_time is not None:
|
||||||
properties['ScheduledStartTime'] = start_time
|
properties['ScheduledStartTime'] = start_time
|
||||||
|
|
||||||
doc = self.client.invoke(resource_uri, 'CreateTargetedConfigJob',
|
doc = self.client.invoke(resource_uri, method_name,
|
||||||
selectors, properties,
|
selectors, properties,
|
||||||
expected_return_value=utils.RET_CREATED)
|
expected_return_value=utils.RET_CREATED,
|
||||||
|
wait_for_idrac=wait_for_idrac)
|
||||||
return self._get_job_id(doc)
|
return self._get_job_id(doc)
|
||||||
|
|
||||||
def create_reboot_job(
|
def create_reboot_job(
|
||||||
|
@ -11,9 +11,9 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from dracclient import constants
|
||||||
from dracclient.resources import uris
|
from dracclient.resources import uris
|
||||||
from dracclient import utils
|
from dracclient import utils
|
||||||
from dracclient import wsman
|
|
||||||
|
|
||||||
|
|
||||||
class LifecycleControllerManagement(object):
|
class LifecycleControllerManagement(object):
|
||||||
@ -42,47 +42,6 @@ class LifecycleControllerManagement(object):
|
|||||||
return tuple(map(int, (lc_version_str.split('.'))))
|
return tuple(map(int, (lc_version_str.split('.'))))
|
||||||
|
|
||||||
|
|
||||||
class LCConfiguration(object):
|
|
||||||
|
|
||||||
def __init__(self, client):
|
|
||||||
"""Creates LifecycleControllerManagement object
|
|
||||||
|
|
||||||
:param client: an instance of WSManClient
|
|
||||||
"""
|
|
||||||
self.client = client
|
|
||||||
|
|
||||||
def list_lifecycle_settings(self):
|
|
||||||
"""List the LC configuration settings
|
|
||||||
|
|
||||||
: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
|
|
||||||
"""
|
|
||||||
result = {}
|
|
||||||
namespaces = [(uris.DCIM_LCEnumeration, LCEnumerableAttribute),
|
|
||||||
(uris.DCIM_LCString, LCStringAttribute)]
|
|
||||||
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)
|
|
||||||
for item in items:
|
|
||||||
attribute = attr_cls.parse(item)
|
|
||||||
result[attribute.instance_id] = attribute
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
class LCAttribute(object):
|
class LCAttribute(object):
|
||||||
"""Generic LC attribute class"""
|
"""Generic LC attribute class"""
|
||||||
|
|
||||||
@ -161,6 +120,17 @@ class LCEnumerableAttribute(LCAttribute):
|
|||||||
lifecycle_attr.current_value, lifecycle_attr.pending_value,
|
lifecycle_attr.current_value, lifecycle_attr.pending_value,
|
||||||
lifecycle_attr.read_only, possible_values)
|
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):
|
class LCStringAttribute(LCAttribute):
|
||||||
"""String LC attribute class"""
|
"""String LC attribute class"""
|
||||||
@ -199,3 +169,96 @@ class LCStringAttribute(LCAttribute):
|
|||||||
return cls(lifecycle_attr.name, lifecycle_attr.instance_id,
|
return cls(lifecycle_attr.name, lifecycle_attr.instance_id,
|
||||||
lifecycle_attr.current_value, lifecycle_attr.pending_value,
|
lifecycle_attr.current_value, lifecycle_attr.pending_value,
|
||||||
lifecycle_attr.read_only, min_length, max_length)
|
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)
|
||||||
|
@ -353,7 +353,8 @@ class ClientBIOSConfigurationTestCase(base.BaseTest):
|
|||||||
result)
|
result)
|
||||||
mock_invoke.assert_called_once_with(
|
mock_invoke.assert_called_once_with(
|
||||||
mock.ANY, uris.DCIM_BIOSService, 'SetAttributes',
|
mock.ANY, uris.DCIM_BIOSService, 'SetAttributes',
|
||||||
expected_selectors, expected_properties)
|
expected_selectors, expected_properties,
|
||||||
|
wait_for_idrac=True)
|
||||||
|
|
||||||
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_wait_until_idrac_is_ready):
|
||||||
|
@ -214,7 +214,8 @@ class ClientiDRACCardConfigurationTestCase(base.BaseTest):
|
|||||||
result)
|
result)
|
||||||
mock_invoke.assert_called_once_with(
|
mock_invoke.assert_called_once_with(
|
||||||
mock.ANY, uris.DCIM_iDRACCardService, 'SetAttributes',
|
mock.ANY, uris.DCIM_iDRACCardService, 'SetAttributes',
|
||||||
expected_selectors, expected_properties)
|
expected_selectors, expected_properties,
|
||||||
|
wait_for_idrac=True)
|
||||||
|
|
||||||
@mock.patch.object(dracclient.client.WSManClient, 'invoke',
|
@mock.patch.object(dracclient.client.WSManClient, 'invoke',
|
||||||
spec_set=True, autospec=True)
|
spec_set=True, autospec=True)
|
||||||
@ -245,7 +246,8 @@ class ClientiDRACCardConfigurationTestCase(base.BaseTest):
|
|||||||
result)
|
result)
|
||||||
mock_invoke.assert_called_once_with(
|
mock_invoke.assert_called_once_with(
|
||||||
mock.ANY, uris.DCIM_iDRACCardService, 'SetAttributes',
|
mock.ANY, uris.DCIM_iDRACCardService, 'SetAttributes',
|
||||||
expected_selectors, expected_properties)
|
expected_selectors, expected_properties,
|
||||||
|
wait_for_idrac=True)
|
||||||
|
|
||||||
def test_set_idrac_settings_with_too_long_string(
|
def test_set_idrac_settings_with_too_long_string(
|
||||||
self, mock_requests, mock_wait_until_idrac_is_ready):
|
self, mock_requests, mock_wait_until_idrac_is_ready):
|
||||||
|
@ -226,12 +226,43 @@ class ClientJobManagementTestCase(base.BaseTest):
|
|||||||
|
|
||||||
self.assertEqual(mock_requests.call_count, 2)
|
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',
|
@mock.patch.object(dracclient.client.WSManClient, 'invoke',
|
||||||
spec_set=True, autospec=True)
|
spec_set=True, autospec=True)
|
||||||
def test_create_config_job(self, mock_invoke):
|
def test_create_config_job(self, mock_invoke):
|
||||||
cim_creation_class_name = 'DCIM_BIOSService'
|
cim_creation_class_name = 'DCIM_BIOSService'
|
||||||
cim_name = 'DCIM:BIOSService'
|
cim_name = 'DCIM:BIOSService'
|
||||||
target = 'BIOS.Setup.1-1'
|
target = 'BIOS.Setup.1-1'
|
||||||
|
wait_for_idrac = True
|
||||||
expected_selectors = {'CreationClassName': cim_creation_class_name,
|
expected_selectors = {'CreationClassName': cim_creation_class_name,
|
||||||
'Name': cim_name,
|
'Name': cim_name,
|
||||||
'SystemCreationClassName': 'DCIM_ComputerSystem',
|
'SystemCreationClassName': 'DCIM_ComputerSystem',
|
||||||
@ -249,7 +280,8 @@ class ClientJobManagementTestCase(base.BaseTest):
|
|||||||
mock_invoke.assert_called_once_with(
|
mock_invoke.assert_called_once_with(
|
||||||
mock.ANY, uris.DCIM_BIOSService, 'CreateTargetedConfigJob',
|
mock.ANY, uris.DCIM_BIOSService, 'CreateTargetedConfigJob',
|
||||||
expected_selectors, expected_properties,
|
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)
|
self.assertEqual('JID_442507917525', job_id)
|
||||||
|
|
||||||
@mock.patch.object(dracclient.client.WSManClient, 'invoke',
|
@mock.patch.object(dracclient.client.WSManClient, 'invoke',
|
||||||
@ -259,6 +291,7 @@ class ClientJobManagementTestCase(base.BaseTest):
|
|||||||
cim_name = 'DCIM:BIOSService'
|
cim_name = 'DCIM:BIOSService'
|
||||||
target = 'BIOS.Setup.1-1'
|
target = 'BIOS.Setup.1-1'
|
||||||
start_time = "20140924120105"
|
start_time = "20140924120105"
|
||||||
|
wait_for_idrac = True
|
||||||
expected_selectors = {'CreationClassName': cim_creation_class_name,
|
expected_selectors = {'CreationClassName': cim_creation_class_name,
|
||||||
'Name': cim_name,
|
'Name': cim_name,
|
||||||
'SystemCreationClassName': 'DCIM_ComputerSystem',
|
'SystemCreationClassName': 'DCIM_ComputerSystem',
|
||||||
@ -276,7 +309,8 @@ class ClientJobManagementTestCase(base.BaseTest):
|
|||||||
mock_invoke.assert_called_once_with(
|
mock_invoke.assert_called_once_with(
|
||||||
mock.ANY, uris.DCIM_BIOSService, 'CreateTargetedConfigJob',
|
mock.ANY, uris.DCIM_BIOSService, 'CreateTargetedConfigJob',
|
||||||
expected_selectors, expected_properties,
|
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)
|
self.assertEqual('JID_442507917525', job_id)
|
||||||
|
|
||||||
@mock.patch.object(dracclient.client.WSManClient, 'invoke',
|
@mock.patch.object(dracclient.client.WSManClient, 'invoke',
|
||||||
@ -286,6 +320,7 @@ class ClientJobManagementTestCase(base.BaseTest):
|
|||||||
cim_name = 'DCIM:BIOSService'
|
cim_name = 'DCIM:BIOSService'
|
||||||
target = 'BIOS.Setup.1-1'
|
target = 'BIOS.Setup.1-1'
|
||||||
start_time = None
|
start_time = None
|
||||||
|
wait_for_idrac = True
|
||||||
expected_selectors = {'CreationClassName': cim_creation_class_name,
|
expected_selectors = {'CreationClassName': cim_creation_class_name,
|
||||||
'Name': cim_name,
|
'Name': cim_name,
|
||||||
'SystemCreationClassName': 'DCIM_ComputerSystem',
|
'SystemCreationClassName': 'DCIM_ComputerSystem',
|
||||||
@ -302,7 +337,8 @@ class ClientJobManagementTestCase(base.BaseTest):
|
|||||||
mock_invoke.assert_called_once_with(
|
mock_invoke.assert_called_once_with(
|
||||||
mock.ANY, uris.DCIM_BIOSService, 'CreateTargetedConfigJob',
|
mock.ANY, uris.DCIM_BIOSService, 'CreateTargetedConfigJob',
|
||||||
expected_selectors, expected_properties,
|
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)
|
self.assertEqual('JID_442507917525', job_id)
|
||||||
|
|
||||||
@requests_mock.Mocker()
|
@requests_mock.Mocker()
|
||||||
@ -323,12 +359,32 @@ class ClientJobManagementTestCase(base.BaseTest):
|
|||||||
exceptions.DRACOperationFailed, self.drac_client.create_config_job,
|
exceptions.DRACOperationFailed, self.drac_client.create_config_job,
|
||||||
uris.DCIM_BIOSService, cim_creation_class_name, cim_name, target)
|
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,
|
@mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True,
|
||||||
autospec=True)
|
autospec=True)
|
||||||
def test_create_config_job_with_reboot(self, mock_invoke):
|
def test_create_config_job_with_reboot(self, mock_invoke):
|
||||||
cim_creation_class_name = 'DCIM_BIOSService'
|
cim_creation_class_name = 'DCIM_BIOSService'
|
||||||
cim_name = 'DCIM:BIOSService'
|
cim_name = 'DCIM:BIOSService'
|
||||||
target = 'BIOS.Setup.1-1'
|
target = 'BIOS.Setup.1-1'
|
||||||
|
wait_for_idrac = True
|
||||||
expected_selectors = {'CreationClassName': cim_creation_class_name,
|
expected_selectors = {'CreationClassName': cim_creation_class_name,
|
||||||
'Name': cim_name,
|
'Name': cim_name,
|
||||||
'SystemCreationClassName': 'DCIM_ComputerSystem',
|
'SystemCreationClassName': 'DCIM_ComputerSystem',
|
||||||
@ -347,7 +403,8 @@ class ClientJobManagementTestCase(base.BaseTest):
|
|||||||
mock_invoke.assert_called_once_with(
|
mock_invoke.assert_called_once_with(
|
||||||
mock.ANY, uris.DCIM_BIOSService, 'CreateTargetedConfigJob',
|
mock.ANY, uris.DCIM_BIOSService, 'CreateTargetedConfigJob',
|
||||||
expected_selectors, expected_properties,
|
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)
|
self.assertEqual('JID_442507917525', job_id)
|
||||||
|
|
||||||
@mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True,
|
@mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True,
|
||||||
@ -356,6 +413,7 @@ class ClientJobManagementTestCase(base.BaseTest):
|
|||||||
cim_creation_class_name = 'DCIM_BIOSService'
|
cim_creation_class_name = 'DCIM_BIOSService'
|
||||||
cim_name = 'DCIM:BIOSService'
|
cim_name = 'DCIM:BIOSService'
|
||||||
target = 'BIOS.Setup.1-1'
|
target = 'BIOS.Setup.1-1'
|
||||||
|
wait_for_idrac = True
|
||||||
expected_selectors = {'CreationClassName': cim_creation_class_name,
|
expected_selectors = {'CreationClassName': cim_creation_class_name,
|
||||||
'Name': cim_name,
|
'Name': cim_name,
|
||||||
'SystemCreationClassName': 'DCIM_ComputerSystem',
|
'SystemCreationClassName': 'DCIM_ComputerSystem',
|
||||||
@ -374,7 +432,8 @@ class ClientJobManagementTestCase(base.BaseTest):
|
|||||||
mock_invoke.assert_called_once_with(
|
mock_invoke.assert_called_once_with(
|
||||||
mock.ANY, uris.DCIM_BIOSService, 'CreateTargetedConfigJob',
|
mock.ANY, uris.DCIM_BIOSService, 'CreateTargetedConfigJob',
|
||||||
expected_selectors, expected_properties,
|
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)
|
self.assertEqual('JID_442507917525', job_id)
|
||||||
|
|
||||||
@mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True,
|
@mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True,
|
||||||
|
@ -11,14 +11,20 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import lxml.etree
|
||||||
import mock
|
import mock
|
||||||
|
import re
|
||||||
import requests_mock
|
import requests_mock
|
||||||
|
|
||||||
import dracclient.client
|
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 lifecycle_controller
|
||||||
from dracclient.resources import uris
|
from dracclient.resources import uris
|
||||||
from dracclient.tests import base
|
from dracclient.tests import base
|
||||||
from dracclient.tests import utils as test_utils
|
from dracclient.tests import utils as test_utils
|
||||||
|
from dracclient import utils
|
||||||
|
|
||||||
|
|
||||||
class ClientLifecycleControllerManagementTestCase(base.BaseTest):
|
class ClientLifecycleControllerManagementTestCase(base.BaseTest):
|
||||||
@ -40,6 +46,7 @@ class ClientLifecycleControllerManagementTestCase(base.BaseTest):
|
|||||||
self.assertEqual((2, 1, 0), version)
|
self.assertEqual((2, 1, 0), version)
|
||||||
|
|
||||||
|
|
||||||
|
@requests_mock.Mocker()
|
||||||
class ClientLCConfigurationTestCase(base.BaseTest):
|
class ClientLCConfigurationTestCase(base.BaseTest):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -47,12 +54,12 @@ class ClientLCConfigurationTestCase(base.BaseTest):
|
|||||||
self.drac_client = dracclient.client.DRACClient(
|
self.drac_client = dracclient.client.DRACClient(
|
||||||
**test_utils.FAKE_ENDPOINT)
|
**test_utils.FAKE_ENDPOINT)
|
||||||
|
|
||||||
@requests_mock.Mocker()
|
|
||||||
@mock.patch.object(dracclient.client.WSManClient,
|
@mock.patch.object(dracclient.client.WSManClient,
|
||||||
'wait_until_idrac_is_ready', spec_set=True,
|
'wait_until_idrac_is_ready', spec_set=True,
|
||||||
autospec=True)
|
autospec=True)
|
||||||
def test_list_lifecycle_settings(self, mock_requests,
|
def test_list_lifecycle_settings_by_instance_id(
|
||||||
mock_wait_until_idrac_is_ready):
|
self, mock_requests,
|
||||||
|
mock_wait_until_idrac_is_ready):
|
||||||
expected_enum_attr = lifecycle_controller.LCEnumerableAttribute(
|
expected_enum_attr = lifecycle_controller.LCEnumerableAttribute(
|
||||||
name='Lifecycle Controller State',
|
name='Lifecycle Controller State',
|
||||||
instance_id='LifecycleController.Embedded.1#LCAttributes.1#LifecycleControllerState', # noqa
|
instance_id='LifecycleController.Embedded.1#LCAttributes.1#LifecycleControllerState', # noqa
|
||||||
@ -74,7 +81,8 @@ class ClientLCConfigurationTestCase(base.BaseTest):
|
|||||||
{'text': test_utils.LifecycleControllerEnumerations[
|
{'text': test_utils.LifecycleControllerEnumerations[
|
||||||
uris.DCIM_LCString]['ok']}])
|
uris.DCIM_LCString]['ok']}])
|
||||||
|
|
||||||
lifecycle_settings = self.drac_client.list_lifecycle_settings()
|
lifecycle_settings = self.drac_client.list_lifecycle_settings(
|
||||||
|
by_name=False)
|
||||||
|
|
||||||
self.assertEqual(14, len(lifecycle_settings))
|
self.assertEqual(14, len(lifecycle_settings))
|
||||||
# enumerable attribute
|
# enumerable attribute
|
||||||
@ -89,3 +97,203 @@ class ClientLCConfigurationTestCase(base.BaseTest):
|
|||||||
lifecycle_settings)
|
lifecycle_settings)
|
||||||
self.assertEqual(expected_string_attr,
|
self.assertEqual(expected_string_attr,
|
||||||
lifecycle_settings['LifecycleController.Embedded.1#LCAttributes.1#SystemID']) # noqa
|
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')
|
||||||
|
@ -214,7 +214,8 @@ class ClientNICTestCase(base.BaseTest):
|
|||||||
|
|
||||||
mock_invoke.assert_called_once_with(
|
mock_invoke.assert_called_once_with(
|
||||||
mock.ANY, uris.DCIM_NICService, 'SetAttributes',
|
mock.ANY, uris.DCIM_NICService, 'SetAttributes',
|
||||||
expected_selectors, expected_properties)
|
expected_selectors, expected_properties,
|
||||||
|
wait_for_idrac=True)
|
||||||
|
|
||||||
@mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True,
|
@mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True,
|
||||||
autospec=True)
|
autospec=True)
|
||||||
@ -250,7 +251,8 @@ class ClientNICTestCase(base.BaseTest):
|
|||||||
|
|
||||||
mock_invoke.assert_called_once_with(
|
mock_invoke.assert_called_once_with(
|
||||||
mock.ANY, uris.DCIM_NICService, 'SetAttributes',
|
mock.ANY, uris.DCIM_NICService, 'SetAttributes',
|
||||||
expected_selectors, expected_properties)
|
expected_selectors, expected_properties,
|
||||||
|
wait_for_idrac=True)
|
||||||
|
|
||||||
@mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True,
|
@mock.patch.object(dracclient.client.WSManClient, 'invoke', spec_set=True,
|
||||||
autospec=True)
|
autospec=True)
|
||||||
@ -286,7 +288,8 @@ class ClientNICTestCase(base.BaseTest):
|
|||||||
|
|
||||||
mock_invoke.assert_called_once_with(
|
mock_invoke.assert_called_once_with(
|
||||||
mock.ANY, uris.DCIM_NICService, 'SetAttributes',
|
mock.ANY, uris.DCIM_NICService, 'SetAttributes',
|
||||||
expected_selectors, expected_properties)
|
expected_selectors, expected_properties,
|
||||||
|
wait_for_idrac=True)
|
||||||
|
|
||||||
def test_set_nic_settings_error(self, mock_requests,
|
def test_set_nic_settings_error(self, mock_requests,
|
||||||
mock_wait_until_idrac_is_ready):
|
mock_wait_until_idrac_is_ready):
|
||||||
|
@ -133,6 +133,14 @@ JobInvocations = {
|
|||||||
'error': load_wsman_xml(
|
'error': load_wsman_xml(
|
||||||
'bios_service-invoke-delete_pending_configuration-error'),
|
'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'),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +200,15 @@ LifecycleControllerInvocations = {
|
|||||||
'GetRemoteServicesAPIStatus': {
|
'GetRemoteServicesAPIStatus': {
|
||||||
'is_ready': load_wsman_xml('lc_getremoteservicesapistatus_ready'),
|
'is_ready': load_wsman_xml('lc_getremoteservicesapistatus_ready'),
|
||||||
'is_not_ready': load_wsman_xml(
|
'is_not_ready': load_wsman_xml(
|
||||||
'lc_getremoteservicesapistatus_not_ready')
|
'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'),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:n1="http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_LCService">
|
||||||
|
<s:Header>
|
||||||
|
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
|
||||||
|
<wsa:Action>http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_LCService/GetRemoteServicesAPIStatusResponse</wsa:Action>
|
||||||
|
<wsa:RelatesTo>uuid:18745811-2782-4d30-a288-8f001a895215</wsa:RelatesTo>
|
||||||
|
<wsa:MessageID>uuid:9ec203ba-4fc0-1fc0-8094-98d61742a844</wsa:MessageID>
|
||||||
|
</s:Header>
|
||||||
|
<s:Body>
|
||||||
|
<n1:GetRemoteServicesAPIStatus_OUTPUT>
|
||||||
|
<n1:LCStatus>4</n1:LCStatus>
|
||||||
|
<n1:Message>Lifecycle Controller Remote Services is not ready.</n1:Message>
|
||||||
|
<n1:MessageID>LC060</n1:MessageID>
|
||||||
|
<n1:RTStatus>0</n1:RTStatus>
|
||||||
|
<n1:ReturnValue>0</n1:ReturnValue>
|
||||||
|
<n1:ServerStatus>7</n1:ServerStatus>
|
||||||
|
<n1:Status>1</n1:Status>
|
||||||
|
</n1:GetRemoteServicesAPIStatus_OUTPUT>
|
||||||
|
</s:Body>
|
||||||
|
</s:Envelope>
|
@ -0,0 +1,17 @@
|
|||||||
|
<s:Envelope xmlns:n1="http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_LCService"
|
||||||
|
xmlns:s="http://www.w3.org/2003/05/soap-envelope"
|
||||||
|
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
|
||||||
|
<s:Header>
|
||||||
|
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
|
||||||
|
<wsa:Action>http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_LCService/CreateConfigJobResponse</wsa:Action>
|
||||||
|
<wsa:RelatesTo>uuid:80cf5e1b-b109-4ef5-87c8-5b03ce6ba117</wsa:RelatesTo>
|
||||||
|
<wsa:MessageID>uuid:e57fa514-2189-1189-8ec1-a36fc6fe83b0</wsa:MessageID>
|
||||||
|
</s:Header>
|
||||||
|
<s:Body>
|
||||||
|
<n1:CreateConfigJob_OUTPUT>
|
||||||
|
<n1:Message>Configuration job already created, cannot create another config job on specified target until existing job is completed or is cancelled</n1:Message>
|
||||||
|
<n1:MessageID>LC007</n1:MessageID>
|
||||||
|
<n1:ReturnValue>2</n1:ReturnValue>
|
||||||
|
</n1:CreateConfigJob_OUTPUT>
|
||||||
|
</s:Body>
|
||||||
|
</s:Envelope>
|
@ -0,0 +1,28 @@
|
|||||||
|
<s:Envelope xmlns:n1="http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_LCService"
|
||||||
|
xmlns:s="http://www.w3.org/2003/05/soap-envelope"
|
||||||
|
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
|
||||||
|
xmlns:wsman="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">
|
||||||
|
<s:Header>
|
||||||
|
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
|
||||||
|
<wsa:Action>http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_LCService/CreateConfigJobResponse</wsa:Action>
|
||||||
|
<wsa:RelatesTo>uuid:fc2fdae5-6ac2-4338-9b2e-e69b813af829</wsa:RelatesTo>
|
||||||
|
<wsa:MessageID>uuid:d7d89957-2189-1189-8ec0-a36fc6fe83b0</wsa:MessageID>
|
||||||
|
</s:Header>
|
||||||
|
<s:Body>
|
||||||
|
<n1:CreateConfigJob_OUTPUT>
|
||||||
|
<n1:Job>
|
||||||
|
<wsa:EndpointReference>
|
||||||
|
<wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
|
||||||
|
<wsa:ReferenceParameters>
|
||||||
|
<wsman:ResourceURI>http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_LifecycleJob</wsman:ResourceURI>
|
||||||
|
<wsman:SelectorSet>
|
||||||
|
<wsman:Selector Name="InstanceID">JID_442507917525</wsman:Selector>
|
||||||
|
<wsman:Selector Name="__cimnamespace">root/dcim</wsman:Selector>
|
||||||
|
</wsman:SelectorSet>
|
||||||
|
</wsa:ReferenceParameters>
|
||||||
|
</wsa:EndpointReference>
|
||||||
|
</n1:Job>
|
||||||
|
<n1:ReturnValue>4096</n1:ReturnValue>
|
||||||
|
</n1:CreateConfigJob_OUTPUT>
|
||||||
|
</s:Body>
|
||||||
|
</s:Envelope>
|
@ -0,0 +1,21 @@
|
|||||||
|
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
|
||||||
|
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
|
||||||
|
xmlns:n1="http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_LCService">
|
||||||
|
<s:Header>
|
||||||
|
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
|
||||||
|
</wsa:To>
|
||||||
|
<wsa:Action>http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_LCService/SetAttributesResponse
|
||||||
|
</wsa:Action>
|
||||||
|
<wsa:RelatesTo>uuid:bf8adefe-6fc0-456d-b97c-fd8d4aca2d6c
|
||||||
|
</wsa:RelatesTo>
|
||||||
|
<wsa:MessageID>uuid:84abf7b9-7176-1176-a11c-a53ffbd9bed4
|
||||||
|
</wsa:MessageID>
|
||||||
|
</s:Header>
|
||||||
|
<s:Body>
|
||||||
|
<n1:SetAttributes_OUTPUT>
|
||||||
|
<n1:Message>Invalid AttributeName.</n1:Message>
|
||||||
|
<n1:MessageID>LC057</n1:MessageID>
|
||||||
|
<n1:ReturnValue>2</n1:ReturnValue>
|
||||||
|
</n1:SetAttributes_OUTPUT>
|
||||||
|
</s:Body>
|
||||||
|
</s:Envelope>
|
@ -0,0 +1,24 @@
|
|||||||
|
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
|
||||||
|
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
|
||||||
|
xmlns:n1="http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_LCService">
|
||||||
|
<s:Header>
|
||||||
|
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
|
||||||
|
</wsa:To>
|
||||||
|
<wsa:Action>http://schemas.dell.com/wbem/wscim/1/cim-schema/2/DCIM_LCService/SetAttributesResponse
|
||||||
|
</wsa:Action>
|
||||||
|
<wsa:RelatesTo>uuid:bf8adefe-6fc0-456d-b97c-fd8d4aca2d6c
|
||||||
|
</wsa:RelatesTo>
|
||||||
|
<wsa:MessageID>uuid:84abf7b9-7176-1176-a11c-a53ffbd9bed4
|
||||||
|
</wsa:MessageID>
|
||||||
|
</s:Header>
|
||||||
|
<s:Body>
|
||||||
|
<n1:SetAttributes_OUTPUT>
|
||||||
|
<n1:MessageID>LC001</n1:MessageID>
|
||||||
|
<n1:Message>The command was successful</n1:Message>
|
||||||
|
<n1:ReturnValue>0</n1:ReturnValue>
|
||||||
|
<n1:RebootRequired>No</n1:RebootRequired>
|
||||||
|
<n1:SetResult>Set PendingValue</n1:SetResult>
|
||||||
|
</n1:SetAttributes_OUTPUT>
|
||||||
|
</s:Body>
|
||||||
|
</s:Envelope>
|
||||||
|
|
@ -233,7 +233,7 @@ def validate_integer_value(value, attr_name, error_msgs):
|
|||||||
|
|
||||||
|
|
||||||
def list_settings(client, namespaces, by_name=True, fqdd_filter=None,
|
def list_settings(client, namespaces, by_name=True, fqdd_filter=None,
|
||||||
name_formatter=None):
|
name_formatter=None, wait_for_idrac=True):
|
||||||
"""List the configuration settings
|
"""List the configuration settings
|
||||||
|
|
||||||
:param client: an instance of WSManClient.
|
:param client: an instance of WSManClient.
|
||||||
@ -245,6 +245,9 @@ def list_settings(client, namespaces, by_name=True, fqdd_filter=None,
|
|||||||
:param name_formatter: a method used to format the keys in the
|
:param name_formatter: a method used to format the keys in the
|
||||||
returned dictionary. By default,
|
returned dictionary. By default,
|
||||||
attribute.name will be used.
|
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
|
:returns: a dictionary with the settings using name or instance_id as
|
||||||
the key.
|
the key.
|
||||||
:raises: WSManRequestFailure on request failures
|
:raises: WSManRequestFailure on request failures
|
||||||
@ -256,7 +259,7 @@ def list_settings(client, namespaces, by_name=True, fqdd_filter=None,
|
|||||||
result = {}
|
result = {}
|
||||||
for (namespace, attr_cls) in namespaces:
|
for (namespace, attr_cls) in namespaces:
|
||||||
attribs = _get_config(client, namespace, attr_cls, by_name,
|
attribs = _get_config(client, namespace, attr_cls, by_name,
|
||||||
fqdd_filter, name_formatter)
|
fqdd_filter, name_formatter, wait_for_idrac)
|
||||||
if not set(result).isdisjoint(set(attribs)):
|
if not set(result).isdisjoint(set(attribs)):
|
||||||
raise exceptions.DRACOperationFailed(
|
raise exceptions.DRACOperationFailed(
|
||||||
drac_messages=('Colliding attributes %r' % (
|
drac_messages=('Colliding attributes %r' % (
|
||||||
@ -266,10 +269,10 @@ def list_settings(client, namespaces, by_name=True, fqdd_filter=None,
|
|||||||
|
|
||||||
|
|
||||||
def _get_config(client, resource, attr_cls, by_name, fqdd_filter,
|
def _get_config(client, resource, attr_cls, by_name, fqdd_filter,
|
||||||
name_formatter):
|
name_formatter, wait_for_idrac):
|
||||||
result = {}
|
result = {}
|
||||||
|
|
||||||
doc = client.enumerate(resource)
|
doc = client.enumerate(resource, wait_for_idrac=wait_for_idrac)
|
||||||
items = doc.find('.//{%s}Items' % wsman.NS_WSMAN)
|
items = doc.find('.//{%s}Items' % wsman.NS_WSMAN)
|
||||||
|
|
||||||
for item in items:
|
for item in items:
|
||||||
@ -297,7 +300,8 @@ def set_settings(settings_type,
|
|||||||
cim_creation_class_name,
|
cim_creation_class_name,
|
||||||
cim_name,
|
cim_name,
|
||||||
target,
|
target,
|
||||||
name_formatter=None):
|
name_formatter=None,
|
||||||
|
wait_for_idrac=True):
|
||||||
"""Generically handles setting various types of settings on the iDRAC
|
"""Generically handles setting various types of settings on the iDRAC
|
||||||
|
|
||||||
This method pulls the current list of settings from the iDRAC then compares
|
This method pulls the current list of settings from the iDRAC then compares
|
||||||
@ -318,6 +322,9 @@ def set_settings(settings_type,
|
|||||||
:param name_formatter: a method used to format the keys in the
|
:param name_formatter: a method used to format the keys in the
|
||||||
returned dictionary. By default,
|
returned dictionary. By default,
|
||||||
attribute.name will be used.
|
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 containing:
|
:returns: a dictionary containing:
|
||||||
- The is_commit_required key with a boolean value indicating
|
- The is_commit_required key with a boolean value indicating
|
||||||
whether a config job must be created for the values to be
|
whether a config job must be created for the values to be
|
||||||
@ -335,12 +342,15 @@ def set_settings(settings_type,
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
current_settings = list_settings(client, namespaces, by_name=True,
|
current_settings = list_settings(client, namespaces, by_name=True,
|
||||||
name_formatter=name_formatter)
|
name_formatter=name_formatter,
|
||||||
|
wait_for_idrac=wait_for_idrac)
|
||||||
|
|
||||||
unknown_keys = set(new_settings) - set(current_settings)
|
unknown_keys = set(new_settings) - set(current_settings)
|
||||||
if unknown_keys:
|
if unknown_keys:
|
||||||
msg = ('Unknown %(settings_type)s attributes found: %(unknown_keys)r' %
|
msg = ('Unknown %(settings_type)s attributes found: '
|
||||||
{'settings_type': settings_type, 'unknown_keys': unknown_keys})
|
'%(unknown_keys)r' %
|
||||||
|
{'settings_type': settings_type,
|
||||||
|
'unknown_keys': unknown_keys})
|
||||||
raise exceptions.InvalidParameterValue(reason=msg)
|
raise exceptions.InvalidParameterValue(reason=msg)
|
||||||
|
|
||||||
read_only_keys = []
|
read_only_keys = []
|
||||||
@ -393,11 +403,14 @@ def set_settings(settings_type,
|
|||||||
'Name': cim_name,
|
'Name': cim_name,
|
||||||
'SystemCreationClassName': 'DCIM_ComputerSystem',
|
'SystemCreationClassName': 'DCIM_ComputerSystem',
|
||||||
'SystemName': 'DCIM:ComputerSystem'}
|
'SystemName': 'DCIM:ComputerSystem'}
|
||||||
|
|
||||||
properties = {'Target': target,
|
properties = {'Target': target,
|
||||||
'AttributeName': attrib_names,
|
'AttributeName': attrib_names,
|
||||||
'AttributeValue': [new_settings[attr] for attr
|
'AttributeValue': [new_settings[attr] for attr
|
||||||
in attrib_names]}
|
in attrib_names]}
|
||||||
|
|
||||||
doc = client.invoke(resource_uri, 'SetAttributes',
|
doc = client.invoke(resource_uri, 'SetAttributes',
|
||||||
selectors, properties)
|
selectors, properties,
|
||||||
|
wait_for_idrac=wait_for_idrac)
|
||||||
|
|
||||||
return build_return_dict(doc, resource_uri)
|
return build_return_dict(doc, resource_uri)
|
||||||
|
Loading…
Reference in New Issue
Block a user