From 2e54d50d349aafdc189eba2702e5913835cdf88f Mon Sep 17 00:00:00 2001 From: Lorry Tar Creator Date: Thu, 9 May 2013 15:12:28 +0000 Subject: Imported from /home/lorry/working-area/delta_pyipmi-tarball/pyipmi-0.7.1.tar.gz. --- pyipmi/__init__.py | 213 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 pyipmi/__init__.py (limited to 'pyipmi/__init__.py') diff --git a/pyipmi/__init__.py b/pyipmi/__init__.py new file mode 100644 index 0000000..ef6c175 --- /dev/null +++ b/pyipmi/__init__.py @@ -0,0 +1,213 @@ +# 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. + + +"""pyipmi provides IPMI client functionality""" +from __future__ import print_function + +__all__ = ['Handle', 'Tool', 'Command', 'make_bmc', 'IpmiError'] + +class Handle: + """A handle to speak with a BMC + + Handles use a Tool to speak with a BMC. It's basically a session handle + from its user's perspective, although handles may or may not use a single + ipmi session for their duration, depending on their implementation. + + The Handle class itself is concrete, but may become abstract in the future. + """ + + def __init__(self, bmc, tool_class, command_list): + """ + Arguments: + bmc -- A BMC object + tool_class -- the class of the tool to be used for this handle, + for example, IpmiTool. + command_list -- a list of Commands to be made available to this handle. + """ + self.bmc = bmc + self._tool = tool_class(self, command_list) + self._add_command_stubs(command_list) + self._log_file = None + + def _add_command_stubs(self, command_list): + """Adds command methods to an instance of Handle + + Each command in the command_list supplied to init will add a method to + this handle instance. Calling that method causes the command to be issued. + """ + for command in command_list: + self._add_command_stub(command) + + def _add_command_stub(self, command): + """Add a a method for a command""" + def _cmd(*args, **kwargs): + """Call the method of the same name on the tool""" + tool_method = getattr(self._tool, command) + return tool_method(*args, **kwargs) + + setattr(self, command, _cmd) + + def set_log(self, log_file): + """Setup a logger for the handle + + Arguments: + log_file -- a file like object + """ + self._log_file = log_file + + def set_verbose(self, verbose): + """Set verbosity for the handle + + Arguments: + verbose -- true or false + """ + self._verbose = verbose + + def log(self, string): + """Write a string to a log + + The log is flushed after log is written + + Arguments: + string -- the string to log.""" + if len(string) > 0: + if (self._log_file): + print(string, file = self._log_file) + self._log_file.flush() + if (self._verbose): + print(string) + +class Tool(object): + """A tool implements communications with a BMC + + Tool is an abstract class - it needs a 'run' method defined to be useful. + + Tool implementations vary in the way they implement IPMI communications. + The IpmiTool implementation uses high level ipmitool commands executed via + subprocesses. A freeipmi implementation could do the same using freeipmi + commands, or there could be a RawIpmiTool implementation that used IpmiTool + with raw commands. Another possibility is implementing IPMI natively in + python, and having a NativeIpmi Tool implementation for that. + + Tool instances are bound to handle instances - each tool has exactly one + handle. + + Tool instances are created with a list of commands - each command in the + list causes a method (named after the command) to be added to the tool + for executing the command. Commands in the list must implement support + for the tool - each tool has + + Concrete implementations should go in the tools directory. An example + concrete implementation is the ImpiTool class. + """ + def __init__(self, handle, command_list): + """ + Arguments: + handle -- the handle to which this command is bound + command_list -- the list of commands the tool can execute + """ + self._handle = handle + self._add_command_stubs(command_list) + self._command_list = command_list + + def _add_command_stubs(self, command_list): + """Add command methods to this Tool instance + + Just like handles, tools get a method per command in command_list + """ + for command in command_list: + self._add_command_stub(command) + + def _add_command_stub(self, command): + """Add an individual command method""" + def _cmd(*args, **kwargs): + """An individual command method. + + Uses this tool's run method to execute a command in this + tool's special way.""" + inst = self._command_list[command](self, *args, **kwargs) + return self.run(inst) + + setattr(self, command, _cmd) + + def _log(self, string): + """Log a message via this tool's handle""" + self._handle.log(string) + + def run(self, command): + """This should be defined in a subclass of Tool""" + pass + +class Command: + """A Command describes a specific IPMI command""" + def __init__(self, tool, **params): + self._tool = tool + self._params = params + +class InteractiveCommand(Command): + """A dummy class for an interactive command""" + +def make_bmc(bmc_class, logfile = None, verbose = True, **kwargs): + """Returns a bmc object with 'default' settings + + This uses IpmiTool for the tool,the base Handle class, and + the default "ipmi_commands" list of IPMI commands. + + kwargs is combined with those default settings into a single + dict with its contents passed as keyword args when calling + bmc_class. + + Arguments: + bmc_class -- called w/ kwargs as its parameter to get the + object to return. + + Keyword arguments: + logfile -- an optional file object for logging (default none) + """ + + from commands import ipmi_commands + from tools import IpmiTool + bmc_kwargs = { + 'tool_class' : IpmiTool, + 'handle_class' : Handle, + 'command_list' : ipmi_commands + } + + bmc_kwargs.update(kwargs) + bmc_obj = bmc_class(**bmc_kwargs) + bmc_obj.handle.set_log(logfile) + bmc_obj.handle.set_verbose(verbose) + + return bmc_obj + + +class IpmiError(Exception): + """A wrapper for an Ipmi error""" -- cgit v1.2.1