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 != "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 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.current_value, bios_attr.pending_value, bios_attr.read_only, possible_values)
def test_get_wsman_resource_attr(self): doc = etree.fromstring( test_utils.InventoryEnumerations[uris.DCIM_CPUView]['ok']) cpus = utils.find_xml(doc, 'DCIM_CPUView', uris.DCIM_CPUView, find_all=True) val = utils.get_wsman_resource_attr( cpus[0], uris.DCIM_CPUView, 'HyperThreadingEnabled', allow_missing=False) self.assertEqual('1', val)
def invoke(self, resource_uri, method, selectors=None, properties=None, expected_return_value=None): """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. :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 selectors is None: selectors = {} if properties is None: properties = {} 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) return resp
def test_get_wsman_resource_attr_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_wsman_resource_attr, cpus[0], uris.DCIM_CPUView, 'HyperThreadingEnabled', allow_missing=False)
def test_get_wsman_resource_attr_missing_attr(self): expected_message = ("Attribute 'HyperThreadingEnabled' is missing " "from the response") doc = etree.fromstring( test_utils.InventoryEnumerations[ uris.DCIM_CPUView]['missing_flags']) cpus = utils.find_xml(doc, 'DCIM_CPUView', uris.DCIM_CPUView, find_all=True) self.assertRaisesRegexp( exceptions.DRACMissingResponseField, re.escape(expected_message), utils.get_wsman_resource_attr, cpus[0], uris.DCIM_CPUView, 'HyperThreadingEnabled', allow_missing=False)
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 where Name="srv:system"' 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_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 test_get_wsman_resource_attr_missing_attr(self): expected_message = ("Attribute 'HyperThreadingEnabled' is missing " "from the response") doc = etree.fromstring(test_utils.InventoryEnumerations[ uris.DCIM_CPUView]['missing_flags']) cpus = utils.find_xml(doc, 'DCIM_CPUView', uris.DCIM_CPUView, find_all=True) self.assertRaisesRegexp(exceptions.DRACMissingResponseField, re.escape(expected_message), utils.get_wsman_resource_attr, cpus[0], uris.DCIM_CPUView, 'HyperThreadingEnabled', allow_missing=False)
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_wsman_resource_attr_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_wsman_resource_attr, cpus[0], uris.DCIM_CPUView, 'HyperThreadingEnabled', allow_missing=False)
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 list_nics(self): """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) return [self._parse_drac_nic(nic) for nic in drac_nics]
def list_system_inventory(self): """Returns the system inventory :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_SystemView) inventory = utils.find_xml(doc, 'DCIM_SystemView', uris.DCIM_SystemView, find_all=True) return [self._parse_system_inventory(item) for item in inventory]
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 """ filter_query = ('select LifecycleControllerVersion ' 'from DCIM_SystemView') doc = self.client.enumerate(uris.DCIM_SystemView, filter_query=filter_query) lc_version_str = utils.find_xml(doc, 'LifecycleControllerVersion', uris.DCIM_SystemView).text return tuple(map(int, (lc_version_str.split('.'))))
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) return [self._parse_drac_physical_disk(disk) for disk in drac_physical_disks]
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_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_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 list_virtual_disks(self): """Returns the list of virtual disks :returns: a list of VirtualDisk 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_VirtualDiskView) drac_virtual_disks = utils.find_xml(doc, 'DCIM_VirtualDiskView', uris.DCIM_VirtualDiskView, find_all=True) return [self._parse_drac_virtual_disk(disk) for disk in drac_virtual_disks]
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)
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: return self._parse_drac_job(drac_job)
def list_firmware_components(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_SoftwareIdentity) software_components = utils.find_xml(doc, 'DCIM_SoftwareIdentity', uris.DCIM_SoftwareIdentity, find_all=True) return [ self._parse_software_components(component) for component in software_components ]
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)
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)