ceef78a938
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
265 lines
11 KiB
Python
265 lines
11 KiB
Python
#
|
|
# 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 import constants
|
|
from dracclient.resources import uris
|
|
from dracclient import utils
|
|
|
|
|
|
class LifecycleControllerManagement(object):
|
|
|
|
def __init__(self, client):
|
|
"""Creates LifecycleControllerManagement object
|
|
|
|
:param client: an instance of WSManClient
|
|
"""
|
|
self.client = client
|
|
|
|
def get_version(self):
|
|
"""Returns the Lifecycle controller version
|
|
|
|
:returns: Lifecycle controller version as a tuple of integers
|
|
:raises: WSManRequestFailure on request failures
|
|
:raises: WSManInvalidResponse when receiving invalid response
|
|
:raises: DRACOperationFailed on error reported back by the DRAC
|
|
interface
|
|
"""
|
|
|
|
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)
|