Source code for cfme.utils.ipmi

import subprocess
from cfme.utils.wait import wait_for


[docs]class IPMI(): """ Utility to access IPMI via CLI. The IPMI utility uses the ``ipmitool`` package to access the remote management card of a server. .. note: ``ipmitool`` is not a standard tool and will need to be installed separately. .. warning These commands do not gracefully shutdown a machine. The immediately remove power to a machine. Use with caution. Args: hostname: The hostname of the remote management console. username: The username for the remote management console. password: The password tied to the username. interface_type: A string giving the ``interface_type`` to pass to the CLI. timeout: The number of seconds to wait before giving up on a command. Returns: A :py:class:`IPMI` instnace. """ def __init__(self, hostname, username, password, interface_type="lan", timeout=30): self.hostname = hostname self.username = username self.password = password self.interface_type = interface_type cmd_args = ['ipmitool'] cmd_args.extend(['-H', self.hostname]) cmd_args.extend(['-U', self.username]) cmd_args.extend(['-P', self.password]) cmd_args.extend(['-I', self.interface_type]) self.cmd_args = cmd_args self.timeout = timeout
[docs] def is_power_on(self): """ Checks if the power is on. Returns: ``True`` if power is on, ``False`` if not. """ command = "chassis power status" output = self._run_command(command) if "Chassis Power is on" in output: return True elif "Chassis Power is off" in output: return False else: raise IPMIException("Unexpected command output: {}".format(output))
[docs] def power_off(self): """ Turns the power off. Returns: ``True`` if power is off, ``False`` if not. """ if not self.is_power_on(): return True else: return self._change_power_state(power_on=False)
[docs] def power_on(self): """ Turns the power on. Returns: ``True`` if power is on, ``False`` if not. """ if self.is_power_on(): return True else: return self._change_power_state(power_on=True)
[docs] def power_reset(self): """ Turns the power off. Returns: ``True`` if power reset initiated, ``False`` if not. """ if not self.is_power_on(): return self.power_on() else: command = "chassis power reset" output = self._run_command(command) if "Reset" in output: return True else: raise Exception("Unexpected command output: {}".format(output))
def _change_power_state(self, power_on=True): """ Changes the power state of a machine. Args: power_on: A boolean. ``True`` to request the power be turned on, ``False`` to turn it off. Returns: ``True`` if operation was successful, ``False`` if not. """ if power_on: command = "chassis power on" else: command = "chassis power off" output = self._run_command(command) if "Chassis Power Control: Up/On" in output and power_on: return True elif "Chassis Power Control: Down/Off" in output and not power_on: return True else: raise Exception("Unexpected command output: {}".format(output)) def _run_command(self, command): """ Builds the command arguments from the command string. Args: command: An IPMI command to be passed to the CLI as a string. As an example, "chassis power on". Returns: The string output from the command's stdout. """ command_args = self.cmd_args + command.split(" ") return self._run_ipmi(command_args) def _run_ipmi(self, command_args): """ Runs the actual IPMI command Args: command_args: A list of command arguments to be send to ``ipmitool``. Returns: The string output from the command's stdout. Raises: IPMIException: If the return code is non zero. """ proc = subprocess.Popen(command_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) wait_for(proc.poll, fail_condition=None, num_sec=self.timeout) if proc.returncode == 0: return proc.stdout.read() else: raise IPMIException("Unexpected failure: {}".format(proc.stderr.read()))
[docs]class IPMIException(Exception): """ Raised during :py:meth:`_run_ipmi` if the error code is non zero. """ pass