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 :param method: name of the method to invoke :param selectors: dictionary of selectors :param properties: dictionary of properties :param expected_return_value: expected return value reported back by 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 :raises: DRACOperationFailed on error reported back by the DRAC interface :raises: DRACUnexpectedReturnValue on return value mismatch """ if wait_for_idrac: self.wait_until_idrac_is_ready() if selectors is None: selectors = {} if properties is None: properties = {} resp = super(WSManClient, self).invoke(resource_uri, method, selectors, properties) 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 list_physical_disks(self): """Returns the list of physical disks :returns: a list of PhysicalDisk objects :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_PhysicalDiskView) 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
def list_jobs(self, only_unfinished=False): """Returns a list of jobs from the job queue :param only_unfinished: indicates whether only unfinished jobs should be returned :returns: a list of Job objects :raises: WSManRequestFailure on request failures :raises: WSManInvalidResponse when receiving invalid response :raises: DRACOperationFailed on error reported back by the DRAC interface """ filter_query = None if only_unfinished: 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"') doc = self.client.enumerate(uris.DCIM_LifecycleJob, filter_query=filter_query) drac_jobs = utils.find_xml(doc, 'DCIM_LifecycleJob', uris.DCIM_LifecycleJob, find_all=True) return [self._parse_drac_job(drac_job) for drac_job in drac_jobs]
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) message_id = utils.find_xml(result, 'MessageID', uris.DCIM_LCService).text return message_id == IDRAC_IS_READY
def parse(cls, bios_attr_xml): """Parses XML and creates BIOSEnumerableAttribute object""" bios_attr = BIOSAttribute.parse(cls.namespace, bios_attr_xml) possible_values = [attr.text for attr in utils.find_xml(bios_attr_xml, 'PossibleValues', cls.namespace, find_all=True)] return cls(bios_attr.name, bios_attr.instance_id, bios_attr.current_value, bios_attr.pending_value, bios_attr.read_only, possible_values)
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 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 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 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 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('.'))))
def list_cpus(self): """Returns the list of CPUs :returns: a list of CPU objects :raises: WSManRequestFailure on request failures :raises: WSManInvalidResponse when receiving invalid response :raises: DRACOperationFailed on error reported back by the DRAC """ doc = self.client.enumerate(uris.DCIM_CPUView) cpus = utils.find_xml(doc, 'DCIM_CPUView', uris.DCIM_CPUView, find_all=True) return [self._parse_cpus(cpu) for cpu in cpus]
def list_memory(self): """Returns the list of installed memory :returns: a list of Memory objects :raises: WSManRequestFailure on request failures :raises: WSManInvalidResponse when receiving invalid response :raises: DRACOperationFailed on error reported back by the DRAC """ doc = self.client.enumerate(uris.DCIM_MemoryView) installed_memory = utils.find_xml(doc, 'DCIM_MemoryView', uris.DCIM_MemoryView, find_all=True) return [self._parse_memory(memory) for memory in installed_memory]
def list_boot_devices(self): """Returns the list of boot devices :returns: a dictionary with the boot modes and the list of associated BootDevice objects, ordered by the pending_assigned_sequence property :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_BootSourceSetting) drac_boot_devices = utils.find_xml(doc, 'DCIM_BootSourceSetting', uris.DCIM_BootSourceSetting, find_all=True) try: boot_devices = [self._parse_drac_boot_device(drac_boot_device) for drac_boot_device in drac_boot_devices] except AttributeError: # DRAC 11g doesn't have the BootSourceType attribute on the # DCIM_BootSourceSetting resource controller_version = ( lifecycle_controller.LifecycleControllerManagement( self.client).get_version()) if controller_version < LC_CONTROLLER_VERSION_12G: boot_devices = [ self._parse_drac_boot_device_11g(drac_boot_device) for drac_boot_device in drac_boot_devices] else: raise # group devices by boot mode boot_devices_per_mode = {device.boot_mode: [] for device in boot_devices} for device in boot_devices: boot_devices_per_mode[device.boot_mode].append(device) # sort the device list by pending assigned seqeuence for mode in boot_devices_per_mode.keys(): boot_devices_per_mode[mode].sort( key=lambda device: device.pending_assigned_sequence) return boot_devices_per_mode
def list_boot_modes(self): """Returns the list of boot modes :returns: list of BootMode objects :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_BootConfigSetting) drac_boot_modes = utils.find_xml(doc, 'DCIM_BootConfigSetting', uris.DCIM_BootConfigSetting, find_all=True) return [self._parse_drac_boot_mode(drac_boot_mode) for drac_boot_mode in drac_boot_modes]
def get_power_state(self): """Returns the current power state of the node :returns: power state of the node, one of 'POWER_ON', 'POWER_OFF' or 'REBOOT' :raises: WSManRequestFailure on request failures :raises: WSManInvalidResponse when receiving invalid response :raises: DRACOperationFailed on error reported back by the DRAC interface """ 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', uris.DCIM_ComputerSystem) return POWER_STATES[enabled_state.text]
def list_nics(self, sort=False): """Returns the list of NICs :returns: a list of NIC objects :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_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 nics
def list_raid_controllers(self): """Returns the list of RAID controllers :returns: a list of RAIDController objects :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_ControllerView) drac_raid_controllers = utils.find_xml(doc, 'DCIM_ControllerView', uris.DCIM_ControllerView, find_all=True) return [ self._parse_drac_raid_controller(controller) for controller in drac_raid_controllers ]
def get_job(self, job_id): """Returns a job from the job queue :param job_id: id of the job :returns: a Job object on successful query, None otherwise :raises: WSManRequestFailure on request failures :raises: WSManInvalidResponse when receiving invalid response :raises: DRACOperationFailed on error reported back by the DRAC interface """ filter_query = ( 'select * from DCIM_LifecycleJob where InstanceID="%s"' % job_id) doc = self.client.enumerate(uris.DCIM_LifecycleJob, filter_query=filter_query) drac_job = utils.find_xml(doc, 'DCIM_LifecycleJob', uris.DCIM_LifecycleJob) if drac_job is not None: return self._parse_drac_job(drac_job)