diff options
Diffstat (limited to 'pyipmi/tools/ipmitool.py')
-rw-r--r-- | pyipmi/tools/ipmitool.py | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/pyipmi/tools/ipmitool.py b/pyipmi/tools/ipmitool.py new file mode 100644 index 0000000..75cb179 --- /dev/null +++ b/pyipmi/tools/ipmitool.py @@ -0,0 +1,111 @@ +# Copyright (c) 2012, Calxeda Inc. +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Calxeda Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +# DAMAGE. + + +"""An implementation of Tool for ipmitool support""" + +import os, subprocess, pexpect +from pyipmi import Tool, InteractiveCommand + +class IpmiTool(Tool): + """Implements interaction with impitool + + Currently only supports one off commands, persistent sessions will come. + """ + + def run(self, command): + """Run a command via ipmitool""" + ipmi_args = self._ipmi_args(command) + + arg_str = 'Running %s' % ' '.join(ipmi_args) + self._log(arg_str) + + if isinstance(command, InteractiveCommand): + command = ipmi_args[0] + args = ipmi_args[1:] + proc = self._start_command(command, args) + return proc + + out, err = self._execute(command, ipmi_args) + return command.parse_results(out, err) + + def _ipmi_args(self, command): + """Return the command line arguments to ipmitool for command""" + if 'IPMITOOL_PATH' in os.environ: + args = [os.environ['IPMITOOL_PATH']] + else: + args = ['ipmitool'] + args.extend(self._config_args) + args.extend(command.ipmitool_args) + return map(str, args) + + @property + def _config_args(self): + """Return the config dependent command line arguments + + This arguments are generated from the BMC's config, not from + a specific command. They will be the same from command to + command. + """ + params_to_args = { + 'hostname' : '-H', + 'password' : '-P', + 'username' : '-U', + 'authtype' : '-A', + 'level' : '-L', + 'port' : '-p', + 'interface' : '-I' + } + + base = [] + bmc_params = self._handle.bmc.params + + for param, val in bmc_params.iteritems(): + arg = params_to_args.get(param) + if arg and val: + base.extend([arg, str(val)]) + + return base + + def _execute(self, command, args): + """Execute an ipmitool command""" + proc = subprocess.Popen(args, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + out, err = proc.communicate() + self._log(out) + self._log(err) + if proc.returncode != 0: + command.handle_command_error(out, err) + return out, err + + def _start_command(self, command, args, timeout=5): + return pexpect.spawn(command, args, timeout=timeout, + logfile=self._handle._log_file) |