python-ipmi-0.4.2/0000775000372000037200000000000013574451533014646 5ustar travistravis00000000000000python-ipmi-0.4.2/python_ipmi.egg-info/0000775000372000037200000000000013574451533020677 5ustar travistravis00000000000000python-ipmi-0.4.2/python_ipmi.egg-info/PKG-INFO0000664000372000037200000001644313574451533022004 0ustar travistravis00000000000000Metadata-Version: 1.1 Name: python-ipmi Version: 0.4.2 Summary: Pure python IPMI library Home-page: https://github.com/kontron/python-ipmi Author: Michael Walle, Heiko Thiery Author-email: michael.walle@kontron.com, heiko.thiery@kontron.com License: LGPLv2+ Download-URL: https://github.com/kontron/python-ipmi/tarball/0.4.2 Description: Pure Python IPMI Library ======================== |BuildStatus| |PyPiVersion| |Documentation| |PyPiPythonVersions| |Coveralls| |CodeClimate| |Codacy| Features -------- * native RMCP interface * legacy RMCP interface (using ipmitool) * IPMB interface (using the `Total Phase`_ Aardvark) Tested Devices -------------- * Kontron mTCA Carrier Manager * Kontron CompactPCI boards * Pigeon Point Shelf Manager * HPE iLO3/iLO4 Requirements ------------ For IPMB interface a `Total Phase`_ Aardvark is needed. Installation ------------ Using ``pip`` ''''''''''''' The recommended installation method is using `pip `__:: pip install python-ipmi Manual installation ''''''''''''''''''' Download the source distribution package for the library. Extract the the package to a temporary location and install:: python setup.py install Documentation ------------- You can find the most up to date documentation at: http://python-ipmi.rtfd.org Example ------- Below is an example that shows how to setup the interface and the connection using the `ipmitool`_ as backend with both network and serial interfaces. Example with lan interface: .. code:: python import pyipmi import pyipmi.interfaces # Supported interface_types for ipmitool are: 'lan' , 'lanplus', and 'serial-terminal' interface = pyipmi.interfaces.create_interface('ipmitool', interface_type='lan') connection = pyipmi.create_connection(interface) connection.target = pyipmi.Target(0x82) connection.target.set_routing([(0x81,0x20,0),(0x20,0x82,7)]) connection.session.set_session_type_rmcp('10.0.0.1', port=623) connection.session.set_auth_type_user('admin', 'admin') connection.session.establish() connection.get_device_id() ipmitool command: .. code:: shell ipmitool -I lan -H 10.0.0.1 -p 623 -U "admin" -P "admin" -t 0x82 -b 0 -l 0 raw 0x06 0x01 Example with serial interface: .. code:: python import pyipmi import pyipmi.interfaces interface = pyipmi.interfaces.create_interface('ipmitool', interface_type='serial-terminal') connection = pyipmi.create_connection(interface) connection.target = pyipmi.Target(0xb2) # set_session_type_serial(port, baudrate) connection.session.set_session_type_serial('/dev/tty2', 115200) connection.session.establish() connection.get_device_id() ipmitool command: .. code:: shell ipmitool -I serial-terminal -D /dev/tty2:115200 -t 0xb2 -l 0 raw 0x06 0x01 Compatibility ------------- Python 2.7 is currently supported. Python 3.x support is in beta Contributing ------------ Contributions are always welcome. You may send patches directly (eg. ``git send-email``), do a github pull request or just file an issue. * respect the coding style (eg. PEP8), * provide well-formed commit message (see `this blog post `_.) * add a Signed-off-by line (eg. ``git commit -s``) License ------- This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .. _Total Phase: http://www.totalphase.com .. _ipmitool: http://sourceforge.net/projects/ipmitool/ .. |BuildStatus| image:: https://travis-ci.org/kontron/python-ipmi.png?branch=master :target: https://travis-ci.org/kontron/python-ipmi .. |PyPiVersion| image:: https://badge.fury.io/py/python-ipmi.svg :target: http://badge.fury.io/py/python-ipmi .. |Documentation| image:: https://readthedocs.org/projects/python-ipmi/badge/?version=latest :target: https://python-ipmi.readthedocs.io/en/latest/?badge=latest :alt: Documentation Status .. |PyPiPythonVersions| image:: https://img.shields.io/pypi/pyversions/python-ipmi.svg :alt: Python versions :target: http://badge.fury.io/py/python-ipmi .. |CodeClimate| image:: https://codeclimate.com/github/kontron/python-ipmi/badges/gpa.svg :target: http://codeclimate.com/github/kontron/python-ipmi .. |Coveralls| image:: https://coveralls.io/repos/github/kontron/python-ipmi/badge.svg?branch=master :target: https://coveralls.io/github/kontron/python-ipmi?branch=master .. |Codacy| image:: https://api.codacy.com/project/badge/Grade/bdda77c6596b4e9b8508d95805ba34c5 :alt: Codacy Badge :target: https://app.codacy.com/app/hthiery/python-ipmi?utm_source=github.com&utm_medium=referral&utm_content=kontron/python-ipmi&utm_campaign=Badge_Grade_Dashboard Platform: any Classifier: Development Status :: 3 - Alpha Classifier: Environment :: Console Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+) Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Topic :: Software Development :: Libraries :: Python Modules python-ipmi-0.4.2/python_ipmi.egg-info/dependency_links.txt0000664000372000037200000000000113574451533024745 0ustar travistravis00000000000000 python-ipmi-0.4.2/python_ipmi.egg-info/top_level.txt0000664000372000037200000000001513574451533023425 0ustar travistravis00000000000000pyipmi tests python-ipmi-0.4.2/python_ipmi.egg-info/SOURCES.txt0000664000372000037200000000353513574451533022571 0ustar travistravis00000000000000README.rst setup.py pyipmi/__init__.py pyipmi/bmc.py pyipmi/chassis.py pyipmi/constants.py pyipmi/dcmi.py pyipmi/errors.py pyipmi/event.py pyipmi/fields.py pyipmi/fru.py pyipmi/helper.py pyipmi/hpm.py pyipmi/ipmitool.py pyipmi/lan.py pyipmi/logger.py pyipmi/messaging.py pyipmi/picmg.py pyipmi/sdr.py pyipmi/sel.py pyipmi/sensor.py pyipmi/session.py pyipmi/state.py pyipmi/utils.py pyipmi/version.py pyipmi/interfaces/__init__.py pyipmi/interfaces/aardvark.py pyipmi/interfaces/ipmb.py pyipmi/interfaces/ipmitool.py pyipmi/interfaces/mock.py pyipmi/interfaces/rmcp.py pyipmi/msgs/__init__.py pyipmi/msgs/bmc.py pyipmi/msgs/chassis.py pyipmi/msgs/constants.py pyipmi/msgs/dcmi.py pyipmi/msgs/device_messaging.py pyipmi/msgs/event.py pyipmi/msgs/fru.py pyipmi/msgs/hpm.py pyipmi/msgs/lan.py pyipmi/msgs/message.py pyipmi/msgs/picmg.py pyipmi/msgs/registry.py pyipmi/msgs/sdr.py pyipmi/msgs/sel.py pyipmi/msgs/sensor.py pyipmi/msgs/session.py python_ipmi.egg-info/PKG-INFO python_ipmi.egg-info/SOURCES.txt python_ipmi.egg-info/dependency_links.txt python_ipmi.egg-info/entry_points.txt python_ipmi.egg-info/requires.txt python_ipmi.egg-info/top_level.txt tests/__init__.py tests/test_bmc.py tests/test_chassis.py tests/test_errors.py tests/test_fields.py tests/test_fru.py tests/test_helper.py tests/test_hpm.py tests/test_ipmi.py tests/test_picmg.py tests/test_sdr.py tests/test_sel.py tests/test_sensor.py tests/test_utils.py tests/interfaces/__init__.py tests/interfaces/test_aardvark.py tests/interfaces/test_ipmb.py tests/interfaces/test_ipmitool.py tests/interfaces/test_rmcp.py tests/msgs/__init__.py tests/msgs/test_bmc.py tests/msgs/test_chassis.py tests/msgs/test_device_messaging.py tests/msgs/test_event.py tests/msgs/test_fru.py tests/msgs/test_hpm.py tests/msgs/test_message.py tests/msgs/test_picmg.py tests/msgs/test_sdr.py tests/msgs/test_sel.py tests/msgs/test_sensor.pypython-ipmi-0.4.2/python_ipmi.egg-info/requires.txt0000664000372000037200000000002013574451533023267 0ustar travistravis00000000000000markdown future python-ipmi-0.4.2/python_ipmi.egg-info/entry_points.txt0000664000372000037200000000006613574451533024177 0ustar travistravis00000000000000[console_scripts] ipmitool.py = pyipmi.ipmitool:main python-ipmi-0.4.2/PKG-INFO0000664000372000037200000001644313574451533015753 0ustar travistravis00000000000000Metadata-Version: 1.1 Name: python-ipmi Version: 0.4.2 Summary: Pure python IPMI library Home-page: https://github.com/kontron/python-ipmi Author: Michael Walle, Heiko Thiery Author-email: michael.walle@kontron.com, heiko.thiery@kontron.com License: LGPLv2+ Download-URL: https://github.com/kontron/python-ipmi/tarball/0.4.2 Description: Pure Python IPMI Library ======================== |BuildStatus| |PyPiVersion| |Documentation| |PyPiPythonVersions| |Coveralls| |CodeClimate| |Codacy| Features -------- * native RMCP interface * legacy RMCP interface (using ipmitool) * IPMB interface (using the `Total Phase`_ Aardvark) Tested Devices -------------- * Kontron mTCA Carrier Manager * Kontron CompactPCI boards * Pigeon Point Shelf Manager * HPE iLO3/iLO4 Requirements ------------ For IPMB interface a `Total Phase`_ Aardvark is needed. Installation ------------ Using ``pip`` ''''''''''''' The recommended installation method is using `pip `__:: pip install python-ipmi Manual installation ''''''''''''''''''' Download the source distribution package for the library. Extract the the package to a temporary location and install:: python setup.py install Documentation ------------- You can find the most up to date documentation at: http://python-ipmi.rtfd.org Example ------- Below is an example that shows how to setup the interface and the connection using the `ipmitool`_ as backend with both network and serial interfaces. Example with lan interface: .. code:: python import pyipmi import pyipmi.interfaces # Supported interface_types for ipmitool are: 'lan' , 'lanplus', and 'serial-terminal' interface = pyipmi.interfaces.create_interface('ipmitool', interface_type='lan') connection = pyipmi.create_connection(interface) connection.target = pyipmi.Target(0x82) connection.target.set_routing([(0x81,0x20,0),(0x20,0x82,7)]) connection.session.set_session_type_rmcp('10.0.0.1', port=623) connection.session.set_auth_type_user('admin', 'admin') connection.session.establish() connection.get_device_id() ipmitool command: .. code:: shell ipmitool -I lan -H 10.0.0.1 -p 623 -U "admin" -P "admin" -t 0x82 -b 0 -l 0 raw 0x06 0x01 Example with serial interface: .. code:: python import pyipmi import pyipmi.interfaces interface = pyipmi.interfaces.create_interface('ipmitool', interface_type='serial-terminal') connection = pyipmi.create_connection(interface) connection.target = pyipmi.Target(0xb2) # set_session_type_serial(port, baudrate) connection.session.set_session_type_serial('/dev/tty2', 115200) connection.session.establish() connection.get_device_id() ipmitool command: .. code:: shell ipmitool -I serial-terminal -D /dev/tty2:115200 -t 0xb2 -l 0 raw 0x06 0x01 Compatibility ------------- Python 2.7 is currently supported. Python 3.x support is in beta Contributing ------------ Contributions are always welcome. You may send patches directly (eg. ``git send-email``), do a github pull request or just file an issue. * respect the coding style (eg. PEP8), * provide well-formed commit message (see `this blog post `_.) * add a Signed-off-by line (eg. ``git commit -s``) License ------- This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .. _Total Phase: http://www.totalphase.com .. _ipmitool: http://sourceforge.net/projects/ipmitool/ .. |BuildStatus| image:: https://travis-ci.org/kontron/python-ipmi.png?branch=master :target: https://travis-ci.org/kontron/python-ipmi .. |PyPiVersion| image:: https://badge.fury.io/py/python-ipmi.svg :target: http://badge.fury.io/py/python-ipmi .. |Documentation| image:: https://readthedocs.org/projects/python-ipmi/badge/?version=latest :target: https://python-ipmi.readthedocs.io/en/latest/?badge=latest :alt: Documentation Status .. |PyPiPythonVersions| image:: https://img.shields.io/pypi/pyversions/python-ipmi.svg :alt: Python versions :target: http://badge.fury.io/py/python-ipmi .. |CodeClimate| image:: https://codeclimate.com/github/kontron/python-ipmi/badges/gpa.svg :target: http://codeclimate.com/github/kontron/python-ipmi .. |Coveralls| image:: https://coveralls.io/repos/github/kontron/python-ipmi/badge.svg?branch=master :target: https://coveralls.io/github/kontron/python-ipmi?branch=master .. |Codacy| image:: https://api.codacy.com/project/badge/Grade/bdda77c6596b4e9b8508d95805ba34c5 :alt: Codacy Badge :target: https://app.codacy.com/app/hthiery/python-ipmi?utm_source=github.com&utm_medium=referral&utm_content=kontron/python-ipmi&utm_campaign=Badge_Grade_Dashboard Platform: any Classifier: Development Status :: 3 - Alpha Classifier: Environment :: Console Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+) Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Topic :: Software Development :: Libraries :: Python Modules python-ipmi-0.4.2/pyipmi/0000775000372000037200000000000013574451533016155 5ustar travistravis00000000000000python-ipmi-0.4.2/pyipmi/logger.py0000664000372000037200000000205313574451473020011 0ustar travistravis00000000000000# Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import logging def log(): return logging.getLogger('pyipmi') def add_log_handler(handler): log().addHandler(handler) def set_log_level(level): log().setLevel(level) class NullHandler(logging.Handler): def emit(self, record): pass add_log_handler(NullHandler()) python-ipmi-0.4.2/pyipmi/sel.py0000664000372000037200000001544213574451473017323 0ustar travistravis00000000000000 # Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from array import array from .errors import DecodingError from .utils import check_completion_code, ByteBuffer from .msgs import create_request_by_name from .msgs import constants from .event import EVENT_ASSERTION, EVENT_DEASSERTION from .helper import clear_repository_helper from .state import State class Sel(object): def get_sel_entries_count(self): info = SelInfo(self.send_message_with_name('GetSelInfo')) return info.entries def get_sel_reservation_id(self): rsp = self.send_message_with_name('ReserveSel') return rsp.reservation_id def _clear_sel(self, cmd, reservation): rsp = self.send_message_with_name('ClearSel', reservation_id=reservation, cmd=cmd) return rsp.status.erase_in_progress def clear_sel(self, retry=5): clear_repository_helper(self.get_sel_reservation_id, self._clear_sel, retry) def sel_entries(self): """Generator which returns all SEL entries.""" ENTIRE_RECORD = 0xff rsp = self.send_message_with_name('GetSelInfo') if rsp.entries == 0: return reservation_id = self.get_sel_reservation_id() next_record_id = 0 while True: req = create_request_by_name('GetSelEntry') req.reservation_id = reservation_id req.record_id = next_record_id req.offset = 0 self.max_req_len = ENTIRE_RECORD record_data = ByteBuffer() while True: req.length = self.max_req_len if (self.max_req_len != 0xff and (req.offset + req.length) > 16): req.length = 16 - req.offset rsp = self.send_message(req) if rsp.completion_code == constants.CC_CANT_RET_NUM_REQ_BYTES: if self.max_req_len == 0xff: self.max_req_len = 16 else: self.max_req_len -= 1 continue else: check_completion_code(rsp.completion_code) record_data.extend(rsp.record_data) req.offset = len(record_data) if len(record_data) >= 16: break next_record_id = rsp.next_record_id yield SelEntry(record_data) if next_record_id == 0xffff: break def get_sel_entries(self): '''Returns all SEL entries as a list.''' return list(self.sel_entries()) class SelInfo(State): def _from_response(self, rsp): self.version = rsp.version self.entries = rsp.entries self.free_bytes = rsp.free_bytes self.most_recent_addition = rsp.most_recent_addition self.most_recent_erase = rsp.most_recent_erase self.operation_support = [] if rsp.operation_support.get_sel_allocation_info: self.operation_support.append('get_sel_allocation_info') if rsp.operation_support.reserve_sel: self.operation_support.append('reserve_sel') if rsp.operation_support.partial_add_sel_entry: self.operation_support.append('partial_add_sel_entry') if rsp.operation_support.delete_sel: self.operation_support.append('delete_sel') if rsp.operation_support.overflow_flag: self.operation_support.append('overflow_flag') class SelEntry(State): TYPE_SYSTEM_EVENT = 0x02 TYPE_OEM_TIMESTAMPED_RANGE = list(range(0xc0, 0xe0)) TYPE_OEM_NON_TIMESTAMPED_RANGE = list(range(0xe0, 0x100)) def __str__(self): raw = '[%s]' % (' '.join(['0x%02x' % b for b in self.data])) string = [] string.append('SEL Record ID 0x%04x' % self.record_id) string.append(' Raw: %s' % raw) string.append(' Type: %d' % self.type) string.append(' Timestamp: %d' % self.timestamp) string.append(' Generator: %d' % self.generator_id) string.append(' EvM rev: %d' % self.evm_rev) string.append(' Sensor Type: 0x%02x' % self.sensor_type) string.append(' Sensor Number: %d' % self.sensor_number) string.append(' Event Direction: %d' % self.event_direction) string.append(' Event Type: 0x%02x' % self.event_type) string.append(' Event Data: %s' % array('B', self.event_data).tolist()) return "\n".join(string) @staticmethod def type_to_string(entry_type): string = None if entry_type == SelEntry.TYPE_SYSTEM_EVENT: string = 'System Event' elif entry_type in SelEntry.TYPE_OEM_TIMESTAMPED_RANGE: string = 'OEM timestamped (0x%02x)' % entry_type elif entry_type in SelEntry.TYPE_OEM_NON_TIMESTAMPED_RANGE: string = 'OEM non-timestamped (0x%02x)' % entry_type return string def _from_response(self, data): if len(data) != 16: raise DecodingError('Invalid SEL record length (%d)' % len(data)) self.data = data # pop will change data, therefore copy it buffer = ByteBuffer(data) self.record_id = buffer.pop_unsigned_int(2) self.type = buffer.pop_unsigned_int(1) if (self.type != self.TYPE_SYSTEM_EVENT and self.type not in self.TYPE_OEM_TIMESTAMPED_RANGE and self.type not in self.TYPE_OEM_NON_TIMESTAMPED_RANGE): raise DecodingError('Unknown SEL type (0x%02x)' % self.type) self.timestamp = buffer.pop_unsigned_int(4) self.generator_id = buffer.pop_unsigned_int(2) self.evm_rev = buffer.pop_unsigned_int(1) self.sensor_type = buffer.pop_unsigned_int(1) self.sensor_number = buffer.pop_unsigned_int(1) event_desc = buffer.pop_unsigned_int(1) if event_desc & 0x80: self.event_direction = EVENT_DEASSERTION else: self.event_direction = EVENT_ASSERTION self.event_type = event_desc & 0x7f self.event_data = [buffer.pop_unsigned_int(1) for _ in range(3)] python-ipmi-0.4.2/pyipmi/sensor.py0000664000372000037200000001704613574451473020053 0ustar travistravis00000000000000# cOPYRIGht (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from __future__ import absolute_import from .utils import check_completion_code from .msgs import create_request_by_name from .helper import get_sdr_data_helper, get_sdr_chunk_helper from . import sdr # THRESHOLD BASED STATES EVENT_READING_TYPE_CODE_THRESHOLD = 0x01 # DMI-based "Usage States" STATES EVENT_READING_TYPE_CODE_DISCRETE = 0x02 # DIGITAL/DISCRETE EVENT STATES EVENT_READING_TYPE_CODE_STATE = 0x03 EVENT_READING_TYPE_CODE_PREDICTIVE_FAILURE = 0x04 EVENT_READING_TYPE_CODE_LIMIT = 0x05 EVENT_READING_TYPE_CODE_PERFORMANCE = 0x06 # Sensor Types SENSOR_TYPE_TEMPERATURE = 0x01 SENSOR_TYPE_VOLTAGE = 0x02 SENSOR_TYPE_CURRENT = 0x03 SENSOR_TYPE_FAN = 0x04 SENSOR_TYPE_CHASSIS_INTRUSION = 0x05 SENSOR_TYPE_PLATFORM_SECURITY = 0x06 SENSOR_TYPE_PROCESSOR = 0x07 SENSOR_TYPE_POWER_SUPPLY = 0x08 SENSOR_TYPE_POWER_UNIT = 0x09 SENSOR_TYPE_COOLING_DEVICE = 0x0a SENSOR_TYPE_OTHER_UNITS_BASED_SENSOR = 0x0b SENSOR_TYPE_MEMORY = 0x0c SENSOR_TYPE_DRIVE_SLOT = 0x0d SENSOR_TYPE_POST_MEMORY_RESIZE = 0x0e SENSOR_TYPE_SYSTEM_FIRMWARE_PROGRESS = 0x0f SENSOR_TYPE_EVENT_LOGGING_DISABLED = 0x10 SENSOR_TYPE_WATCHDOG_1 = 0x11 SENSOR_TYPE_SYSTEM_EVENT = 0x12 SENSOR_TYPE_CRITICAL_INTERRUPT = 0x13 SENSOR_TYPE_BUTTON = 0x14 SENSOR_TYPE_MODULE_BOARD = 0x15 SENSOR_TYPE_MICROCONTROLLER_COPROCESSOR = 0x16 SENSOR_TYPE_ADD_IN_CARD = 0x17 SENSOR_TYPE_CHASSIS = 0x18 SENSOR_TYPE_CHIP_SET = 0x19 SENSOR_TYPE_OTHER_FRU = 0x1a SENSOR_TYPE_CABLE_INTERCONNECT = 0x1b SENSOR_TYPE_TERMINATOR = 0x1c SENSOR_TYPE_SYSTEM_BOOT_INITIATED = 0x1d SENSOR_TYPE_BOOT_ERROR = 0x1e SENSOR_TYPE_OS_BOOT = 0x1f SENSOR_TYPE_OS_CRITICAL_STOP = 0x20 SENSOR_TYPE_SLOT_CONNECTOR = 0x21 SENSOR_TYPE_SYSTEM_ACPI_POWER_STATE = 0x22 SENSOR_TYPE_WATCHDOG_2 = 0x23 SENSOR_TYPE_PLATFORM_ALERT = 0x24 SENSOR_TYPE_ENTITY_PRESENT = 0x25 SENSOR_TYPE_MONITOR_ASIC_IC = 0x26 SENSOR_TYPE_LAN = 0x27 SENSOR_TYPE_MANGEMENT_SUBSYSTEM_HEALTH = 0x28 SENSOR_TYPE_BATTERY = 0x29 SENSOR_TYPE_SESSION_AUDIT = 0x2a SENSOR_TYPE_VERSION_CHANGE = 0x2b SENSOR_TYPE_FRU_STATE = 0x2c SENSOR_TYPE_FRU_HOT_SWAP = 0xf0 SENSOR_TYPE_IPMB_PHYSICAL_LINK = 0xf1 SENSOR_TYPE_MODULE_HOT_SWAP = 0xf2 SENSOR_TYPE_POWER_CHANNEL_NOTIFICATION = 0xf3 SENSOR_TYPE_TELCO_ALARM_INPUT = 0xf4 SENSOR_TYPE_OEM_KONTRON_FRU_INFORMATION_AGENT = 0xc5 SENSOR_TYPE_OEM_KONTRON_POST_VALUE = 0xc6 SENSOR_TYPE_OEM_KONTRON_FW_UPGRADE = 0xc7 SENSOR_TYPE_OEM_KONTRON_DIAGNOSTIC = 0xc9 SENSOR_TYPE_OEM_KONTRON_SYSTEM_FIRMWARE_UPGRADE = 0xca SENSOR_TYPE_OEM_KONTRON_POWER_DENIED = 0xcd SENSOR_TYPE_OEM_KONTRON_RESET = 0xcf class Sensor(object): def reserve_device_sdr_repository(self): rsp = self.send_message_with_name('ReserveDeviceSdrRepository') return rsp.reservation_id def _get_device_sdr_chunk(self, reservation_id, record_id, offset, length): req = create_request_by_name('GetDeviceSdr') req.reservation_id = reservation_id req.record_id = record_id req.offset = offset req.bytes_to_read = length rsp = get_sdr_chunk_helper(self.send_message, req, self.reserve_device_sdr_repository) return (rsp.next_record_id, rsp.record_data) def get_device_sdr(self, record_id, reservation_id=None): """Collects all data from the sensor device to get the SDR specified by record id. `record_id` the Record ID. `reservation_id=None` can be set. if None the reservation ID will be determined. """ (next_id, record_data) = \ get_sdr_data_helper(self.reserve_device_sdr_repository, self._get_device_sdr_chunk, record_id, reservation_id) return sdr.SdrCommon.from_data(record_data, next_id) def device_sdr_entries(self): """A generator that returns the SDR list. Starting with ID=0x0000 and end when ID=0xffff is returned. """ reservation_id = self.reserve_device_sdr_repository() record_id = 0 while True: record = self.get_device_sdr(record_id, reservation_id) yield record if record.next_id == 0xffff: break record_id = record.next_id def get_device_sdr_list(self, reservation_id=None): """Returns the complete SDR list. """ return list(self.device_sdr_entries()) def rearm_sensor_events(self, sensor_number): """Rearm sensor events for the given sensor number. """ self.send_message_with_name('RearmSensorEvents', sensor_number=sensor_number) def get_sensor_reading(self, sensor_number, lun=0): """Returns the sensor reading at the assertion states for the given sensor number. `sensor_number` Returns a tuple with `raw reading`and `assertion states`. """ rsp = self.send_message_with_name('GetSensorReading', sensor_number=sensor_number, lun=lun) reading = rsp.sensor_reading if rsp.config.initial_update_in_progress: reading = None states = None if rsp.states1 is not None: states = rsp.states1 if rsp.states2 is not None: states |= (rsp.states2 << 8) return (reading, states) def set_sensor_thresholds(self, sensor_number, lun=0, unr=None, ucr=None, unc=None, lnc=None, lcr=None, lnr=None): """Set the sensor thresholds that are not 'None' `sensor_number` `unr` for upper non-recoverable `ucr` for upper critical `unc` for upper non-critical `lnc` for lower non-critical `lcr` for lower critical `lnr` for lower non-recoverable """ req = create_request_by_name('SetSensorThresholds') req.sensor_number = sensor_number req.lun = lun thresholds = dict(unr=unr, ucr=ucr, unc=unc, lnc=lnc, lcr=lcr, lnr=lnr) for key, value in thresholds.items(): if value is not None: setattr(req.set_mask, key, 1) setattr(req.threshold, key, value) rsp = self.send_message(req) check_completion_code(rsp.completion_code) def get_sensor_thresholds(self, sensor_number, lun=0): rsp = self.send_message_with_name('GetSensorThresholds', sensor_number=sensor_number, lun=lun) thresholds = {} threshold_list = ('unr', 'ucr', 'unc', 'lnc', 'lcr', 'lnr') for threshold in threshold_list: if hasattr(rsp.readable_mask, threshold): if getattr(rsp.readable_mask, threshold): thresholds[threshold] = getattr(rsp.threshold, threshold) return thresholds python-ipmi-0.4.2/pyipmi/lan.py0000664000372000037200000000644213574451473017312 0ustar travistravis00000000000000# Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from .msgs import create_request_by_name from .utils import check_completion_code LAN_PARAMETER_SET_IN_PROGRESS = 0 LAN_PARAMETER_AUTHENTICATION_TYPE_SUPPORT = 1 LAN_PARAMETER_AUTHENTICATION_TYPE_ENABLE = 2 LAN_PARAMETER_IP_ADDRESS = 3 LAN_PARAMETER_IP_ADDRESS_SOURCE = 4 LAN_PARAMETER_MAC_ADDRESS = 5 LAN_PARAMETER_SUBNET_MASK = 6 LAN_PARAMETER_IPV4_HEADER_PARAMETERS = 7 LAN_PARAMETER_PRIMARY_RMCP_PORT = 8 LAN_PARAMETER_SECONDARY_RMCP_PORT = 9 LAN_PARAMETER_BMC_GENERATED_ARP_CONTROL = 10 LAN_PARAMETER_GRATUITOUS_ARP_INTERVAL = 11 LAN_PARAMETER_DEFAULT_GATEWAY_ADDRESS = 12 LAN_PARAMETER_DEFAULT_GATEWAY_MAC_ADDRESS = 13 LAN_PARAMETER_BACKUP_GATEWAY_ADDRESS = 14 LAN_PARAMETER_BACKUP_GATEWAY_MAC_ADDRESS = 15 LAN_PARAMETER_COMMUNITY_STRING = 16 LAN_PARAMETER_NUMBER_OF_DESTINATIONS = 17 LAN_PARAMETER_DESTINATION_TYPE = 18 LAN_PARAMETER_DESTINATION_ADDRESSES = 19 # following parameters are introduced with IPMI v2.0/RMCP+ LAN_PARAMETER_802_1Q_VLAN_ID = 20 LAN_PARAMETER_802_1Q_VLAN_PRIORITY = 21 LAN_PARAMETER_RMCP_PLUS_MESSAGING_CIPHER_SUITE_ENTRY_SUPPORT = 22 LAN_PARAMETER_RMCP_PLUS__MESSAGING_CIPHER_SUITE_ENTRIES = 23 LAN_PARAMETER_RMCP_PLUS_MESSAGING_CIPHER_SUITE_PRIVILEGE_LEVES = 24 LAN_PARAMETER_DESTINATION_ADDRESS_VLAN_TAGS = 25 LAN_PARAMETER_IP_ADDRESS_SOURCE_UNSPECIFIED = 0 LAN_PARAMETER_IP_ADDRESS_SOURCE_STATIC = 1 LAN_PARAMETER_IP_ADDRESS_SOURCE_DHCP = 2 LAN_PARAMETER_IP_ADDRESS_SOURCE_BIOS_OR_SYSTEM_SOFTWARE = 3 LAN_PARAMETER_IP_ADDRESS_SOURCE_BMC_OTHER_PROTOCOL = 4 class Lan(object): def get_lan_config_param(self, channel=0, parameter_selector=0, set_selector=0, block_selector=0, revision_only=0): req = create_request_by_name('GetLanConfigurationParameters') req.command.get_parameter_revision_only = revision_only if revision_only is not 1: req.command.channel_number = channel req.parameter_selector = parameter_selector req.set_selector = set_selector req.block_selector = block_selector rsp = self.send_message(req) check_completion_code(rsp.completion_code) return rsp.data def set_lan_config_param(self, channel, parameter_selector, data): req = create_request_by_name('SetLanConfigurationParameters') req.command.channel_number = channel req.parameter_selector = parameter_selector req.data = data rsp = self.send_message(req) check_completion_code(rsp.completion_code) class LanParameter(object): pass python-ipmi-0.4.2/pyipmi/msgs/0000775000372000037200000000000013574451533017126 5ustar travistravis00000000000000python-ipmi-0.4.2/pyipmi/msgs/sel.py0000664000372000037200000001354413574451473020275 0ustar travistravis00000000000000from __future__ import absolute_import # Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from . import constants from . import register_message_class from . import Message from . import ByteArray from . import UnsignedInt from . import Timestamp from . import Bitfield from . import CompletionCode from . import RemainingBytes @register_message_class class GetSelInfoReq(Message): __cmdid__ = constants.CMDID_GET_SEL_INFO __netfn__ = constants.NETFN_STORAGE @register_message_class class GetSelInfoRsp(Message): __cmdid__ = constants.CMDID_GET_SEL_INFO __netfn__ = constants.NETFN_STORAGE | 1 __fields__ = ( CompletionCode(), UnsignedInt('version', 1, default=0x51), UnsignedInt('entries', 2), UnsignedInt('free_bytes', 2), Timestamp('most_recent_addition'), Timestamp('most_recent_erase'), Bitfield('operation_support', 1, Bitfield.Bit('get_sel_allocation_info', 1), Bitfield.Bit('reserve_sel', 1), Bitfield.Bit('partial_add_sel_entry', 1), Bitfield.Bit('delete_sel', 1), Bitfield.ReservedBit(3), Bitfield.Bit('overflow_flag', 1)), ) @register_message_class class GetSelAllocationInfoReq(Message): __cmdid__ = constants.CMDID_GET_SEL_ALLOCATION_INFO __netfn__ = constants.NETFN_STORAGE @register_message_class class GetSelAllocationInfoRsp(Message): __cmdid__ = constants.CMDID_GET_SEL_ALLOCATION_INFO __netfn__ = constants.NETFN_STORAGE | 1 __fields__ = ( CompletionCode(), UnsignedInt('possible_alloc_units', 2), UnsignedInt('alloc_unit_size', 2), UnsignedInt('free_alloc_units', 2), UnsignedInt('largest_free_block', 2), UnsignedInt('max_record_size', 1) ) @register_message_class class ReserveSelReq(Message): __cmdid__ = constants.CMDID_RESERVE_SEL __netfn__ = constants.NETFN_STORAGE @register_message_class class ReserveSelRsp(Message): __cmdid__ = constants.CMDID_RESERVE_SEL __netfn__ = constants.NETFN_STORAGE | 1 __fields__ = ( CompletionCode(), UnsignedInt('reservation_id', 2) ) @register_message_class class GetSelEntryReq(Message): __cmdid__ = constants.CMDID_GET_SEL_ENTRY __netfn__ = constants.NETFN_STORAGE __fields__ = ( UnsignedInt('reservation_id', 2), UnsignedInt('record_id', 2), UnsignedInt('offset', 1), UnsignedInt('length', 1), ) @register_message_class class GetSelEntryRsp(Message): __cmdid__ = constants.CMDID_GET_SEL_ENTRY __netfn__ = constants.NETFN_STORAGE | 1 __fields__ = ( CompletionCode(), UnsignedInt('next_record_id', 2), RemainingBytes('record_data'), ) @register_message_class class AddSelEntryReq(Message): __cmdid__ = constants.CMDID_ADD_SEL_ENTRY __netfn__ = constants.NETFN_STORAGE __fields__ = ( ByteArray('record_data', 16) ) @register_message_class class AddSelEntryRsp(Message): __cmdid__ = constants.CMDID_ADD_SEL_ENTRY __netfn__ = constants.NETFN_STORAGE | 1 __fields__ = ( CompletionCode(), UnsignedInt('record_id', 2) ) @register_message_class class DeleteSelEntryReq(Message): __cmdid__ = constants.CMDID_DELETE_SEL_ENTRY __netfn__ = constants.NETFN_STORAGE __fields__ = ( UnsignedInt('reservation_id', 2), UnsignedInt('record_id', 2) ) @register_message_class class DeleteSelEntryRsp(Message): __cmdid__ = constants.CMDID_DELETE_SEL_ENTRY __netfn__ = constants.NETFN_STORAGE | 1 __fields__ = ( CompletionCode(), UnsignedInt('record_id', 2) ) @register_message_class class ClearSelReq(Message): __cmdid__ = constants.CMDID_CLEAR_SEL __netfn__ = constants.NETFN_STORAGE __fields__ = ( UnsignedInt('reservation_id', 2), ByteArray('key', 3, default=b'CLR'), UnsignedInt('cmd', 1) ) @register_message_class class ClearSelRsp(Message): __cmdid__ = constants.CMDID_CLEAR_SEL __netfn__ = constants.NETFN_STORAGE | 1 __fields__ = ( CompletionCode(), Bitfield('status', 1, Bitfield.Bit('erase_in_progress', 4), Bitfield.ReservedBit(4),), ) @register_message_class class GetSelTimeReq(Message): __cmdid__ = constants.CMDID_GET_SEL_TIME __netfn__ = constants.NETFN_STORAGE @register_message_class class GetSelTimeRsp(Message): __cmdid__ = constants.CMDID_GET_SEL_TIME __netfn__ = constants.NETFN_STORAGE | 1 __fields__ = ( CompletionCode(), Timestamp('timestamp') ) @register_message_class class SetSelTimeReq(Message): __cmdid__ = constants.CMDID_SET_SEL_TIME __netfn__ = constants.NETFN_STORAGE __fields__ = ( Timestamp('timestamp') ) @register_message_class class SetSelTimeRsp(Message): __cmdid__ = constants.CMDID_SET_SEL_TIME __netfn__ = constants.NETFN_STORAGE | 1 __fields__ = ( CompletionCode() ) python-ipmi-0.4.2/pyipmi/msgs/sensor.py0000664000372000037200000002335613574451473021025 0ustar travistravis00000000000000from __future__ import absolute_import # Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from . import constants from . import register_message_class from . import Message from . import UnsignedInt from . import Timestamp from . import Bitfield from . import CompletionCode from . import Optional from . import RemainingBytes @register_message_class class GetDeviceSdrInfoReq(Message): __cmdid__ = constants.CMDID_GET_DEVICE_SDR_INFO __netfn__ = constants.NETFN_SENSOR_EVENT @register_message_class class GetDeviceSdrInfoRsp(Message): __cmdid__ = constants.CMDID_GET_DEVICE_SDR_INFO __netfn__ = constants.NETFN_SENSOR_EVENT | 1 __fields__ = ( CompletionCode(), UnsignedInt('number_of_sensors', 1), Bitfield('flags', 1, Bitfield.Bit('lun0_has_sensors', 1), Bitfield.Bit('lun1_has_sensors', 1), Bitfield.Bit('lun2_has_sensors', 1), Bitfield.Bit('lun3_has_sensors', 1), Bitfield.ReservedBit(3, 0), Bitfield.Bit('dynamic_population', 1)), Optional( Timestamp('sensor_population_change') ), ) @register_message_class class GetDeviceSdrReq(Message): __cmdid__ = constants.CMDID_GET_DEVICE_SDR __netfn__ = constants.NETFN_SENSOR_EVENT __fields__ = ( UnsignedInt('reservation_id', 2, 0x0000), UnsignedInt('record_id', 2), UnsignedInt('offset', 1), UnsignedInt('bytes_to_read', 1), ) @register_message_class class GetDeviceSdrRsp(Message): __cmdid__ = constants.CMDID_GET_DEVICE_SDR __netfn__ = constants.NETFN_SENSOR_EVENT | 1 __fields__ = ( CompletionCode(), UnsignedInt('next_record_id', 2), RemainingBytes('record_data'), ) @register_message_class class ReserveDeviceSdrRepositoryReq(Message): __cmdid__ = constants.CMDID_RESERVE_DEVICE_SDR_REPOSITORY __netfn__ = constants.NETFN_SENSOR_EVENT @register_message_class class ReserveDeviceSdrRepositoryRsp(Message): __cmdid__ = constants.CMDID_RESERVE_DEVICE_SDR_REPOSITORY __netfn__ = constants.NETFN_SENSOR_EVENT | 1 __fields__ = ( CompletionCode(), UnsignedInt('reservation_id', 2) ) @register_message_class class GetSensorThresholdsReq(Message): __cmdid__ = constants.CMDID_GET_SENSOR_THRESHOLD __netfn__ = constants.NETFN_SENSOR_EVENT __fields__ = ( UnsignedInt('sensor_number', 1), ) @register_message_class class GetSensorThresholdsRsp(Message): __cmdid__ = constants.CMDID_GET_SENSOR_THRESHOLD __netfn__ = constants.NETFN_SENSOR_EVENT | 1 __fields__ = ( CompletionCode(), Bitfield('readable_mask', 1, Bitfield.Bit('lnc', 1, default=0), Bitfield.Bit('lcr', 1, default=0), Bitfield.Bit('lnr', 1, default=0), Bitfield.Bit('unc', 1, default=0), Bitfield.Bit('ucr', 1, default=0), Bitfield.Bit('unr', 1, default=0), Bitfield.ReservedBit(2, 0),), Bitfield('threshold', 6, Bitfield.Bit('lnc', 8, default=0), Bitfield.Bit('lcr', 8, default=0), Bitfield.Bit('lnr', 8, default=0), Bitfield.Bit('unc', 8, default=0), Bitfield.Bit('ucr', 8, default=0), Bitfield.Bit('unr', 8, default=0),), ) @register_message_class class SetSensorHysteresisReq(Message): __cmdid__ = constants.CMDID_SET_SENSOR_HYSTERESIS __netfn__ = constants.NETFN_SENSOR_EVENT __fields__ = ( UnsignedInt('sensor_number', 1), UnsignedInt('reserved', 1, 0xff), UnsignedInt('positive_going_hysteresis', 1), UnsignedInt('negative_going_hysteresis', 1), ) @register_message_class class SetSensorHysteresisRsp(Message): __cmdid__ = constants.CMDID_SET_SENSOR_HYSTERESIS __netfn__ = constants.NETFN_SENSOR_EVENT | 1 __fields__ = ( CompletionCode(), ) @register_message_class class GetSensorHysteresisReq(Message): __cmdid__ = constants.CMDID_GET_SENSOR_HYSTERESIS __netfn__ = constants.NETFN_SENSOR_EVENT __fields__ = ( UnsignedInt('sensor_number', 1), UnsignedInt('reserved', 1, 0xff), ) @register_message_class class GetSensorHysteresisRsp(Message): __cmdid__ = constants.CMDID_GET_SENSOR_HYSTERESIS __netfn__ = constants.NETFN_SENSOR_EVENT | 1 __fields__ = ( CompletionCode(), UnsignedInt('positive_going_hysteresis', 1), UnsignedInt('negative_going_hysteresis', 1), ) @register_message_class class SetSensorThresholdsReq(Message): __cmdid__ = constants.CMDID_SET_SENSOR_THRESHOLD __netfn__ = constants.NETFN_SENSOR_EVENT __fields__ = ( UnsignedInt('sensor_number', 1), Bitfield('set_mask', 1, Bitfield.Bit('lnc', 1, default=0), Bitfield.Bit('lcr', 1, default=0), Bitfield.Bit('lnr', 1, default=0), Bitfield.Bit('unc', 1, default=0), Bitfield.Bit('ucr', 1, default=0), Bitfield.Bit('unr', 1, default=0), Bitfield.ReservedBit(2, 0),), Bitfield('threshold', 6, Bitfield.Bit('lnc', 8, default=0), Bitfield.Bit('lcr', 8, default=0), Bitfield.Bit('lnr', 8, default=0), Bitfield.Bit('unc', 8, default=0), Bitfield.Bit('ucr', 8, default=0), Bitfield.Bit('unr', 8, default=0),), ) @register_message_class class SetSensorThresholdsRsp(Message): __cmdid__ = constants.CMDID_SET_SENSOR_THRESHOLD __netfn__ = constants.NETFN_SENSOR_EVENT | 1 __fields__ = ( CompletionCode(), ) @register_message_class class SetSensorEventEnableReq(Message): __cmdid__ = constants.CMDID_SET_SENSOR_EVENT_ENABLE __netfn__ = constants.NETFN_SENSOR_EVENT __fields__ = ( UnsignedInt('sensor_number', 1), Bitfield('enable', 1, Bitfield.ReservedBit(4, 0), Bitfield.Bit('config', 2, 0), Bitfield.Bit('sensor_scanning', 1, 0), Bitfield.Bit('event_message', 1, 0),), Optional(UnsignedInt('byte3', 1)), Optional(UnsignedInt('byte4', 1)), Optional(UnsignedInt('byte5', 1)), Optional(UnsignedInt('byte6', 1)), ) @register_message_class class SetSensorEventEnableRsp(Message): __cmdid__ = constants.CMDID_SET_SENSOR_EVENT_ENABLE __netfn__ = constants.NETFN_SENSOR_EVENT | 1 __fields__ = ( CompletionCode(), ) @register_message_class class GetSensorEventEnableReq(Message): __cmdid__ = constants.CMDID_GET_SENSOR_EVENT_ENABLE __netfn__ = constants.NETFN_SENSOR_EVENT __fields__ = ( UnsignedInt('sensor_number', 1), ) @register_message_class class GetSensorEventEnableRsp(Message): __cmdid__ = constants.CMDID_GET_SENSOR_EVENT_ENABLE __netfn__ = constants.NETFN_SENSOR_EVENT | 1 __fields__ = ( CompletionCode(), Bitfield('enabled', 1, Bitfield.ReservedBit(6, 0), Bitfield.Bit('sensor_scanning', 1, 0), Bitfield.Bit('event_message', 1, 0),), Optional(UnsignedInt('byte3', 1)), Optional(UnsignedInt('byte4', 1)), Optional(UnsignedInt('byte5', 1)), Optional(UnsignedInt('byte6', 1)), ) @register_message_class class RearmSensorEventsReq(Message): __cmdid__ = constants.CMDID_RE_ARM_SENSOR __netfn__ = constants.NETFN_SENSOR_EVENT __fields__ = ( UnsignedInt('sensor_number', 1), Bitfield('re_arm', 1, Bitfield.ReservedBit(7, 0), Bitfield.Bit('all_event_status', 1, 0),), UnsignedInt('re_arm_assertion_event', 2, 0), UnsignedInt('re_arm_deassertion_event', 2, 0), ) @register_message_class class RearmSensorEventsRsp(Message): __cmdid__ = constants.CMDID_RE_ARM_SENSOR __netfn__ = constants.NETFN_SENSOR_EVENT | 1 __fields__ = ( CompletionCode(), ) @register_message_class class GetSensorReadingReq(Message): __cmdid__ = constants.CMDID_GET_SENSOR_READING __netfn__ = constants.NETFN_SENSOR_EVENT __fields__ = ( UnsignedInt('sensor_number', 1), ) @register_message_class class GetSensorReadingRsp(Message): __cmdid__ = constants.CMDID_GET_SENSOR_READING __netfn__ = constants.NETFN_SENSOR_EVENT | 1 __fields__ = ( CompletionCode(), UnsignedInt('sensor_reading', 1), Bitfield('config', 1, Bitfield.ReservedBit(5, 0), Bitfield.Bit('initial_update_in_progress', 1, 0), Bitfield.Bit('sensor_scanning_disabled', 1, 0), Bitfield.Bit('event_message_disabled', 1, 0),), Optional(UnsignedInt('states1', 1)), Optional(UnsignedInt('states2', 1)), ) python-ipmi-0.4.2/pyipmi/msgs/lan.py0000664000372000037200000000505713574451473020264 0ustar travistravis00000000000000from __future__ import absolute_import # Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from . import constants from . import register_message_class from . import Message from . import ByteArray from . import UnsignedInt from . import Bitfield from . import CompletionCode from . import Optional from . import RemainingBytes @register_message_class class SetLanConfigurationParametersReq(Message): __cmdid__ = constants.CMDID_SET_LAN_CONFIGURATION_PARAMETERS __netfn__ = constants.NETFN_TRANSPORT __fields__ = ( Bitfield('command', 1, Bitfield.Bit('channel_number', 4, 0), Bitfield.ReservedBit(4, 0),), UnsignedInt('parameter_selector', 1), RemainingBytes('data'), ) @register_message_class class SetLanConfigurationParametersRsp(Message): __cmdid__ = constants.CMDID_SET_LAN_CONFIGURATION_PARAMETERS __netfn__ = constants.NETFN_TRANSPORT | 1 __fields__ = ( CompletionCode(), Optional(ByteArray('auxiliary', 4)) ) @register_message_class class GetLanConfigurationParametersReq(Message): __cmdid__ = constants.CMDID_GET_LAN_CONFIGURATION_PARAMETERS __netfn__ = constants.NETFN_TRANSPORT __fields__ = ( Bitfield('command', 1, Bitfield.Bit('channel_number', 4), Bitfield.ReservedBit(3, 0), Bitfield.Bit('get_parameter_revision_only', 1, 0),), UnsignedInt('parameter_selector', 1, 0), UnsignedInt('set_selector', 1, 0), UnsignedInt('block_selector', 1, 0), ) @register_message_class class GetLanConfigurationParametersRsp(Message): __cmdid__ = constants.CMDID_GET_LAN_CONFIGURATION_PARAMETERS __netfn__ = constants.NETFN_TRANSPORT | 1 __fields__ = ( CompletionCode(), UnsignedInt('parameter_revision', 1, 0), RemainingBytes('data'), ) python-ipmi-0.4.2/pyipmi/msgs/hpm.py0000664000372000037200000002165213574451473020275 0ustar travistravis00000000000000from __future__ import absolute_import # Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from . import constants from . import register_message_class from . import UnsignedInt from . import Bitfield from . import CompletionCode from . import Optional from . import RemainingBytes from . import GroupExtensionIdentifier from .picmg import PicmgMessage, PICMG_IDENTIFIER @register_message_class class GetTargetUpgradeCapabilitiesReq(PicmgMessage): __cmdid__ = constants.CMDID_HPM_GET_TARGET_UPGRADE_CAPABILITIES __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), ) @register_message_class class GetTargetUpgradeCapabilitiesRsp(PicmgMessage): __cmdid__ = constants.CMDID_HPM_GET_TARGET_UPGRADE_CAPABILITIES __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('hpm_1_version', 1), Bitfield('capabilities', 1, Bitfield.Bit('firmware_upgrade_undesirable', 1), Bitfield.Bit('automatic_rollback_overriden', 1), Bitfield.Bit('ipmc_degraded_during_upgrade', 1), Bitfield.Bit('deferred_activation', 1), Bitfield.Bit('services_affected_by_upgrade', 1), Bitfield.Bit('manual_rollback', 1), Bitfield.Bit('automatic_rollback', 1), Bitfield.Bit('selftest', 1),), Bitfield('timeout', 4, Bitfield.Bit('upgrade', 8), Bitfield.Bit('selftest', 8), Bitfield.Bit('rollback', 8), Bitfield.Bit('inaccessibility', 8),), UnsignedInt('component_present', 1), ) @register_message_class class GetComponentPropertiesReq(PicmgMessage): __cmdid__ = constants.CMDID_HPM_GET_COMPONENT_PROPERTIES __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('id', 1), UnsignedInt('selector', 1), ) @register_message_class class GetComponentPropertiesRsp(PicmgMessage): __cmdid__ = constants.CMDID_HPM_GET_COMPONENT_PROPERTIES __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), RemainingBytes('data'), ) @register_message_class class AbortFirmwareUpgradeReq(PicmgMessage): __cmdid__ = constants.CMDID_HPM_ABORT_FIRMWARE_UPGRADE __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), ) @register_message_class class AbortFirmwareUpgradeRsp(PicmgMessage): __cmdid__ = constants.CMDID_HPM_ABORT_FIRMWARE_UPGRADE __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), ) @register_message_class class InitiateUpgradeActionReq(PicmgMessage): __cmdid__ = constants.CMDID_HPM_INITIATE_UPGRADE_ACTION __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('components', 1), UnsignedInt('action', 1), ) @register_message_class class InitiateUpgradeActionRsp(PicmgMessage): __cmdid__ = constants.CMDID_HPM_INITIATE_UPGRADE_ACTION __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), ) @register_message_class class UploadFirmwareBlockReq(PicmgMessage): __cmdid__ = constants.CMDID_HPM_UPLOAD_FIRMWARE_BLOCK __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('number', 1), RemainingBytes('data'), ) @register_message_class class UploadFirmwareBlockRsp(PicmgMessage): __cmdid__ = constants.CMDID_HPM_UPLOAD_FIRMWARE_BLOCK __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), Optional(UnsignedInt('section_offset', 4)), Optional(UnsignedInt('section_length', 4)), ) @register_message_class class FinishFirmwareUploadReq(PicmgMessage): __cmdid__ = constants.CMDID_HPM_FINISH_FIRMWARE_UPLOAD __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('component_id', 1), UnsignedInt('image_length', 4), ) @register_message_class class FinishFirmwareUploadRsp(PicmgMessage): __cmdid__ = constants.CMDID_HPM_FINISH_FIRMWARE_UPLOAD __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), ) @register_message_class class GetUpgradeStatusReq(PicmgMessage): __cmdid__ = constants.CMDID_HPM_GET_UPGRADE_STATUS __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), ) @register_message_class class GetUpgradeStatusRsp(PicmgMessage): __cmdid__ = constants.CMDID_HPM_GET_UPGRADE_STATUS __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('command_in_progress', 1), UnsignedInt('last_completion_code', 1), Optional(UnsignedInt('completion_estimate', 1)), ) @register_message_class class ActivateFirmwareReq(PicmgMessage): __cmdid__ = constants.CMDID_HPM_ACTIVATE_FIRMWARE __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), Optional(UnsignedInt('rollback_override_policy', 1)), ) @register_message_class class ActivateFirmwareRsp(PicmgMessage): __cmdid__ = constants.CMDID_HPM_ACTIVATE_FIRMWARE __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), ) @register_message_class class QuerySelftestResultsReq(PicmgMessage): __cmdid__ = constants.CMDID_HPM_QUERY_SELFTEST_RESULTS __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), ) @register_message_class class QuerySelftestResultsRsp(PicmgMessage): __cmdid__ = constants.CMDID_HPM_QUERY_SELFTEST_RESULTS __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('selftest_result_1', 1), UnsignedInt('selftest_result_2', 1), ) @register_message_class class QueryRollbackStatusReq(PicmgMessage): __cmdid__ = constants.CMDID_HPM_QUERY_ROLLBACK_STATUS __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), ) @register_message_class class QueryRollbackStatusRsp(PicmgMessage): __cmdid__ = constants.CMDID_HPM_QUERY_ROLLBACK_STATUS __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('rollback_status', 1), Optional(UnsignedInt('completion_estimate', 1)), ) @register_message_class class InitiateManualRollbackReq(PicmgMessage): __cmdid__ = constants.CMDID_HPM_INITIATE_MANUAL_ROLLBACK __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), ) @register_message_class class InitiateManualRollbackRsp(PicmgMessage): __cmdid__ = constants.CMDID_HPM_INITIATE_MANUAL_ROLLBACK __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), ) python-ipmi-0.4.2/pyipmi/msgs/registry.py0000664000372000037200000000707613574451473021365 0ustar travistravis00000000000000# Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from functools import partial from ..errors import DescriptionError class MessageRegistry(object): def __init__(self): self.registry = dict() def register_class(self, cls): # some sanity checks # (1) class name has to end in Req or Rsp if cls.__name__[-3:] not in ('Req', 'Rsp'): raise DescriptionError('Class name has to end in Req or Rsp') # (2) mandantory fields for attr in ('__netfn__', '__cmdid__', '__default_lun__', '__group_extension__'): if not hasattr(cls, attr): raise DescriptionError('Class has to have attribute "%s"' % attr) # (3) netfn lsb has to be 0 for Req and 1 for Rsp if cls.__name__.endswith('Req') and cls.__netfn__ & 1 != 0: raise DescriptionError('LSB of NetFN of a Request must be 0') if cls.__name__.endswith('Rsp') and cls.__netfn__ & 1 != 1: raise DescriptionError('LSB of NetFN of a Request must be 1') # (4) must not be registered before if cls.__name__ in self.registry: raise DescriptionError('Message %s already registered' % cls.__name__) msg_id = (cls.__netfn__, cls.__cmdid__, cls.__group_extension__) if msg_id in self.registry: raise DescriptionError('Message (%d,%d,%d) already registered (%s)' % (msg_id[0], msg_id[1], msg_id[2], self.registry[msg_id])) # register name self.registry[cls.__name__] = cls # register (netfn, cmdid, group_extension) tuple self.registry[msg_id] = cls # register return cls def create(self, netfn, cmdid, group_extension, *args, **kwargs): return self.registry[(netfn, cmdid, group_extension)](*args, **kwargs) def create_response(self, req): return self.create(self, req.netfn + 1, req.cmdid, req.group_extension) def create_request_by_name(self, name, *args, **kwargs): return self.registry[name + "Req"](*args, **kwargs) def create_response_by_name(self, name, *args, **kwargs): return self.registry[name + "Rsp"](*args, **kwargs) DEFAULT_REGISTRY = MessageRegistry() register_message_class = partial(MessageRegistry.register_class, DEFAULT_REGISTRY) create_message = partial(MessageRegistry.create, DEFAULT_REGISTRY) create_response_message = partial(MessageRegistry.create_response, DEFAULT_REGISTRY) create_request_by_name = partial(MessageRegistry.create_request_by_name, DEFAULT_REGISTRY) create_response_by_name = partial(MessageRegistry.create_response_by_name, DEFAULT_REGISTRY) python-ipmi-0.4.2/pyipmi/msgs/dcmi.py0000664000372000037200000002013513574451473020420 0ustar travistravis00000000000000# Copyright (c) 2018 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from __future__ import absolute_import from . import constants from . import register_message_class from . import Bitfield from . import CompletionCode from . import GroupExtensionIdentifier from . import Message from . import RemainingBytes from . import Timestamp from . import UnsignedInt DCMI_GROUP_CODE = 0xdc class DcmiMessage(Message): __group_extension__ = DCMI_GROUP_CODE @register_message_class class GetDcmiCapabilitiesReq(DcmiMessage): __cmdid__ = constants.CMDID_GET_DCMI_CAPABILITIES_INFO __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('group_extension_id', DCMI_GROUP_CODE), UnsignedInt('parameter_selector', 1), ) @register_message_class class GetDcmiCapabilitiesRsp(DcmiMessage): __cmdid__ = constants.CMDID_GET_DCMI_CAPABILITIES_INFO __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('group_extension_id', DCMI_GROUP_CODE), Bitfield('specification_conformence', 2, Bitfield.Bit('major', 8), Bitfield.Bit('minor', 8)), UnsignedInt('parameter_revision', 1), RemainingBytes('parameter_data'), ) @register_message_class class GetPowerReadingReq(DcmiMessage): __cmdid__ = constants.CMDID_GET_POWER_READING __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('group_extension_id', DCMI_GROUP_CODE), UnsignedInt('mode', 1), UnsignedInt('attributes', 1), UnsignedInt('reserved', 1), ) @register_message_class class GetPowerReadingRsp(DcmiMessage): __cmdid__ = constants.CMDID_GET_POWER_READING __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __not_implemented__ = True __fields__ = ( CompletionCode(), GroupExtensionIdentifier('group_extension_id', DCMI_GROUP_CODE), UnsignedInt('current_power', 2), UnsignedInt('minimum_power', 2), UnsignedInt('maximum_power', 2), UnsignedInt('average_power', 2), Timestamp('timestamp'), UnsignedInt('period', 4), UnsignedInt('reading_state', 1), ) @register_message_class class GetPowerLimitReq(DcmiMessage): __cmdid__ = constants.CMDID_GET_POWER_LIMIT __netfn__ = constants.NETFN_GROUP_EXTENSION __not_implemented__ = True __fields__ = ( GroupExtensionIdentifier('group_extension_id', DCMI_GROUP_CODE), ) @register_message_class class GetPowerLimitRsp(DcmiMessage): __cmdid__ = constants.CMDID_GET_POWER_LIMIT __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __not_implemented__ = True __fields__ = ( CompletionCode(), GroupExtensionIdentifier('group_extension_id', DCMI_GROUP_CODE), ) @register_message_class class SetPowerLimitReq(DcmiMessage): __cmdid__ = constants.CMDID_SET_POWER_LIMIT __netfn__ = constants.NETFN_GROUP_EXTENSION __not_implemented__ = True __fields__ = ( GroupExtensionIdentifier('group_extension_id', DCMI_GROUP_CODE), ) @register_message_class class SetPowerLimitRsp(DcmiMessage): __cmdid__ = constants.CMDID_SET_POWER_LIMIT __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __not_implemented__ = True __fields__ = ( CompletionCode(), GroupExtensionIdentifier('group_extension_id', DCMI_GROUP_CODE), ) @register_message_class class GetActivateDeactivatePowerLimitReq(DcmiMessage): __cmdid__ = constants.CMDID_ACTIVATE_DEACTIVATE_POWER_LIMIT __netfn__ = constants.NETFN_GROUP_EXTENSION __not_implemented__ = True __fields__ = ( GroupExtensionIdentifier('group_extension_id', DCMI_GROUP_CODE), ) @register_message_class class GetActivateDeactivatePowerLimitRsp(DcmiMessage): __cmdid__ = constants.CMDID_ACTIVATE_DEACTIVATE_POWER_LIMIT __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __not_implemented__ = True __fields__ = ( CompletionCode(), GroupExtensionIdentifier('group_extension_id', DCMI_GROUP_CODE), ) @register_message_class class GetAssetTagReq(DcmiMessage): __cmdid__ = constants.CMDID_GET_ASSET_TAG __netfn__ = constants.NETFN_GROUP_EXTENSION __not_implemented__ = True __fields__ = ( GroupExtensionIdentifier('group_extension_id', DCMI_GROUP_CODE), ) @register_message_class class GetAssetTagRsp(DcmiMessage): __cmdid__ = constants.CMDID_GET_ASSET_TAG __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __not_implemented__ = True __fields__ = ( CompletionCode(), GroupExtensionIdentifier('group_extension_id', DCMI_GROUP_CODE), ) @register_message_class class GetDcmiSensorInfoReq(DcmiMessage): __cmdid__ = constants.CMDID_GET_DCMI_SENSOR_INFO __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('group_extension_id', DCMI_GROUP_CODE), UnsignedInt('sensor_type', 1), UnsignedInt('entity_id', 1), UnsignedInt('entity_instance', 1), UnsignedInt('entity_instance_start', 1), ) @register_message_class class GetDcmiSensorInfoRsp(DcmiMessage): __cmdid__ = constants.CMDID_GET_DCMI_SENSOR_INFO __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('group_extension_id', DCMI_GROUP_CODE), UnsignedInt('total_number_of_instances', 1), UnsignedInt('number_of_record_ids', 1), RemainingBytes('record_ids'), ) @register_message_class class SetAssetTagReq(DcmiMessage): __cmdid__ = constants.CMDID_SET_ASSET_TAG __netfn__ = constants.NETFN_GROUP_EXTENSION __not_implemented__ = True __fields__ = ( GroupExtensionIdentifier('group_extension_id', DCMI_GROUP_CODE), ) @register_message_class class SetAssetTagRsp(DcmiMessage): __cmdid__ = constants.CMDID_SET_ASSET_TAG __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __not_implemented__ = True __fields__ = ( CompletionCode(), GroupExtensionIdentifier('group_extension_id', DCMI_GROUP_CODE), ) @register_message_class class GetManagementControllerIdStringReq(DcmiMessage): __cmdid__ = constants.CMDID_GET_MANAGEMENT_CONTROLLER_ID_STRING __netfn__ = constants.NETFN_GROUP_EXTENSION __not_implemented__ = True __fields__ = ( GroupExtensionIdentifier('group_extension_id', DCMI_GROUP_CODE), ) @register_message_class class GetManagementControllerIdStringRsp(DcmiMessage): __cmdid__ = constants.CMDID_GET_MANAGEMENT_CONTROLLER_ID_STRING __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __not_implemented__ = True __fields__ = ( CompletionCode(), GroupExtensionIdentifier('group_extension_id', DCMI_GROUP_CODE), ) @register_message_class class SetManagementControllerIdStringReq(DcmiMessage): __cmdid__ = constants.CMDID_SET_MANAGEMENT_CONTROLLER_ID_STRING __netfn__ = constants.NETFN_GROUP_EXTENSION __not_implemented__ = True __fields__ = ( GroupExtensionIdentifier('group_extension_id', DCMI_GROUP_CODE), ) @register_message_class class SetManagementControllerIdStringRsp(DcmiMessage): __cmdid__ = constants.CMDID_SET_MANAGEMENT_CONTROLLER_ID_STRING __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __not_implemented__ = True __fields__ = ( CompletionCode(), GroupExtensionIdentifier('group_extension_id', DCMI_GROUP_CODE), ) python-ipmi-0.4.2/pyipmi/msgs/constants.py0000664000372000037200000003020713574451473021521 0ustar travistravis00000000000000# Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # completion codes CC_OK = 0x00 CC_NODE_BUSY = 0xc0 CC_INV_CMD = 0xc1 CC_INV_CMD_FOR_LUN = 0xc2 CC_TIMEOUT = 0xc3 CC_OUT_OF_SPACE = 0xc4 CC_RES_CANCELED = 0xc5 CC_REQ_DATA_TRUNC = 0xc6 CC_REQ_DATA_INV_LENGTH = 0xc7 CC_REQ_DATA_FIELD_EXCEED = 0xc8 CC_PARAM_OUT_OF_RANGE = 0xc9 CC_CANT_RET_NUM_REQ_BYTES = 0xca CC_REQ_DATA_NOT_PRESENT = 0xcb CC_INV_DATA_FIELD_IN_REQ = 0xcc CC_ILL_SENSOR_OR_RECORD = 0xcd CC_RESP_COULD_NOT_BE_PRV = 0xce CC_CANT_RESP_DUPLI_REQ = 0xcf CC_CANT_RESP_SDRR_UPDATE = 0xd0 CC_CANT_RESP_FIRM_UPDATE = 0xd1 CC_CANT_RESP_BMC_INIT = 0xd2 CC_DESTINATION_UNAVAILABLE = 0xd3 CC_INSUFFICIENT_PRIVILEGES = 0xd4 CC_NOT_SUPPORTED_PRESENT_STATE = 0xd5 CC_ILLEGAL_COMMAND_DISABLED = 0xd6 CC_UNSPECIFIED_ERROR = 0xff COMPLETION_CODE_DESCR = ( (CC_OK, 'Command Completed Normally'), (CC_NODE_BUSY, 'Node Busy'), (CC_INV_CMD, 'Invalid Command'), (CC_INV_CMD_FOR_LUN, 'Command invalid for given LUN'), (CC_TIMEOUT, 'Timeout while processing command'), (CC_OUT_OF_SPACE, 'Out of space'), (CC_RES_CANCELED, 'Reservation Canceled or Invalid Reservation ID'), (CC_REQ_DATA_TRUNC, 'Request data truncated'), (CC_REQ_DATA_INV_LENGTH, 'Request data length invalid'), (CC_REQ_DATA_FIELD_EXCEED, 'Request data field length limit exceeded'), (CC_PARAM_OUT_OF_RANGE, 'Parameter out of range'), (CC_CANT_RET_NUM_REQ_BYTES, 'Cannot return number of requested data bytes'), (CC_REQ_DATA_NOT_PRESENT, 'Requested data not present'), (CC_INV_DATA_FIELD_IN_REQ, 'Invalid data field in Request'), (CC_ILL_SENSOR_OR_RECORD, 'Command illegal for specified sensor or record'), (CC_RESP_COULD_NOT_BE_PRV, 'Command response could not be provided'), (CC_CANT_RESP_DUPLI_REQ, 'Cannot execute duplicated request'), (CC_CANT_RESP_SDRR_UPDATE, 'Command response could not be provided. SDRR in update mode'), (CC_CANT_RESP_FIRM_UPDATE, 'Command response could not be provided. Device in firmware ' 'update mode'), (CC_CANT_RESP_BMC_INIT, 'Command response could not be provided. BMC initialization or ' 'initialization agent in progress'), (CC_DESTINATION_UNAVAILABLE, 'Destination unavailable'), (CC_INSUFFICIENT_PRIVILEGES, 'Cannot execute command due to insufficient privilege level'), (CC_NOT_SUPPORTED_PRESENT_STATE, 'Cannot execute command. Not supported in present state'), (CC_ILLEGAL_COMMAND_DISABLED, 'Cannot execute command. Command sub-function has been disabled ' 'or is unavailable'), (CC_UNSPECIFIED_ERROR, 'Unspecified error'), ) # network functions NETFN_CHASSIS = 0x00 NETFN_BRIDGE = 0x02 NETFN_SENSOR_EVENT = 0x04 NETFN_APP = 0x06 NETFN_FIRMWARE = 0x08 NETFN_STORAGE = 0x0a NETFN_TRANSPORT = 0x0c NETFN_GROUP_EXTENSION = 0x2c NETFN_OEM = 0x2e NETFN_DESCR = ( (NETFN_CHASSIS, 'Chassis'), (NETFN_BRIDGE, 'Bridge'), (NETFN_SENSOR_EVENT, 'Sensor/Event'), (NETFN_APP, 'App'), (NETFN_FIRMWARE, 'Firmware'), (NETFN_STORAGE, 'Storage'), (NETFN_TRANSPORT, 'Transport'), (NETFN_GROUP_EXTENSION, 'Group Extension'), (NETFN_OEM, 'IANA'), ) # IPM device 'global' .. NetFn App CMDID_GET_DEVICE_ID = 0x01 CMDID_COLD_RESET = 0x02 CMDID_WARM_RESET = 0x03 CMDID_GET_SELF_TEST_RESULTS = 0x04 CMDID_MANUFACTURING_TEST_ON = 0x05 CMDID_SET_ACPI_POWER_STATE = 0x06 CMDID_GET_ACPI_POWER_STATE = 0x07 CMDID_GET_DEVICE_GUID = 0x08 CMDID_GET_NETFN_SUPPORT = 0x09 CMDID_GET_COMMAND_SUPPORT = 0x0a CMDID_GET_COMMAND_SUBFUNCTION_SUPPORT = 0x0b CMDID_GET_CONFIGURATION_COMMANDS = 0x0c CMDID_GET_CONFIGURATION_SUBFUNCTION_COMMANDS = 0x0d CMDID_SET_COMMAND_ENABLES = 0x60 CMDID_GET_COMMAND_ENABLES = 0x61 CMDID_SET_COMMAND_SUBFUNCTION_ENABLES = 0x62 CMDID_GET_COMMAND_SUBFUNCTION_ENABLES = 0x63 CMDID_GET_OEM_NETFN_IANA_SUPPORT = 0x64 # BMC watchdog timer .. NetFn App CMDID_RESET_WATCHDOG_TIMER = 0x22 CMDID_SET_WATCHDOG_TIMER = 0x24 CMDID_GET_WATCHDOG_TIMER = 0x25 # BMC device and messaging .. NetFn App CMDID_SET_BMC_GLOBAL_ENABLES = 0x2e CMDID_GET_BMC_GLOBAL_ENABLES = 0x2f CMDID_CLEAR_MESSAGE_FLAGS = 0x30 CMDID_GET_MESSAGE_FLAGS = 0x31 CMDID_ENABLE_MESSAGE_CHANNEL_RECEIVE = 0x32 CMDID_GET_MESSAGE = 0x33 CMDID_SEND_MESSAGE = 0x34 CMDID_READ_EVENT_MESSAGE_BUFFER = 0x35 CMDID_GET_BT_INTERFACE_CAPABILITIES = 0x36 CMDID_GET_SYSTEM_GUID = 0x37 CMDID_GET_CHANNEL_AUTHENTICATION_CAPABILITIES = 0x38 CMDID_GET_SESSION_CHALLENGE = 0x39 CMDID_ACTIVATE_SESSION = 0x3a CMDID_SET_SESSION_PRIVILEGE_LEVEL = 0x3b CMDID_CLOSE_SESSION = 0x3c CMDID_GET_SESSION_INFO = 0x3d CMDID_GET_AUTHCODE = 0x3f CMDID_SET_CHANNEL_ACCESS = 0x40 CMDID_GET_CHANNEL_ACCESS = 0x41 CMDID_GET_CHANNEL_INFO = 0x42 CMDID_SET_USER_ACCESS = 0x43 CMDID_GET_USER_ACCESS = 0x44 CMDID_SET_USER_NAME = 0x45 CMDID_GET_USER_NAME = 0x46 CMDID_SET_USER_PASSWORD = 0x47 CMDID_ACTIVATE_PAYLOAD = 0x48 CMDID_DEACTIVATE_PAYLOAD = 0x49 CMDID_GET_PAYLOAD_ACTITVATION_STATUS = 0x4a CMDID_GET_PAYLOAD_INSTANCE_INFO = 0x4b CMDID_SET_USER_PAYLOAD_ACCESS = 0x4c CMDID_GET_USER_PAYLOAD_ACCESS = 0x4d CMDID_GET_CHANNEL_PAYLOAD_SUPPORT = 0x4e CMDID_GET_CHANNEL_PAYLOAD_VERSION = 0x4f CMDID_GET_CHANNEL_OEM_PAYLOAD_INFO = 0x50 CMDID_MASTER_WRITE_READ = 0x52 CMDID_GET_CHANNEL_CIPHER_SUITES = 0x54 CMDID_SUSPEND_RESUME_PAYLOAD_ENCRYPTION = 0x55 CMDID_SET_CHANNEL_SECURITY_KEYS = 0x56 CMDID_GET_SYSTEM_INTERFACE_CAPABILITIES = 0x57 CMDID_SET_SYSTEM_INFO_PARAMETERS = 0x58 CMDID_GET_SYSTEM_INFO_PARAMETERS = 0x59 # chassis device .. NetFn Chassis CMDID_GET_CHASSIS_CAPABILITIES = 0x00 CMDID_GET_CHASSIS_STATUS = 0x01 CMDID_CHASSIS_CONTROL = 0x02 CMDID_CHASSIS_RESET = 0x03 CMDID_CHASSIS_IDENTIFY = 0x04 CMDID_SET_CHASSIS_CAPABILITIES = 0x05 CMDID_SET_POWER_RESTORE_POLICY = 0x06 CMDID_GET_SYSTEM_RESTART_CAUSE = 0x07 CMDID_SET_SYSTEM_BOOT_OPTIONS = 0x08 CMDID_GET_SYSTEM_BOOT_OPTIONS = 0x09 CMDID_GET_POH_COUNTER = 0x0f # event .. NetFn S/E CMDID_SET_EVENT_RECEIVER = 0x00 CMDID_GET_EVENT_RECEIVER = 0x01 CMDID_PLATFORM_EVENT = 0x02 # PEF and alerting .. NetFn S/E CMDID_GET_PEF_CAPABILITIES = 0x10 CMDID_ARM_PEF_POSTPONE_TIMER = 0x11 CMDID_SET_PEFCONFIGURATION_PARAMETERS = 0x12 CMDID_GET_PEFCONFIGURATION_PARAMETERS = 0x13 CMDID_SET_LAST_PROCESSED_EVENT_ID = 0x14 CMDID_GET_LAST_PROCESSED_EVENT_ID = 0x15 CMDID_ALERT_IMMEDIATE = 0x16 CMDID_PET_ACKNOWLEDGE = 0x17 # sensor device .. NetFn S/E CMDID_GET_DEVICE_SDR_INFO = 0x20 CMDID_GET_DEVICE_SDR = 0x21 CMDID_RESERVE_DEVICE_SDR_REPOSITORY = 0x22 CMDID_GET_SENSOR_READING_FACTOR = 0x23 CMDID_SET_SENSOR_HYSTERESIS = 0x24 CMDID_GET_SENSOR_HYSTERESIS = 0x25 CMDID_SET_SENSOR_THRESHOLD = 0x26 CMDID_GET_SENSOR_THRESHOLD = 0x27 CMDID_SET_SENSOR_EVENT_ENABLE = 0x28 CMDID_GET_SENSOR_EVENT_ENABLE = 0x29 CMDID_RE_ARM_SENSOR = 0x2a CMDID_GET_SENSOR_EVENT_STATUS = 0x2b CMDID_GET_SENSOR_READING = 0x2d CMDID_SET_SENSOR_TYPE = 0x2e CMDID_GET_SENSOR_TYPE = 0x2f CMDID_SET_SENSOR_READING_AND_EVENT_STATUS = 0x30 # fru device .. NetFn Storage CMDID_GET_FRU_INVENTORY_AREA_INFO = 0x10 CMDID_READ_FRU_DATA = 0x11 CMDID_WRITE_FRU_DATA = 0x12 # SDR device .. NetFn Storage CMDID_GET_SDR_REPOSITORY_INFO = 0x20 CMDID_GET_SDR_REPOSITORY_ALLOCATION_INFO = 0x21 CMDID_RESERVE_SDR_REPOSITORY = 0x22 CMDID_GET_SDR = 0x23 CMDID_ADD_SDR = 0x24 CMDID_PARTIAL_ADD_SDR = 0x25 CMDID_DELETE_SDR = 0x26 CMDID_CLEAR_SDR_REPOSITORY = 0x27 CMDID_GET_SDR_REPOSITORY_TIME = 0x28 CMDID_SET_SDR_REPOSITORY_TIME = 0x29 CMDID_ENTER_SDR_REPOSITORY_UPDATE_MODE = 0x2a CMDID_EXIT_SDR_REPOSITORY_UPDATE_MODE = 0x2b CMDID_RUN_INITIALIZATION_AGENT = 0x2c # SEL device .. NetFn Storage CMDID_GET_SEL_INFO = 0x40 CMDID_GET_SEL_ALLOCATION_INFO = 0x41 CMDID_RESERVE_SEL = 0x42 CMDID_GET_SEL_ENTRY = 0x43 CMDID_ADD_SEL_ENTRY = 0x44 CMDID_PARTIAL_ADD_SEL_ENTRY = 0x45 CMDID_DELETE_SEL_ENTRY = 0x46 CMDID_CLEAR_SEL = 0x47 CMDID_GET_SEL_TIME = 0x48 CMDID_SET_SEL_TIME = 0x49 CMDID_GET_AUXILIARY_LOG_STATUS = 0x5a CMDID_SET_AUXILIARY_LOG_STATUS = 0x5b CMDID_GET_SEL_TIME_UTC_OFFSET = 0x5c CMDID_SET_SEL_TIME_UTC_OFFSET = 0x5d # LAN device .. NetFn Transport CMDID_SET_LAN_CONFIGURATION_PARAMETERS = 0x01 CMDID_GET_LAN_CONFIGURATION_PARAMETERS = 0x02 CMDID_SUSPEND_BMC_ARPS = 0x03 CMDID_GET_IP_UDP_RMCP_STATISTICS = 0x04 # Serial/Modem device .. NetFn Transport # Command Forwarding .. NetFn Transport # bridge management (ICMB) .. NetFn Bridge # discovery (ICMB) .. NetFn Bridge # bridging (ICMB) .. NetFn Bridge # event (ICMB) .. NetFn Bridge # other (ICMB) .. NetFn Bridge # PICMG commands .. NetFn Group Extension (ID 0) CMDID_GET_PICMG_PROPERTIES = 0x00 CMDID_GET_ADDRESS_INFO = 0x01 CMDID_GET_SHELF_ADDRESS_INFO = 0x02 CMDID_SET_SHELF_ADDRESS_INFO = 0x03 CMDID_FRU_CONTROL = 0x04 CMDID_GET_FRU_LED_PROPERTIES = 0x05 CMDID_GET_FRU_LED_COLOR_CAPABILITIES = 0x06 CMDID_SET_FRU_LED_STATE = 0x07 CMDID_GET_FRU_LED_STATE = 0x08 CMDID_SET_IPMB_STATE = 0x09 CMDID_SET_FRU_ACTIVATION_POLICY = 0x0a CMDID_GET_FRU_ACTIVATION_POLICY = 0x0b CMDID_SET_FRU_ACTIVATION = 0x0c CMDID_GET_DEVLOC_RECORD_ID = 0x0d CMDID_SET_PORT_STATE = 0x0e CMDID_GET_PORT_STATE = 0x0f CMDID_COMPUTE_POWER_PROPERTIES = 0x10 CMDID_SET_POWER_LEVEL = 0x11 CMDID_GET_POWER_LEVEL = 0x12 CMDID_RENEGOTIATE_POWER = 0x13 CMDID_GET_FAN_SPEED_PROPERTIES = 0x14 CMDID_SET_FAN_LEVEL = 0x15 CMDID_GET_FAN_LEVEL = 0x16 CMDID_BUSED_RESOURCE = 0x17 CMDID_GET_IPMB_LINK_INFO = 0x18 CMDID_GET_SHELF_MANAGER_IPMB_ADDRESS = 0x1b CMDID_SET_FAN_POLICY = 0x1c CMDID_GET_FAN_POLICY = 0x1d CMDID_FRU_CONTROL_CAPABILITIES = 0x1e CMDID_FRU_INVENTORY_DEVICE_LOCK_CONTROL = 0x1f CMDID_FRU_INVENTORY_DEVICE_WRITE = 0x20 CMDID_GET_SHELF_MANAGER_IP_ADDRESSES = 0x21 CMDID_GET_SHELF_POWER_ALLOCATION = 0x22 CMDID_SET_CHANNEL_SIGNALING_CLASS = 0x3b CMDID_GET_CHANNEL_SIGNALING_CLASS = 0x3c # PICMG AdvancedMC .. NetFn Group Extension (ID 0) CMDID_SET_AMC_PORT_STATE = 0x19 CMDID_GET_AMC_PORT_STATE = 0x1a # PICMG MicroTCA .. NetFn Group Extension (ID 0) CMDID_GET_LOCATION_INFO = 0x23 CMDID_POWER_CHANNEL_CONTROL = 0x24 CMDID_GET_POWER_CHANNEL_STATUS = 0x25 CMDID_PM_RESET = 0x26 CMDID_GET_PM_STATUS = 0x27 CMDID_PM_HEARTBEAT = 0x28 CMDID_GET_TELCO_ALARM_CAPABILITY = 0x29 CMDID_SET_TELCO_ALARM_STATE = 0x2a CMDID_GET_TELCO_ALARM_STATE = 0x2b # PICMG HPM.1 commands .. NetFn Group Extension (ID 0) CMDID_HPM_GET_TARGET_UPGRADE_CAPABILITIES = 0x2e CMDID_HPM_GET_COMPONENT_PROPERTIES = 0x2f CMDID_HPM_ABORT_FIRMWARE_UPGRADE = 0x30 CMDID_HPM_INITIATE_UPGRADE_ACTION = 0x31 CMDID_HPM_UPLOAD_FIRMWARE_BLOCK = 0x32 CMDID_HPM_FINISH_FIRMWARE_UPLOAD = 0x33 CMDID_HPM_GET_UPGRADE_STATUS = 0x34 CMDID_HPM_ACTIVATE_FIRMWARE = 0x35 CMDID_HPM_QUERY_SELFTEST_RESULTS = 0x36 CMDID_HPM_QUERY_ROLLBACK_STATUS = 0x37 CMDID_HPM_INITIATE_MANUAL_ROLLBACK = 0x38 # DCMI commands .. NetFn Group Extension (ID 0xdc) CMDID_GET_DCMI_CAPABILITIES_INFO = 0x01 CMDID_GET_POWER_READING = 0x02 CMDID_GET_POWER_LIMIT = 0x03 CMDID_SET_POWER_LIMIT = 0x04 CMDID_ACTIVATE_DEACTIVATE_POWER_LIMIT = 0x05 CMDID_GET_ASSET_TAG = 0x06 CMDID_GET_DCMI_SENSOR_INFO = 0x07 CMDID_SET_ASSET_TAG = 0x08 CMDID_GET_MANAGEMENT_CONTROLLER_ID_STRING = 0x09 CMDID_SET_MANAGEMENT_CONTROLLER_ID_STRING = 0x0a cc_err_cmd_specific_desc = { CMDID_GET_SESSION_CHALLENGE: { 0x81: 'invalid user name', 0x82: 'null user name (User 1) not enabled', }, CMDID_ACTIVATE_SESSION: { 0x81: 'No session slot available (BMC cannot accept any more' ' sessions)', 0x82: 'No slot available for given user', 0x83: 'No slot available to support user due to maximum privilege' ' capability', 0x84: 'session sequence number out-of-range', 0x85: 'invalid Session ID in request', 0x86: 'requested maximum privilege level exceeds user and/or channel' ' privilege limit', }, } python-ipmi-0.4.2/pyipmi/msgs/sdr.py0000664000372000037200000001500613574451473020275 0ustar travistravis00000000000000# Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from __future__ import absolute_import from . import constants from . import register_message_class from . import Message from . import ByteArray from . import UnsignedInt from . import Timestamp from . import Bitfield from . import CompletionCode from . import RemainingBytes @register_message_class class GetSdrRepositoryInfoReq(Message): __cmdid__ = constants.CMDID_GET_SDR_REPOSITORY_INFO __netfn__ = constants.NETFN_STORAGE @register_message_class class GetSdrRepositoryInfoRsp(Message): __cmdid__ = constants.CMDID_GET_SDR_REPOSITORY_INFO __netfn__ = constants.NETFN_STORAGE | 1 __fields__ = ( CompletionCode(), UnsignedInt('sdr_version', 1), UnsignedInt('record_count', 2), UnsignedInt('free_space', 2), Timestamp('most_recent_addition'), Timestamp('most_recent_erase'), Bitfield('support', 1, Bitfield.Bit('get_allocation_info', 1), Bitfield.Bit('reserve', 1), Bitfield.Bit('partial_add', 1), Bitfield.Bit('delete', 1), Bitfield.ReservedBit(1, 0), Bitfield.Bit('update_type', 2), Bitfield.Bit('overflow_flag', 1)), ) @register_message_class class GetSdrRepositoryAllocationInfoReq(Message): __cmdid__ = constants.CMDID_GET_SDR_REPOSITORY_ALLOCATION_INFO __netfn__ = constants.NETFN_STORAGE @register_message_class class GetSdrRepositoryAllocationInfoRsp(Message): __cmdid__ = constants.CMDID_GET_SDR_REPOSITORY_ALLOCATION_INFO __netfn__ = constants.NETFN_STORAGE | 1 __fields__ = ( CompletionCode(), UnsignedInt('number_of_units', 2), UnsignedInt('unit_size', 2), UnsignedInt('free_units', 2), UnsignedInt('largest_free_block', 2), UnsignedInt('maximum_record_size', 1) ) @register_message_class class ReserveSdrRepositoryReq(Message): __cmdid__ = constants.CMDID_RESERVE_SDR_REPOSITORY __netfn__ = constants.NETFN_STORAGE @register_message_class class ReserveSdrRepositoryRsp(Message): __cmdid__ = constants.CMDID_RESERVE_SDR_REPOSITORY __netfn__ = constants.NETFN_STORAGE | 1 __fields__ = ( CompletionCode(), UnsignedInt('reservation_id', 2), ) @register_message_class class GetSdrReq(Message): __cmdid__ = constants.CMDID_GET_SDR __netfn__ = constants.NETFN_STORAGE __fields__ = ( UnsignedInt('reservation_id', 2), UnsignedInt('record_id', 2), UnsignedInt('offset', 1), UnsignedInt('bytes_to_read', 1), ) @register_message_class class GetSdrRsp(Message): __cmdid__ = constants.CMDID_GET_SDR __netfn__ = constants.NETFN_STORAGE | 1 __fields__ = ( CompletionCode(), UnsignedInt('next_record_id', 2), RemainingBytes('record_data'), ) @register_message_class class AddSdrReq(Message): __cmdid__ = constants.CMDID_ADD_SDR __netfn__ = constants.NETFN_STORAGE __fields__ = ( RemainingBytes('record_data'), ) @register_message_class class AddSdrRsp(Message): __cmdid__ = constants.CMDID_ADD_SDR __netfn__ = constants.NETFN_STORAGE | 1 __fields__ = ( CompletionCode(), UnsignedInt('record_id', 2), ) @register_message_class class PartialAddSdrReq(Message): __cmdid__ = constants.CMDID_PARTIAL_ADD_SDR __netfn__ = constants.NETFN_STORAGE __fields__ = ( UnsignedInt('reservation_id', 2), UnsignedInt('record_id', 2), UnsignedInt('offset', 1), Bitfield('status', 1, Bitfield.Bit('in_progress', 4), Bitfield.ReservedBit(4, 0),), RemainingBytes('record_data'), ) @register_message_class class PartialAddSdrRsp(Message): __cmdid__ = constants.CMDID_PARTIAL_ADD_SDR __netfn__ = constants.NETFN_STORAGE | 1 __fields__ = ( CompletionCode(), UnsignedInt('record_id', 2), ) @register_message_class class DeleteSdrReq(Message): __cmdid__ = constants.CMDID_DELETE_SDR __netfn__ = constants.NETFN_STORAGE __fields__ = ( UnsignedInt('reservation_id', 2), UnsignedInt('record_id', 2), ) @register_message_class class DeleteSdrRsp(Message): __cmdid__ = constants.CMDID_DELETE_SDR __netfn__ = constants.NETFN_STORAGE | 1 __fields__ = ( CompletionCode(), UnsignedInt('record_id', 2), ) @register_message_class class ClearSdrRepositoryReq(Message): __cmdid__ = constants.CMDID_CLEAR_SDR_REPOSITORY __netfn__ = constants.NETFN_STORAGE __fields__ = ( UnsignedInt('reservation_id', 2), ByteArray('key', 3, default=b'CLR'), UnsignedInt('cmd', 1) ) @register_message_class class ClearSdrRepositoryRsp(Message): __cmdid__ = constants.CMDID_CLEAR_SDR_REPOSITORY __netfn__ = constants.NETFN_STORAGE | 1 __fields__ = ( CompletionCode(), Bitfield('status', 1, Bitfield.Bit('erase_in_progress', 4), Bitfield.ReservedBit(4, 0),), ) @register_message_class class RunInitializationAgentReq(Message): __cmdid__ = constants.CMDID_RUN_INITIALIZATION_AGENT __netfn__ = constants.NETFN_STORAGE __fields__ = ( UnsignedInt('cmd', 1), ) @register_message_class class RunInitializationAgentRsp(Message): __cmdid__ = constants.CMDID_RUN_INITIALIZATION_AGENT __netfn__ = constants.NETFN_STORAGE | 1 __fields__ = ( CompletionCode(), Bitfield('status', 1, Bitfield.Bit('initialization_completed', 1), Bitfield.ReservedBit(7, 0),), ) python-ipmi-0.4.2/pyipmi/msgs/message.py0000664000372000037200000002731013574451473021132 0ustar travistravis00000000000000# Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from __future__ import absolute_import from array import array from . import constants from ..utils import ByteBuffer from ..errors import (CompletionCodeError, EncodingError, DecodingError, DescriptionError) class BaseField(object): def __init__(self, name, length, default=None): self.name = name self.length = length self.default = default def decode(self, obj, data): raise NotImplementedError() def encode(self, obj, data): if getattr(obj, self.name) is None: raise EncodingError('Field "%s" not set.' % self.name) raise NotImplementedError() def create(self): raise NotImplementedError() class ByteArray(BaseField): def __init__(self, name, length, default=None): BaseField.__init__(self, name, length) if default is not None: self.default = array('B', default) else: self.default = None def _length(self, obj): return self.length def encode(self, obj, data): a = getattr(obj, self.name) if len(a) != self._length(obj): raise EncodingError('Array must be exaclty %d bytes long ' '(but is %d long)' % (self._length(obj), len(a))) for i in range(self._length(obj)): data.push_unsigned_int(a[i], 1) def decode(self, obj, data): bytes = [] for i in range(self._length(obj)): bytes.append(data.pop_unsigned_int(1)) setattr(obj, self.name, array('B', bytes)) def create(self): if self.default is not None: return array('B', self.default) else: return array('B', self.length * '\x00') class VariableByteArray(ByteArray): """Array of bytes with variable length. The length is dynamically computed by a function. """ def __init__(self, name, length_func): ByteArray.__init__(self, name, None, None) self._length_func = length_func def _length(self, obj): return self._length_func(obj) def create(self): return None class UnsignedInt(BaseField): def encode(self, obj, data): value = getattr(obj, self.name) data.push_unsigned_int(value, self.length) def decode(self, obj, data): value = data.pop_unsigned_int(self.length) setattr(obj, self.name, value) def create(self): if self.default is not None: return self.default else: return 0 class String(BaseField): def encode(self, obj, data): value = getattr(obj, self.name) data.push_string(value) def decode(self, obj, data): value = data.pop_string(self.length) setattr(obj, self.name, value) def create(self): if self.default is not None: return self.default else: return '' class CompletionCode(UnsignedInt): def __init__(self, name='completion_code'): UnsignedInt.__init__(self, name, 1, None) def decode(self, obj, data): UnsignedInt.decode(self, obj, data) cc = getattr(obj, self.name) if cc != constants.CC_OK: raise CompletionCodeError(cc) class UnsignedIntMask(UnsignedInt): def __init__(self, name, length, mask, default=None): UnsignedInt.__init__(self, name, length, default) class Timestamp(UnsignedInt): def __init__(self, name): UnsignedInt.__init__(self, name, 4, None) class Conditional(object): def __init__(self, cond_fn, field): self._condition_fn = cond_fn self._field = field def __getattr__(self, name): return getattr(self._field, name) def encode(self, obj, data): if self._condition_fn(obj): self._field.encode(obj, data) def decode(self, obj, data): if self._condition_fn(obj): self._field.decode(obj, data) def create(self): return self._field.create() class Optional(object): def __init__(self, field): self._field = field def __getattr__(self, name): return getattr(self._field, name) def decode(self, obj, data): if len(data) > 0: self._field.decode(obj, data) else: setattr(obj, self._field.name, None) def encode(self, obj, data): if getattr(obj, self._field.name) is not None: self._field.encode(obj, data) def create(self): return None class RemainingBytes(BaseField): def __init__(self, name): BaseField.__init__(self, name, None) def encode(self, obj, data): a = getattr(obj, self.name) data.extend(a) def decode(self, obj, data): setattr(obj, self.name, array('B', data[:])) del data.array[:] def create(self): return array('B') class Bitfield(BaseField): class Bit(object): def __init__(self, name, width=1, default=None): self.name = name self._width = width self.default = default class ReservedBit(Bit): counter = 0 def __init__(self, width, default=0): Bitfield.Bit.__init__(self, 'reserved_bit_%d' % Bitfield.reserved_bit_counter, width, default) Bitfield.reserved_bit_counter += 1 class BitWrapper(object): def __init__(self, bits, length): self._bits = bits self._length = length for bit in bits: if hasattr(self, bit.name): raise DescriptionError('Bit with name "%s" already added' % bit.name) if bit.default is not None: setattr(self, bit.name, bit.default) else: setattr(self, bit.name, 0) def __str__(self): s = '[' for attr in dir(self): if attr.startswith('_'): continue s += '%s=%s, ' % (attr, getattr(self, attr)) s += ']' return s def __int__(self): return self._value def _get_value(self): value = 0 for bit in self._bits: bit_value = getattr(self, bit.name) if bit_value is None: bit_value = bit.default if bit_value is None: raise EncodingError('Bitfield "%s" not set.' % bit.name) value |= (bit_value & (2**bit._width - 1)) << bit.offset return value def _set_value(self, value): for bit in self._bits: tmp = (value >> bit.offset) & (2**bit._width - 1) setattr(self, bit.name, tmp) _value = property(_get_value, _set_value) reserved_bit_counter = 0 def __init__(self, name, length, *bits): BaseField.__init__(self, name, length) self._bits = bits self._precalc_offsets() def _precalc_offsets(self): offset = 0 for b in self._bits: b.offset = offset offset += b._width if offset != 8 * self.length: raise DescriptionError('Bit description does not match bitfield ' 'length') def encode(self, obj, data): wrapper = getattr(obj, self.name) value = wrapper._value for i in range(self.length): data.push_unsigned_int((value >> (8*i)) & 0xff, 1) def decode(self, obj, data): value = 0 for i in range(self.length): try: value |= data.pop_unsigned_int(1) << (8*i) except IndexError: raise DecodingError('Data too short for message') wrapper = getattr(obj, self.name) wrapper._value = value def create(self): return Bitfield.BitWrapper(self._bits, self.length) class GroupExtensionIdentifier(UnsignedInt): def __init__(self, name='picmg_identifier', value=None): UnsignedInt.__init__(self, name, 1, value) class Message(object): RESERVED_FIELD_NAMES = ['cmdid', 'netfn', 'lun', 'group_extension'] __default_lun__ = 0 __group_extension__ = None __not_implemented__ = False def __init__(self, *args, **kwargs): """Message constructor with ([buf], [field=val,...]) prototype. Arguments: buf -- option message buffer to decode Optional keyword arguments corresponts to members to set (matching fields in self.__fields__, or 'data'). """ # create message fields if hasattr(self, '__fields__'): self._create_fields() # set default lun self.lun = self.__default_lun__ self.data = '' if args: self._decode(args[0]) else: for (name, value) in kwargs.items(): self._set_field(name, value) def _set_field(self, name, value): raise NotImplementedError() # TODO walk along the properties.. def _create_fields(self): for field in self.__fields__: if field.name in self.RESERVED_FIELD_NAMES: raise DescriptionError('Field name "%s" is reserved' % field.name) if hasattr(self, field.name): raise DescriptionError('Field "%s" already added', field.name) setattr(self, field.name, field.create()) def _pack(self): """Pack the message and return an array.""" data = ByteBuffer() if not hasattr(self, '__fields__'): return data.array for field in self.__fields__: field.encode(self, data) return data.array def _encode(self): """Encode the message and return a bytestring.""" data = ByteBuffer() if not hasattr(self, '__fields__'): return data.tostring() for field in self.__fields__: field.encode(self, data) return data.tostring() def _decode(self, data): """Decode the bytestring message.""" if not hasattr(self, '__fields__'): raise NotImplementedError('You have to overwrite this method') data = ByteBuffer(data) cc = None for field in self.__fields__: try: field.decode(self, data) except CompletionCodeError as e: # stop decoding on completion code != 0 cc = e.cc break if (cc is None or cc == 0) and len(data) > 0: raise DecodingError('Data has extra bytes') def _is_request(self): return self.__netfn__ & 1 == 0 def _is_response(self): return self.__netfn__ & 1 == 1 netfn = property(lambda s: s.__netfn__) cmdid = property(lambda s: s.__cmdid__) group_extension = property(lambda s: s.__group_extension__) encode_message = lambda m: m._encode() decode_message = lambda m, d: m._decode(d) pack_message = lambda m: m._pack() python-ipmi-0.4.2/pyipmi/msgs/device_messaging.py0000664000372000037200000002772713574451473023016 0ustar travistravis00000000000000# Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from . import constants from . import register_message_class from . import Message from . import UnsignedInt from . import Bitfield from . import String from . import CompletionCode from . import RemainingBytes @register_message_class class SetBmcGlobalEnablesReq(Message): __cmdid__ = constants.CMDID_SET_BMC_GLOBAL_ENABLES __netfn__ = constants.NETFN_APP __fields__ = ( Bitfield('enables', 1, Bitfield.Bit('receive_message_queue_interrupt', 1, 0), Bitfield.Bit('event_message_buffer_full_interrupt', 1, 0), Bitfield.Bit('event_message_buffer', 1, 0), Bitfield.Bit('system_event_logging', 1, 0), Bitfield.ReservedBit(1, 0), Bitfield.Bit('oem_0', 1, 0), Bitfield.Bit('oem_1', 1, 0), Bitfield.Bit('oem_2', 1, 0),), ) @register_message_class class SetBmcGlobalEnablesRsp(Message): __cmdid__ = constants.CMDID_SET_BMC_GLOBAL_ENABLES __netfn__ = constants.NETFN_APP | 1 __fields__ = ( CompletionCode(), ) @register_message_class class GetBmcGlobalEnablesReq(Message): __cmdid__ = constants.CMDID_GET_BMC_GLOBAL_ENABLES __netfn__ = constants.NETFN_APP @register_message_class class GetBmcGlobalEnablesRsp(Message): __cmdid__ = constants.CMDID_GET_BMC_GLOBAL_ENABLES __netfn__ = constants.NETFN_APP | 1 __fields__ = ( CompletionCode(), Bitfield('enables', 1, Bitfield.Bit('receive_message_queue_interrupt', 1, 0), Bitfield.Bit('event_message_buffer_full_interrupt', 1, 0), Bitfield.Bit('event_message_buffer', 1, 0), Bitfield.Bit('system_event_logging', 1, 0), Bitfield.ReservedBit(1, 0), Bitfield.Bit('oem_0', 1, 0), Bitfield.Bit('oem_1', 1, 0), Bitfield.Bit('oem_2', 1, 0),), ) @register_message_class class ClearMessageFlagsReq(Message): __cmdid__ = constants.CMDID_CLEAR_MESSAGE_FLAGS __netfn__ = constants.NETFN_APP __fields__ = ( Bitfield('clear', 1, Bitfield.Bit('receive_message_queue', 1, 0), Bitfield.Bit('event_message_buffer', 1, 0), Bitfield.ReservedBit(1, 0), Bitfield.Bit('watchdog_pretimeout_interrupt_flag', 1, 0), Bitfield.ReservedBit(1, 0), Bitfield.Bit('oem_0', 1, 0), Bitfield.Bit('oem_1', 1, 0), Bitfield.Bit('oem_2', 1, 0),), ) @register_message_class class ClearMessageFlagsRsp(Message): __cmdid__ = constants.CMDID_CLEAR_MESSAGE_FLAGS __netfn__ = constants.NETFN_APP | 1 __fields__ = ( CompletionCode(), ) @register_message_class class GetMessageFlagsReq(Message): __cmdid__ = constants.CMDID_GET_MESSAGE_FLAGS __netfn__ = constants.NETFN_APP @register_message_class class GetMessageFlagsRsp(Message): __cmdid__ = constants.CMDID_GET_MESSAGE_FLAGS __netfn__ = constants.NETFN_APP | 1 __fields__ = ( CompletionCode(), Bitfield('flag', 1, Bitfield.Bit('receive_message_available', 1, 0), Bitfield.Bit('event_message_buffer_full', 1, 0), Bitfield.ReservedBit(1, 0), Bitfield.Bit('watchdog_pretimeout_interrupt_occurred', 1, 0), Bitfield.ReservedBit(1, 0), Bitfield.Bit('oem_0', 1, 0), Bitfield.Bit('oem_1', 1, 0), Bitfield.Bit('oem_2', 1, 0),), ) @register_message_class class EnableMessageChannelReceiveReq(Message): __cmdid__ = constants.CMDID_ENABLE_MESSAGE_CHANNEL_RECEIVE __netfn__ = constants.NETFN_APP __fields__ = ( Bitfield('channel', 2, Bitfield.Bit('number', 4, 0), Bitfield.ReservedBit(4, 0), Bitfield.Bit('state', 2, 0), Bitfield.ReservedBit(6, 0),), ) @register_message_class class EnableMessageChannelReceiveRsp(Message): __cmdid__ = constants.CMDID_ENABLE_MESSAGE_CHANNEL_RECEIVE __netfn__ = constants.NETFN_APP | 1 __fields__ = ( CompletionCode(), Bitfield('channel', 2, Bitfield.Bit('number', 4, 0), Bitfield.ReservedBit(4, 0), Bitfield.Bit('state', 1, 0), Bitfield.ReservedBit(7, 0),), ) @register_message_class class GetMessageReq(Message): __cmdid__ = constants.CMDID_GET_MESSAGE __netfn__ = constants.NETFN_APP @register_message_class class GetMessageRsp(Message): __cmdid__ = constants.CMDID_GET_MESSAGE __netfn__ = constants.NETFN_APP | 1 __fields__ = ( CompletionCode(), Bitfield('channel', 1, Bitfield.Bit('number', 4, 0), Bitfield.Bit('privilege_level', 4, 0),), RemainingBytes('data'), ) @register_message_class class SendMessageReq(Message): __cmdid__ = constants.CMDID_SEND_MESSAGE __netfn__ = constants.NETFN_APP __fields__ = ( Bitfield('channel', 1, Bitfield.Bit('number', 4, 0), Bitfield.Bit('authenticated', 1, 0), Bitfield.Bit('encrypted', 1, 0), Bitfield.Bit('tracking', 2, 0),), ) @register_message_class class SendMessageRsp(Message): __cmdid__ = constants.CMDID_SEND_MESSAGE __netfn__ = constants.NETFN_APP | 1 __fields__ = ( CompletionCode(), RemainingBytes('data'), ) @register_message_class class ReadEventMessageBufferReq(Message): __cmdid__ = constants.CMDID_READ_EVENT_MESSAGE_BUFFER __netfn__ = constants.NETFN_APP @register_message_class class ReadEventMessageBufferRsp(Message): __cmdid__ = constants.CMDID_READ_EVENT_MESSAGE_BUFFER __netfn__ = constants.NETFN_APP | 1 __fields__ = ( CompletionCode(), RemainingBytes('event_data'), ) @register_message_class class MasterWriteReadReq(Message): __cmdid__ = constants.CMDID_MASTER_WRITE_READ __netfn__ = constants.NETFN_APP __fields__ = ( Bitfield('bus_id', 2, Bitfield.Bit('type', 1, 0), Bitfield.Bit('id', 3, 0), Bitfield.Bit('channel', 4, 0), Bitfield.ReservedBit(1, 0), Bitfield.Bit('slave_address', 7, 0),), UnsignedInt('read_count', 1), RemainingBytes('data'), ) @register_message_class class MasterWriteReadRsp(Message): __cmdid__ = constants.CMDID_MASTER_WRITE_READ __netfn__ = constants.NETFN_APP | 1 __fields__ = ( CompletionCode(), RemainingBytes('data'), ) @register_message_class class GetChannelAuthenticationCapabilitiesReq(Message): __cmdid__ = constants.CMDID_GET_CHANNEL_AUTHENTICATION_CAPABILITIES __netfn__ = constants.NETFN_APP __fields__ = ( Bitfield('channel', 1, Bitfield.Bit('number', 4, 0), Bitfield.ReservedBit(3, 0), Bitfield.Bit('type', 1, 0),), Bitfield('privilege_level', 1, Bitfield.Bit('requested', 4, 0), Bitfield.ReservedBit(4, 0),), ) @register_message_class class GetChannelAuthenticationCapabilitiesRsp(Message): __cmdid__ = constants.CMDID_GET_CHANNEL_AUTHENTICATION_CAPABILITIES __netfn__ = constants.NETFN_APP | 1 __fields__ = ( CompletionCode(), UnsignedInt('channel_number', 1), Bitfield('support', 1, Bitfield.Bit('none', 1, 0), Bitfield.Bit('md2', 1, 0), Bitfield.Bit('md5', 1, 0), Bitfield.ReservedBit(1, 0), Bitfield.Bit('straight', 1, 0), Bitfield.Bit('oem_proprietary', 1, 0), Bitfield.ReservedBit(1, 0), Bitfield.Bit('ipmi_2_0', 1, 0),), Bitfield('status', 1, Bitfield.Bit('anonymous_login_enabled', 1, 0), Bitfield.Bit('anonymous_login_null_user', 1, 0), Bitfield.Bit('anonymous_login_non_null', 1, 0), Bitfield.Bit('user_level', 1, 0), Bitfield.Bit('per_message', 1, 0), Bitfield.Bit('kg', 1, 0), Bitfield.ReservedBit(2, 0),), Bitfield('extended_capabilities', 1, Bitfield.Bit('1_5', 1, 0), Bitfield.Bit('2_0', 1, 0), Bitfield.ReservedBit(6, 0),), UnsignedInt('oem_id', 3), UnsignedInt('oem_auxiliary_data', 1), ) @register_message_class class GetSessionChallengeReq(Message): __cmdid__ = constants.CMDID_GET_SESSION_CHALLENGE __netfn__ = constants.NETFN_APP __fields__ = ( Bitfield('authentication', 1, Bitfield.Bit('type', 4, 0), Bitfield.ReservedBit(4, 0),), String('user_name', 16, '\x00' * 16), ) @register_message_class class GetSessionChallengeRsp(Message): __cmdid__ = constants.CMDID_GET_SESSION_CHALLENGE __netfn__ = constants.NETFN_APP | 1 __fields__ = ( CompletionCode(), UnsignedInt('temporary_session_id', 4), String('challenge_string', 16, 0), ) @register_message_class class ActivateSessionReq(Message): __cmdid__ = constants.CMDID_ACTIVATE_SESSION __netfn__ = constants.NETFN_APP __fields__ = ( Bitfield('authentication', 1, Bitfield.Bit('type', 4, 0), Bitfield.ReservedBit(4, 0),), Bitfield('privilege_level', 1, Bitfield.Bit('maximum_requested', 4, 0), Bitfield.ReservedBit(4, 0),), String('challenge_string', 16), UnsignedInt('initial_outbound_sequence_number', 4), ) @register_message_class class ActivateSessionRsp(Message): __cmdid__ = constants.CMDID_ACTIVATE_SESSION __netfn__ = constants.NETFN_APP | 1 __fields__ = ( CompletionCode(), Bitfield('authentication', 1, Bitfield.Bit('type', 4, 0), Bitfield.ReservedBit(4, 0),), UnsignedInt('session_id', 4), UnsignedInt('initial_inbound_sequence_number', 4), Bitfield('privilege_level', 1, Bitfield.Bit('maximum_allowed', 4, 0), Bitfield.ReservedBit(4, 0),), ) @register_message_class class SetSessionPrivilegeLevelReq(Message): __cmdid__ = constants.CMDID_SET_SESSION_PRIVILEGE_LEVEL __netfn__ = constants.NETFN_APP __fields__ = ( Bitfield('privilege_level', 1, Bitfield.Bit('requested', 4, 0), Bitfield.ReservedBit(4, 0),), ) @register_message_class class SetSessionPrivilegeLevelRsp(Message): __cmdid__ = constants.CMDID_SET_SESSION_PRIVILEGE_LEVEL __netfn__ = constants.NETFN_APP | 1 __fields__ = ( CompletionCode(), Bitfield('privilege_level', 1, Bitfield.Bit('new', 4, 0), Bitfield.ReservedBit(4, 0),), ) @register_message_class class CloseSessionReq(Message): __cmdid__ = constants.CMDID_CLOSE_SESSION __netfn__ = constants.NETFN_APP __fields__ = ( UnsignedInt('session_id', 4), ) @register_message_class class CloseSessionRsp(Message): __cmdid__ = constants.CMDID_CLOSE_SESSION __netfn__ = constants.NETFN_APP | 1 __fields__ = ( CompletionCode(), ) python-ipmi-0.4.2/pyipmi/msgs/fru.py0000664000372000037200000000531413574451473020302 0ustar travistravis00000000000000from __future__ import absolute_import # Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from . import constants from . import register_message_class from . import Message from . import UnsignedInt from . import Bitfield from . import CompletionCode from . import RemainingBytes from . import VariableByteArray @register_message_class class GetFruInventoryAreaInfoReq(Message): __cmdid__ = constants.CMDID_GET_FRU_INVENTORY_AREA_INFO __netfn__ = constants.NETFN_STORAGE __fields__ = ( UnsignedInt('fru_id', 1, 0), ) @register_message_class class GetFruInventoryAreaInfoRsp(Message): __cmdid__ = constants.CMDID_GET_FRU_INVENTORY_AREA_INFO __netfn__ = constants.NETFN_STORAGE | 1 __fields__ = ( CompletionCode(), UnsignedInt('area_size', 2), Bitfield('area_info', 1, Bitfield.Bit('access', 1), Bitfield.ReservedBit(7, 0)), ) @register_message_class class ReadFruDataReq(Message): __cmdid__ = constants.CMDID_READ_FRU_DATA __netfn__ = constants.NETFN_STORAGE __fields__ = ( UnsignedInt('fru_id', 1), UnsignedInt('offset', 2), UnsignedInt('count', 1), ) @register_message_class class ReadFruDataRsp(Message): __cmdid__ = constants.CMDID_READ_FRU_DATA __netfn__ = constants.NETFN_STORAGE | 1 def _length_count(obj): return obj.count __fields__ = ( CompletionCode(), UnsignedInt('count', 1), VariableByteArray('data', _length_count), ) @register_message_class class WriteFruDataReq(Message): __cmdid__ = constants.CMDID_WRITE_FRU_DATA __netfn__ = constants.NETFN_STORAGE __fields__ = ( UnsignedInt('fru_id', 1), UnsignedInt('offset', 2), RemainingBytes('data'), ) @register_message_class class WriteFruDataRsp(Message): __cmdid__ = constants.CMDID_WRITE_FRU_DATA __netfn__ = constants.NETFN_STORAGE | 1 __fields__ = ( CompletionCode(), UnsignedInt('count_written', 1) ) python-ipmi-0.4.2/pyipmi/msgs/event.py0000664000372000037200000000421313574451473020624 0ustar travistravis00000000000000from __future__ import absolute_import # Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from . import constants from . import register_message_class from . import Message from . import Bitfield from . import CompletionCode @register_message_class class SetEventReceiverReq(Message): __cmdid__ = constants.CMDID_SET_EVENT_RECEIVER __netfn__ = constants.NETFN_SENSOR_EVENT __fields__ = ( Bitfield('event_receiver', 2, Bitfield.ReservedBit(1, 0), Bitfield.Bit('ipmb_i2c_slave_address', 7, 0), Bitfield.Bit('lun', 2, 0), Bitfield.ReservedBit(6, 0),), ) @register_message_class class SetEventReceiverRsp(Message): __cmdid__ = constants.CMDID_SET_EVENT_RECEIVER __netfn__ = constants.NETFN_SENSOR_EVENT | 1 __fields__ = ( CompletionCode(), ) @register_message_class class GetEventReceiverReq(Message): __cmdid__ = constants.CMDID_GET_EVENT_RECEIVER __netfn__ = constants.NETFN_SENSOR_EVENT @register_message_class class GetEventReceiverRsp(Message): __cmdid__ = constants.CMDID_GET_EVENT_RECEIVER __netfn__ = constants.NETFN_SENSOR_EVENT | 1 __fields__ = ( CompletionCode(), Bitfield('event_receiver', 2, Bitfield.ReservedBit(1, 0), Bitfield.Bit('ipmb_i2c_slave_address', 7, 0), Bitfield.Bit('lun', 2, 0), Bitfield.ReservedBit(6, 0),), ) python-ipmi-0.4.2/pyipmi/msgs/picmg.py0000664000372000037200000005765513574451473020624 0ustar travistravis00000000000000# Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from __future__ import absolute_import from . import constants from . import register_message_class from . import Message from . import UnsignedInt from . import UnsignedIntMask from . import Bitfield from . import CompletionCode from . import Conditional from . import RemainingBytes from . import Optional from . import GroupExtensionIdentifier PICMG_IDENTIFIER = 0x00 FRU_ACTIVATION_FRU_ACTIVATE = 0x1 FRU_ACTIVATION_FRU_DEACTIVATE = 0x0 LINK_INTERFACE_BASE = 0x0 LINK_INTERFACE_FABRIC = 0x1 LINK_INTERFACE_UPDATE_CHANNEL = 0x2 LINK_TYPE_BASE = 0x01 LINK_TYPE_ETHERNET_FABRIC = 0x02 LINK_TYPE_INFINIBAND_FABRIC = 0x03 LINK_TYPE_STARFABRIC_FABRIC = 0x04 LINK_TYPE_PCIEXPRESS_FABRIC = 0x05 LINK_TYPE_OEM0 = 0xf0 LINK_TYPE_OEM1 = 0xf1 LINK_TYPE_OEM2 = 0xf2 LINK_TYPE_OEM3 = 0xf3 LINK_TYPE_EXT_BASE0 = 0x00 LINK_TYPE_EXT_BASE1 = 0x01 LINK_SIGNALING_CLASS_BASIC = 0 LINK_SIGNALING_CLASS_10_3125_GBD = 3 # when link signaling class value is 0000b LINK_TYPE_EXT_ETHERNET_FIX1000_BX = 0x0 LINK_TYPE_EXT_ETHERNET_FIX10G_BX4 = 0x1 LINK_TYPE_EXT_ETHERNET_FCPI = 0x02 LINK_TYPE_EXT_ETHERNET_FIX1000_KX = 0x3 LINK_TYPE_EXT_ETHERNET_FIX10G_KX4 = 0x4 # when link signaling class value is 0011b LINK_TYPE_EXT_ETHERNET_FIX10G_KR = 0x0 LINK_TYPE_EXT_ETHERNET_FIX40G_KR4 = 0x1 LINK_TYPE_EXT_OEM_LINK_TYPE_EXT_0 = 0x00 LINK_FLAGS_LANE0 = 0x01 LINK_FLAGS_LANE0123 = 0x0f LINK_STATE_DISABLE = 0 LINK_STATE_ENABLE = 1 FRU_CONTROL_COLD_RESET = 0x00 FRU_CONTROL_WARM_RESET = 0x01 FRU_CONTROL_GRACEFUL_REBOOT = 0x02 FRU_CONTROL_ISSUE_DIAGNOSTIC_INTERRUPT = 0x03 FRU_CONTROL_QUIESCED = 0x04 LED_COLOR_BLUE = 0x01 LED_COLOR_RED = 0x02 LED_COLOR_GREEN = 0x03 LED_COLOR_AMBER = 0x04 LED_COLOR_ORANGE = 0x05 LED_COLOR_WHITE = 0x06 LED_FUNCTION_OFF = 0x00 LED_FUNCTION_BLINKING_RANGE = list(range(0x01, 0xfa)) LED_FUNCTION_LAMP_TEST = 0xfb LED_FUNCTION_ON = 0xff LED_STATE_LOCAL_CONTROL = 0 LED_STATE_OVERRIDE = 1 LED_STATE_LAMP_TEST = 2 class PicmgIdentifier(UnsignedInt): def __init__(self, name='picmg_identifier'): super(PicmgIdentifier, self).__init__(name, 1, PICMG_IDENTIFIER) class PicmgMessage(Message): __group_extension__ = PICMG_IDENTIFIER @register_message_class class GetPicmgPropertiesReq(PicmgMessage): __cmdid__ = constants.CMDID_GET_PICMG_PROPERTIES __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), ) @register_message_class class GetPicmgPropertiesRsp(PicmgMessage): __cmdid__ = constants.CMDID_GET_PICMG_PROPERTIES __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('extension_version', 1), UnsignedInt('max_fru_device_id', 1), UnsignedInt('fru_device_id', 1), ) @register_message_class class GetAddressInfoReq(PicmgMessage): __cmdid__ = constants.CMDID_GET_ADDRESS_INFO __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('fru_id', 1), ) @register_message_class class GetAddressInfoRsp(PicmgMessage): __cmdid__ = constants.CMDID_GET_ADDRESS_INFO __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('hardware_address', 1), UnsignedInt('ipmb_0_address', 1), UnsignedInt('ipmb_1_address', 1), Optional( UnsignedInt('fru_id', 1), ), Optional( UnsignedInt('site_id', 1), ), Optional( UnsignedInt('site_type', 1), ), Optional( UnsignedInt('carrier_number', 1), ), ) @register_message_class class GetShelfAddressInfoReq(PicmgMessage): __cmdid__ = constants.CMDID_GET_SHELF_ADDRESS_INFO __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), ) @register_message_class class GetShelfAddressInfoRsp(PicmgMessage): __cmdid__ = constants.CMDID_GET_SHELF_ADDRESS_INFO __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), RemainingBytes('shelf_address'), ) @register_message_class class FruControlReq(PicmgMessage): __cmdid__ = constants.CMDID_FRU_CONTROL __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('fru_id', 1), UnsignedInt('option', 1), ) @register_message_class class FruControlRsp(PicmgMessage): __cmdid__ = constants.CMDID_FRU_CONTROL __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), RemainingBytes('rsp_data'), ) @register_message_class class GetFruControlCapabilitiesReq(PicmgMessage): __cmdid__ = constants.CMDID_FRU_CONTROL_CAPABILITIES __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('fru_id', 1), ) @register_message_class class GetFruControlCapabilitiesRsp(PicmgMessage): __cmdid__ = constants.CMDID_FRU_CONTROL_CAPABILITIES __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), Bitfield('capabilities', 1, Bitfield.ReservedBit(1), Bitfield.Bit('warm_reset', 1), Bitfield.Bit('graceful_reboot', 1), Bitfield.Bit('diagnostic_interrupt', 1), Bitfield.ReservedBit(4),), ) @register_message_class class SetFruActivationPolicyReq(PicmgMessage): __cmdid__ = constants.CMDID_SET_FRU_ACTIVATION_POLICY __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('fru_id', 1), Bitfield('mask', 1, Bitfield.Bit('activation_locked', 1, default=0), Bitfield.Bit('deactivation_locked', 1, default=0), Bitfield.ReservedBit(6),), Bitfield('set', 1, Bitfield.Bit('activation_locked', 1, default=0), Bitfield.Bit('deactivation_locked', 1, default=0), Bitfield.ReservedBit(6),), ) @register_message_class class SetFruActivationPolicyRsp(PicmgMessage): __cmdid__ = constants.CMDID_SET_FRU_ACTIVATION_POLICY __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), ) @register_message_class class GetFruActivationPolicyReq(PicmgMessage): __cmdid__ = constants.CMDID_GET_FRU_ACTIVATION_POLICY __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('fru_id', 1), ) @register_message_class class GetFruActivationPolicyRsp(PicmgMessage): __cmdid__ = constants.CMDID_GET_FRU_ACTIVATION_POLICY __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), Bitfield('policy', 1, Bitfield.Bit('activation_locked', 1, default=0), Bitfield.Bit('deactivation_locked', 1, default=0), Bitfield.ReservedBit(6),), ) @register_message_class class SetFruActivationReq(PicmgMessage): __cmdid__ = constants.CMDID_SET_FRU_ACTIVATION __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('fru_id', 1), UnsignedInt('control', 1), ) @register_message_class class SetFruActivationRsp(PicmgMessage): __cmdid__ = constants.CMDID_SET_FRU_ACTIVATION __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), ) @register_message_class class GetDeviceLocatorRecordIdReq(PicmgMessage): __cmdid__ = constants.CMDID_GET_DEVLOC_RECORD_ID __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('fru_id', 1), ) @register_message_class class GetDeviceLocatorRecordIdRsp(PicmgMessage): __cmdid__ = constants.CMDID_GET_DEVLOC_RECORD_ID __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('record_id', 2), ) @register_message_class class GetFruLedPropertiesReq(PicmgMessage): __cmdid__ = constants.CMDID_GET_FRU_LED_PROPERTIES __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('fru_id', 1), ) @register_message_class class GetFruLedPropertiesRsp(PicmgMessage): __cmdid__ = constants.CMDID_GET_FRU_LED_PROPERTIES __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), Bitfield('general_status_led_properties', 1, Bitfield.Bit('blue_led', 1), Bitfield.Bit('led1', 1), Bitfield.Bit('led2', 1), Bitfield.Bit('led3', 1), Bitfield.ReservedBit(4),), UnsignedInt('application_specific_led_count', 1), ) @register_message_class class GetFruLedColorCapabilitiesReq(PicmgMessage): __cmdid__ = constants.CMDID_GET_FRU_LED_COLOR_CAPABILITIES __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('fru_id', 1), UnsignedInt('led_id', 1), ) @register_message_class class GetFruLedColorCapabilitiesRsp(PicmgMessage): __cmdid__ = constants.CMDID_GET_FRU_LED_COLOR_CAPABILITIES __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), Bitfield('color_capabilities', 1, Bitfield.ReservedBit(1), Bitfield.Bit('blue', 1), Bitfield.Bit('red', 1), Bitfield.Bit('green', 1), Bitfield.Bit('amber', 1), Bitfield.Bit('orange', 1), Bitfield.Bit('white', 1), Bitfield.ReservedBit(1)), UnsignedIntMask('local_def_color', 1, 0x0f), UnsignedIntMask('override_def_color', 1, 0x0f), ) @register_message_class class GetPowerLevelReq(PicmgMessage): __cmdid__ = constants.CMDID_GET_POWER_LEVEL __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('fru_id', 1), UnsignedInt('power_type', 1), ) @register_message_class class GetPowerLevelRsp(PicmgMessage): __cmdid__ = constants.CMDID_GET_POWER_LEVEL __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), Bitfield('properties', 1, Bitfield.Bit('power_level', 5, 0), Bitfield.ReservedBit(2, 0), Bitfield.Bit('dynamic_power_configuration', 1, 0),), UnsignedInt('delay_to_stable_power', 1), UnsignedInt('power_multiplier', 1), RemainingBytes('power_draw'), ) @register_message_class class GetFanSpeedPropertiesReq(PicmgMessage): __cmdid__ = constants.CMDID_GET_FAN_SPEED_PROPERTIES __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('fru_id', 1), ) @register_message_class class GetFanSpeedPropertiesRsp(PicmgMessage): __cmdid__ = constants.CMDID_GET_FAN_SPEED_PROPERTIES __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('minimum_speed_level', 1), UnsignedInt('maximum_speed_level', 1), UnsignedInt('normal_operation_level', 1), Bitfield('properties', 1, Bitfield.ReservedBit(7, 0), Bitfield.Bit('local_control_supported', 1),), ) @register_message_class class SetFanLevelReq(PicmgMessage): __cmdid__ = constants.CMDID_SET_FAN_LEVEL __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('fru_id', 1), UnsignedInt('fan_level', 1), UnsignedInt('extra_byte', 1), ) @register_message_class class SetFanLevelRsp(PicmgMessage): __cmdid__ = constants.CMDID_SET_FAN_LEVEL __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), ) @register_message_class class GetFanLevelReq(PicmgMessage): __cmdid__ = constants.CMDID_GET_FAN_LEVEL __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('fru_id', 1), ) @register_message_class class GetFanLevelRsp(PicmgMessage): __cmdid__ = constants.CMDID_GET_FAN_LEVEL __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('override_fan_level', 1), Optional( RemainingBytes('data'), ) ) @register_message_class class SetFruLedStateReq(PicmgMessage): __cmdid__ = constants.CMDID_SET_FRU_LED_STATE __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('fru_id', 1), UnsignedInt('led_id', 1), UnsignedInt('led_function', 1), UnsignedInt('on_duration', 1), UnsignedIntMask('color', 1, 0x0f), ) @register_message_class class SetFruLedStateRsp(PicmgMessage): __cmdid__ = constants.CMDID_SET_FRU_LED_STATE __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), ) @register_message_class class GetFruLedStateReq(PicmgMessage): __cmdid__ = constants.CMDID_GET_FRU_LED_STATE __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('fru_id', 1), UnsignedInt('led_id', 1), ) @register_message_class class GetFruLedStateRsp(PicmgMessage): __cmdid__ = constants.CMDID_GET_FRU_LED_STATE __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 def _cond_override(obj): return (obj.led_states.override_en == 1 or obj.led_states.lamp_test_en == 1) def _cond_lamp_test(obj): return obj.led_states.lamp_test_en == 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), Bitfield('led_states', 1, Bitfield.Bit('local_avail', 1), Bitfield.Bit('override_en', 1), Bitfield.Bit('lamp_test_en', 1), Bitfield.ReservedBit(5)), UnsignedInt('local_function', 1), UnsignedInt('local_on_duration', 1), UnsignedIntMask('local_color', 1, 0x0f), Conditional(_cond_override, UnsignedInt('override_function', 1)), Conditional(_cond_override, UnsignedInt('override_on_duration', 1)), Conditional(_cond_override, UnsignedIntMask('override_color', 1, 0x0f)), Conditional(_cond_lamp_test, UnsignedIntMask('lamp_test_duration', 1, 0x7f)), ) @register_message_class class SetPortStateReq(PicmgMessage): __cmdid__ = constants.CMDID_SET_PORT_STATE __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), Bitfield('link_info', 4, Bitfield.Bit('channel', 6), Bitfield.Bit('interface', 2), Bitfield.Bit('port_0', 1), Bitfield.Bit('port_1', 1), Bitfield.Bit('port_2', 1), Bitfield.Bit('port_3', 1), Bitfield.Bit('type', 4), Bitfield.Bit('sig_class', 4, 0), Bitfield.Bit('type_extension', 4), Bitfield.Bit('grouping_id', 8, 0),), UnsignedInt('state', 1), ) @register_message_class class SetPortStateRsp(PicmgMessage): __cmdid__ = constants.CMDID_SET_PORT_STATE __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), ) @register_message_class class GetPortStateReq(PicmgMessage): __cmdid__ = constants.CMDID_GET_PORT_STATE __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), Bitfield('channel', 1, Bitfield.Bit('number', 6), Bitfield.Bit('interface', 2),), ) @register_message_class class GetPortStateRsp(PicmgMessage): __cmdid__ = constants.CMDID_GET_PORT_STATE __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), RemainingBytes('data'), ) @register_message_class class SetSignalingClassReq(PicmgMessage): __cmdid__ = constants.CMDID_SET_CHANNEL_SIGNALING_CLASS __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), Bitfield('channel_info', 1, Bitfield.Bit('channel_number', 6, 0), Bitfield.Bit('interface', 2, 0),), Bitfield('channel_signaling', 1, Bitfield.Bit('class_capability', 4, 0), Bitfield.ReservedBit(4)), ) @register_message_class class SetSignalingClassRsp(PicmgMessage): __cmdid__ = constants.CMDID_SET_CHANNEL_SIGNALING_CLASS __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), ) @register_message_class class GetSignalingClassReq(PicmgMessage): __cmdid__ = constants.CMDID_GET_CHANNEL_SIGNALING_CLASS __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), Bitfield('channel_info', 1, Bitfield.Bit('channel_number', 6, 0), Bitfield.Bit('interface', 2, 0),), ) @register_message_class class GetSignalingClassRsp(PicmgMessage): __cmdid__ = constants.CMDID_GET_CHANNEL_SIGNALING_CLASS __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), Bitfield('channel_info', 1, Bitfield.Bit('channel_number', 6, 0), Bitfield.Bit('interface', 2, 0),), Bitfield('channel_signaling', 1, Bitfield.Bit('class_capability', 4, 0), Bitfield.ReservedBit(4)), ) @register_message_class class GetLocationInformationReq(PicmgMessage): __cmdid__ = constants.CMDID_GET_LOCATION_INFO __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), Bitfield('info', 1, Bitfield.Bit('carrier_number', 5, 0), Bitfield.ReservedBit(1), Bitfield.Bit('mcs', 2, 0),), UnsignedInt('site_number', 1), UnsignedInt('site_type', 1), ) @register_message_class class GetLocationInformationRsp(PicmgMessage): __cmdid__ = constants.CMDID_GET_LOCATION_INFO __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('slot_number', 1), UnsignedInt('tier_number', 1), Bitfield('info', 1, Bitfield.ReservedBit(5), Bitfield.Bit('carrier_orientation', 1, 0), Bitfield.Bit('tier_number', 1, 0), Bitfield.Bit('slot_number', 1, 0),), UnsignedInt('origin_x', 2), UnsignedInt('origin_y', 2), ) @register_message_class class GetPowerChannelStatusReq(PicmgMessage): __cmdid__ = constants.CMDID_GET_POWER_CHANNEL_STATUS __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('starting_power_channel_number', 1), UnsignedInt('power_channel_count', 1), ) @register_message_class class GetPowerChannelStatusRsp(PicmgMessage): __cmdid__ = constants.CMDID_GET_POWER_CHANNEL_STATUS __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('max_power_channel_number', 1), Bitfield('global_status', 1, Bitfield.Bit('role', 1, 0), Bitfield.Bit('management_power_good', 1, 0), Bitfield.Bit('payload_power_good', 1, 0), Bitfield.Bit('unidentified_fault', 1, 0), Bitfield.ReservedBit(4),), RemainingBytes('data'), ) @register_message_class class GetTelcoAlarmCapabilityReq(PicmgMessage): __cmdid__ = constants.CMDID_GET_TELCO_ALARM_CAPABILITY __netfn__ = constants.NETFN_GROUP_EXTENSION __fields__ = ( GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), UnsignedInt('fru_id', 1), ) @register_message_class class GetTelcoAlarmCapabilityRsp(PicmgMessage): __cmdid__ = constants.CMDID_GET_TELCO_ALARM_CAPABILITY __netfn__ = constants.NETFN_GROUP_EXTENSION | 1 __fields__ = ( CompletionCode(), GroupExtensionIdentifier('picmg_identifier', PICMG_IDENTIFIER), Bitfield('alarm_capabilities', 1, Bitfield.Bit('critical_alarm', 1, 0), Bitfield.Bit('major_alarm', 1, 0), Bitfield.Bit('minor_alarm', 1, 0), Bitfield.Bit('power_alarm', 1, 0), Bitfield.Bit('test_alarm', 1, 0), Bitfield.Bit('autonomous_alarm_cutoff', 1, 0), Bitfield.Bit('autonomous_minor_reset', 1, 0), Bitfield.Bit('autonomous_majorreset', 1, 0),), ) python-ipmi-0.4.2/pyipmi/msgs/__init__.py0000664000372000037200000000343213574451473021244 0ustar travistravis00000000000000from __future__ import absolute_import # Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from .registry import register_message_class from .registry import create_request_by_name from .registry import create_response_by_name from .registry import create_message from .registry import create_response_message from .message import Message from .message import ByteArray from .message import VariableByteArray from .message import UnsignedInt from .message import UnsignedIntMask from .message import Timestamp from .message import Bitfield from .message import CompletionCode from .message import Conditional from .message import Optional from .message import RemainingBytes from .message import String from .message import GroupExtensionIdentifier from .message import encode_message from .message import decode_message from .message import pack_message from . import bmc from . import chassis from . import dcmi from . import device_messaging from . import fru from . import hpm from . import picmg from . import sdr from . import sel from . import sensor from . import event from . import lan python-ipmi-0.4.2/pyipmi/msgs/bmc.py0000664000372000037200000001765113574451473020256 0ustar travistravis00000000000000# Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from __future__ import absolute_import from . import constants from . import register_message_class from . import Message from . import ByteArray from . import UnsignedInt from . import Bitfield from . import CompletionCode from . import Optional from . import RemainingBytes SELFTEST_RESULT_NO_ERROR = 0x55 SELFTEST_RESULT_NOT_IMPLEMENTED = 0x56 SELFTEST_RESULT_CORRUPTED_DATA_OR_INACCESSIBLE_DEVICE = 0x57 SELFTEST_RESULT_FATAL_HARDWARE_ERROR = 0x58 @register_message_class class GetDeviceIdReq(Message): __cmdid__ = constants.CMDID_GET_DEVICE_ID __netfn__ = constants.NETFN_APP @register_message_class class GetDeviceIdRsp(Message): __cmdid__ = constants.CMDID_GET_DEVICE_ID __netfn__ = constants.NETFN_APP | 1 __fields__ = ( CompletionCode(), UnsignedInt('device_id', 1), Bitfield('device_revision', 1, Bitfield.Bit('device_revision', 4), Bitfield.ReservedBit(3, 0), Bitfield.Bit('provides_device_sdrs', 1)), Bitfield('firmware_revision', 2, Bitfield.Bit('major', 7), Bitfield.Bit('device_available', 1), Bitfield.Bit('minor', 8)), UnsignedInt('ipmi_version', 1), Bitfield('additional_support', 1, Bitfield.Bit('sensor', 1), Bitfield.Bit('sdr_repository', 1), Bitfield.Bit('sel', 1), Bitfield.Bit('fru_inventory', 1), Bitfield.Bit('ipmb_event_receiver', 1), Bitfield.Bit('ipmb_event_generator', 1), Bitfield.Bit('bridge', 1), Bitfield.Bit('chassis', 1)), UnsignedInt('manufacturer_id', 3), UnsignedInt('product_id', 2), Optional(ByteArray('auxiliary', 4)) ) @register_message_class class ColdResetReq(Message): __cmdid__ = constants.CMDID_COLD_RESET __netfn__ = constants.NETFN_APP @register_message_class class ColdResetRsp(Message): __cmdid__ = constants.CMDID_COLD_RESET __netfn__ = constants.NETFN_APP | 1 __fields__ = ( CompletionCode(), ) @register_message_class class WarmResetReq(Message): __cmdid__ = constants.CMDID_WARM_RESET __netfn__ = constants.NETFN_APP @register_message_class class WarmResetRsp(Message): __cmdid__ = constants.CMDID_WARM_RESET __netfn__ = constants.NETFN_APP | 1 __fields__ = ( CompletionCode(), ) @register_message_class class ManufacturingTestOnReq(Message): __cmdid__ = constants.CMDID_MANUFACTURING_TEST_ON __netfn__ = constants.NETFN_APP __fields__ = ( RemainingBytes('data'), ) @register_message_class class ManufacturingTestOnRsp(Message): __cmdid__ = constants.CMDID_MANUFACTURING_TEST_ON __netfn__ = constants.NETFN_APP | 1 __fields__ = ( CompletionCode(), RemainingBytes('data'), ) @register_message_class class GetSelftestResultsReq(Message): __cmdid__ = constants.CMDID_GET_SELF_TEST_RESULTS __netfn__ = constants.NETFN_APP @register_message_class class GetSelftestResultsRsp(Message): __cmdid__ = constants.CMDID_GET_SELF_TEST_RESULTS __netfn__ = constants.NETFN_APP | 1 __fields__ = ( CompletionCode(), UnsignedInt('result', 1), Bitfield('status', 1, Bitfield.Bit('controller_firmware_corrupted', 1, 0), Bitfield.Bit('controller_bootblock_corrupted', 1, 0), Bitfield.Bit('internal_use_area_corrupted', 1, 0), Bitfield.Bit('sdr_repository_empty', 1, 0), Bitfield.Bit('ipmb_signal_lines_do_not_respond', 1, 0), Bitfield.Bit('cannot_access_bmc_fru_device', 1, 0), Bitfield.Bit('cannot_access_sdr_device', 1, 0), Bitfield.Bit('cannot_access_sel_device', 1, 0),), ) @register_message_class class SetAcpiPowerStateReq(Message): __cmdid__ = constants.CMDID_SET_ACPI_POWER_STATE __netfn__ = constants.NETFN_APP __not_implemented__ = True @register_message_class class SetAcpiPowerStateRsp(Message): __cmdid__ = constants.CMDID_SET_ACPI_POWER_STATE __netfn__ = constants.NETFN_APP | 1 __not_implemented__ = True @register_message_class class GetAcpiPowerStateReq(Message): __cmdid__ = constants.CMDID_GET_ACPI_POWER_STATE __netfn__ = constants.NETFN_APP __not_implemented__ = True @register_message_class class GetAcpiPowerStateRsp(Message): __cmdid__ = constants.CMDID_GET_ACPI_POWER_STATE __netfn__ = constants.NETFN_APP | 1 __not_implemented__ = True @register_message_class class GetDeviceGuideReq(Message): __cmdid__ = constants.CMDID_GET_DEVICE_GUID __netfn__ = constants.NETFN_APP __not_implemented__ = True @register_message_class class GetDeviceGuideRsp(Message): __cmdid__ = constants.CMDID_GET_DEVICE_GUID __netfn__ = constants.NETFN_APP | 1 __not_implemented__ = True @register_message_class class ResetWatchdogTimerReq(Message): __cmdid__ = constants.CMDID_RESET_WATCHDOG_TIMER __netfn__ = constants.NETFN_APP @register_message_class class ResetWatchdogTimerRsp(Message): __cmdid__ = constants.CMDID_RESET_WATCHDOG_TIMER __netfn__ = constants.NETFN_APP | 1 __fields__ = ( CompletionCode(), ) @register_message_class class SetWatchdogTimerReq(Message): __cmdid__ = constants.CMDID_SET_WATCHDOG_TIMER __netfn__ = constants.NETFN_APP __fields__ = ( Bitfield('timer_use', 1, Bitfield.Bit('timer_use', 3), Bitfield.ReservedBit(3, 0), Bitfield.Bit('dont_stop', 1, 0), Bitfield.Bit('dont_log', 1, 0),), Bitfield('timer_actions', 1, Bitfield.Bit('timeout_action', 3), Bitfield.ReservedBit(1, 0), Bitfield.Bit('pre_timeout_interrupt', 3), Bitfield.ReservedBit(1, 0),), UnsignedInt('pre_timeout_interval', 1), UnsignedInt('timer_use_expiration_flags', 1), UnsignedInt('initial_countdown', 2), ) @register_message_class class SetWatchdogTimerRsp(Message): __cmdid__ = constants.CMDID_SET_WATCHDOG_TIMER __netfn__ = constants.NETFN_APP | 1 __fields__ = ( CompletionCode(), ) @register_message_class class GetWatchdogTimerReq(Message): __cmdid__ = constants.CMDID_GET_WATCHDOG_TIMER __netfn__ = constants.NETFN_APP @register_message_class class GetWatchdogTimerRsp(Message): __cmdid__ = constants.CMDID_GET_WATCHDOG_TIMER __netfn__ = constants.NETFN_APP | 1 __fields__ = ( CompletionCode(), Bitfield('timer_use', 1, Bitfield.Bit('timer_use', 3), Bitfield.ReservedBit(3, 0), Bitfield.Bit('is_running', 1, 0), Bitfield.Bit('dont_log', 1, 0),), Bitfield('timer_actions', 1, Bitfield.Bit('timeout_action', 3), Bitfield.ReservedBit(1, 0), Bitfield.Bit('pre_timeout_interrupt', 3), Bitfield.ReservedBit(1, 0),), UnsignedInt('pre_timeout_interval', 1), UnsignedInt('timer_use_expiration_flags', 1), UnsignedInt('initial_countdown', 2), UnsignedInt('present_countdown', 2), ) python-ipmi-0.4.2/pyipmi/msgs/session.py0000664000372000037200000000000013574451473021154 0ustar travistravis00000000000000python-ipmi-0.4.2/pyipmi/msgs/chassis.py0000664000372000037200000001114213574451473021137 0ustar travistravis00000000000000from __future__ import absolute_import # Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from . import constants from . import register_message_class from . import Message from . import UnsignedInt from . import Bitfield from . import CompletionCode from . import Optional CONTROL_POWER_DOWN = 0 CONTROL_POWER_UP = 1 CONTROL_POWER_CYCLE = 2 CONTROL_HARD_RESET = 3 CONTROL_DIAGNOSTIC_INTERRUPT = 4 CONTROL_SOFT_SHUTDOWN = 5 @register_message_class class GetChassisCapabilitiesReq(Message): __cmdid__ = constants.CMDID_GET_CHASSIS_CAPABILITIES __netfn__ = constants.NETFN_CHASSIS @register_message_class class GetChassisCapabilitiesRsp(Message): __cmdid__ = constants.CMDID_GET_CHASSIS_CAPABILITIES __netfn__ = constants.NETFN_CHASSIS | 1 __fields__ = ( CompletionCode(), Bitfield('capabilities_flags', 1, Bitfield.Bit('intrusion_sensor', 1), Bitfield.Bit('frontpanel_lockout', 1), Bitfield.Bit('diagnostic_interrupt', 1), Bitfield.Bit('power_interlock', 1), Bitfield.ReservedBit(4, 0)), UnsignedInt('fru_info_device_address', 1), UnsignedInt('sdr_device_address', 1), UnsignedInt('sel_device_address', 1), UnsignedInt('system_management_device_address', 1), Optional( UnsignedInt('bridge_device_address', 1) ), ) @register_message_class class GetChassisStatusReq(Message): __cmdid__ = constants.CMDID_GET_CHASSIS_STATUS __netfn__ = constants.NETFN_CHASSIS @register_message_class class GetChassisStatusRsp(Message): __cmdid__ = constants.CMDID_GET_CHASSIS_STATUS __netfn__ = constants.NETFN_CHASSIS | 1 __fields__ = ( CompletionCode(), Bitfield('current_power_state', 1, Bitfield.Bit('power_on', 1), Bitfield.Bit('power_overload', 1), Bitfield.Bit('interlock', 1), Bitfield.Bit('power_fault', 1), Bitfield.Bit('power_control_fault', 1), Bitfield.Bit('power_restore_policy', 2), Bitfield.ReservedBit(1, 0),), Bitfield('last_power_event', 1, Bitfield.Bit('ac_failed', 1), Bitfield.Bit('power_overload', 1), Bitfield.Bit('power_interlock', 1), Bitfield.Bit('power_fault', 1), Bitfield.Bit('power_is_on_via_ipmi_command', 1), Bitfield.ReservedBit(3, 0),), Bitfield('misc_chassis_state', 1, Bitfield.Bit('chassis_intrusion_active', 1), Bitfield.Bit('front_panel_lockout_active', 1), Bitfield.Bit('drive_fault', 1), Bitfield.Bit('cooling_fault_detected', 1), Bitfield.Bit('chassis_id_state', 2), Bitfield.Bit('id_cmd_state_info_support', 1), Bitfield.ReservedBit(1, 0),), Optional( UnsignedInt('front_panel_button_capabilities', 1), ), ) @register_message_class class ChassisControlReq(Message): __cmdid__ = constants.CMDID_CHASSIS_CONTROL __netfn__ = constants.NETFN_CHASSIS __fields__ = ( Bitfield('control', 1, Bitfield.Bit('option', 4), Bitfield.ReservedBit(4, 0)), ) @register_message_class class ChassisControlRsp(Message): __cmdid__ = constants.CMDID_CHASSIS_CONTROL __netfn__ = constants.NETFN_CHASSIS | 1 __fields__ = ( CompletionCode(), ) @register_message_class class GetPohCounterReq(Message): __cmdid__ = constants.CMDID_GET_POH_COUNTER __netfn__ = constants.NETFN_CHASSIS @register_message_class class GetPohCounterRsp(Message): __cmdid__ = constants.CMDID_GET_POH_COUNTER __netfn__ = constants.NETFN_CHASSIS | 1 __fields__ = ( CompletionCode(), UnsignedInt('minutes_per_count', 1), UnsignedInt('counter_reading', 4), ) python-ipmi-0.4.2/pyipmi/hpm.py0000664000372000037200000006324613574451473017331 0ustar travistravis00000000000000# Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from __future__ import print_function import os import codecs import struct import collections import hashlib import time from array import array from .errors import CompletionCodeError, HpmError, IpmiTimeoutError from .msgs import create_request_by_name from .msgs import constants from .utils import check_completion_code, bcd_search, chunks from .utils import py3dec_unic_bytes_fix, bytes2 as bytes from .state import State from .fields import VersionField PROPERTY_GENERAL_PROPERTIES = 0 PROPERTY_CURRENT_VERSION = 1 PROPERTY_DESCRIPTION_STRING = 2 PROPERTY_ROLLBACK_VERSION = 3 PROPERTY_DEFERRED_VERSION = 4 PROPERTY_OEM = list(range(192, 255)) ACTION_BACKUP_COMPONENT = 0x00 ACTION_PREPARE_COMPONENT = 0x01 ACTION_UPLOAD_FOR_UPGRADE = 0x02 ACTION_UPLOAD_FOR_COMPARE = 0x03 CC_LONG_DURATION_CMD_IN_PROGRESS = 0x80 CC_GET_COMP_PROP_UPGRADE_NOT_SUPPORTED_OVER_INTF = 0x81 CC_GET_COMP_PROP_INVALID_COMPONENT = 0x82 CC_GET_COMP_PROP_INVALID_PROPERTIES_SELECTOR = 0x83 CC_INITIATE_UPGRADE_CMD_IN_PROGRESS = 0x80 CC_INITIATE_UPGRADE_INVALID_COMPONENT = 0x81 CC_QUERY_SELFTEST_COMPLETED = 0x00 CC_QUERY_SELFTEST_IN_PROGRESS = 0x80 CC_QUERY_SELFTEST_UPGRADE_NOT_SUPPORTED_OVER_INTF = 0x81 CC_QUERY_SELFTEST_NO_RESULTS_AVAILABLE = 0xD5 CC_ABORT_UPGRADE_CANNOT_ABORT = 0x80 CC_ABORT_UPGRADE_CANNOT_RESUME_OPERATION = 0x81 class Hpm(object): @staticmethod def _get_component_count(components): """Return the number of components""" return bin(components).count('1') def get_target_upgrade_capabilities(self): rsp = self.send_message_with_name('GetTargetUpgradeCapabilities') return TargetUpgradeCapabilities(rsp) def get_component_property(self, component_id, property_id): rsp = self.send_message_with_name('GetComponentProperties', id=component_id, selector=property_id) return ComponentProperty.from_data(property_id, rsp.data) def get_component_properties(self, component_id): properties = [] for p in (PROPERTY_GENERAL_PROPERTIES, PROPERTY_CURRENT_VERSION, PROPERTY_DESCRIPTION_STRING, PROPERTY_ROLLBACK_VERSION, PROPERTY_DEFERRED_VERSION): try: prop = self.get_component_property(component_id, p) if prop is not None: properties.append(prop) except CompletionCodeError as e: if e.cc == CC_GET_COMP_PROP_INVALID_PROPERTIES_SELECTOR: continue return properties def find_component_id_by_descriptor(self, descriptor): caps = self.get_target_upgrade_capabilities() for component_id in caps.components: prop = self.get_component_property(component_id, PROPERTY_DESCRIPTION_STRING) if prop is not None: if prop.description == descriptor: return component_id return None def abort_firmware_upgrade(self): self.send_message_with_name('AbortFirmwareUpgrade') def initiate_upgrade_action(self, components_mask, action): """ Initiate Upgrade Action components: action: ACTION_BACKUP_COMPONENT = 0x00 ACTION_PREPARE_COMPONENT = 0x01 ACTION_UPLOAD_FOR_UPGRADE = 0x02 ACTION_UPLOAD_FOR_COMPARE = 0x03 """ if action in (ACTION_UPLOAD_FOR_UPGRADE, ACTION_UPLOAD_FOR_COMPARE): if self._get_component_count(components_mask) != 1: raise HpmError("more than 1 component not support for action") self.send_message_with_name('InitiateUpgradeAction', components=components_mask, action=action) def initiate_upgrade_action_and_wait(self, components_mask, action, timeout=2, interval=0.1): """ Initiate Upgrade Action and wait for long running command. """ try: self.initiate_upgrade_action(components_mask, action) except CompletionCodeError as e: if e.cc == CC_LONG_DURATION_CMD_IN_PROGRESS: self.wait_for_long_duration_command( constants.CMDID_HPM_INITIATE_UPGRADE_ACTION, timeout, interval) else: raise HpmError('initiate_upgrade_action CC=0x%02x' % e.cc) def upload_firmware_block(self, block_number, data): data = [ord(c) for c in data] self.send_message_with_name('UploadFirmwareBlock', number=block_number, data=data) @staticmethod def _determine_max_block_size(): return 22 def upload_binary(self, binary, timeout=2, interval=0.1, retry=3): """ Upload all firmware blocks from binary and wait for long running command. """ block_number = 0 block_size = self._determine_max_block_size() for chunk in chunks(binary, block_size): try: self.upload_firmware_block(block_number, chunk) except CompletionCodeError as e: if e.cc == CC_LONG_DURATION_CMD_IN_PROGRESS: self.wait_for_long_duration_command( constants.CMDID_HPM_UPLOAD_FIRMWARE_BLOCK, timeout, interval) else: raise HpmError('upload_firmware_block CC=0x%02x' % e.cc) except IpmiTimeoutError: retry -= 1 if retry == 0: raise IpmiTimeoutError() block_number += 1 block_number &= 0xff def finish_firmware_upload(self, component, length): return self.send_message_with_name('FinishFirmwareUpload', component_id=component, image_length=length) def finish_upload_and_wait(self, component, length, timeout=2, interval=0.1): """ Finish the firmware upload process and wait for long running command. """ try: rsp = self.finish_firmware_upload(component, length) check_completion_code(rsp.completion_code) except CompletionCodeError as e: if e.cc == CC_LONG_DURATION_CMD_IN_PROGRESS: self.wait_for_long_duration_command( constants.CMDID_HPM_FINISH_FIRMWARE_UPLOAD, timeout, interval) else: raise HpmError('finish_firmware_upload CC=0x%02x' % e.cc) def get_upgrade_status(self): return UpgradeStatus(self.send_message_with_name('GetUpgradeStatus')) def wait_for_long_duration_command(self, expected_cmd, timeout, interval): start_time = time.time() while time.time() < start_time + timeout: try: status = self.get_upgrade_status() if status.command_in_progress is not expected_cmd \ and status.command_in_progress is not 0x34: pass if status.last_completion_code \ == CC_LONG_DURATION_CMD_IN_PROGRESS: time.sleep(interval) else: return except IpmiTimeoutError: time.sleep(interval) except IOError: time.sleep(interval) def activate_firmware(self, rollback_override=None): req = create_request_by_name('ActivateFirmware') if rollback_override is not None: req.rollback_override_policy = rollback_override rsp = self.send_message(req) check_completion_code(rsp.completion_code) def activate_firmware_and_wait(self, rollback_override=None, timeout=2, interval=1): """ Activate the new uploaded firmware and wait for long running command. """ try: self.activate_firmware(rollback_override) except CompletionCodeError as e: if e.cc == CC_LONG_DURATION_CMD_IN_PROGRESS: self.wait_for_long_duration_command( constants.CMDID_HPM_ACTIVATE_FIRMWARE, timeout, interval) else: raise HpmError('activate_firmware CC=0x%02x' % e.cc) except IpmiTimeoutError: # controller is in reset and flashed new firmware pass def query_selftest_results(self): return SelfTestResult( self.send_message_with_name('QuerySelftestResults')) def query_rollback_status(self): return RollbackStatus( self.send_message_with_name('QueryRollbackStatus')) def initiate_manual_rollback(self): return RollbackStatus( self.send_message_with_name('InitiateManualRollback')) def initiate_manual_rollback_and_wait(self, timeout=2, interval=0.1): try: self.initiate_manual_rollback() except CompletionCodeError as e: if e.cc == CC_LONG_DURATION_CMD_IN_PROGRESS: self.wait_for_long_duration_command( constants.CMDID_HPM_INITIATE_MANUAL_ROLLBACK, 60, interval) else: raise HpmError('activate_firmware CC=0x%02x' % e.cc) except IpmiTimeoutError: # controller is in reset and flashed new firmware pass @staticmethod def open_upgrade_image(filename): return UpgradeImage(filename) @staticmethod def get_upgrade_version_from_file(filename): image = UpgradeImage(filename) for action in image.actions: if isinstance(action, UpgradeActionRecordUploadForUpgrade): return action.firmware_version return None @staticmethod def _do_upgrade_action_backup(image): for action in image.actions: if isinstance(action, UpgradeActionRecordBackup): pass @staticmethod def _do_upgrade_action_prepare(image): for action in image.actions: if isinstance(action, UpgradeActionRecordPrepare): print("do ACTION_PREPARE_COMPONENT") @staticmethod def _do_upgrade_action_upload(image): for action in image.actions: if isinstance(action, UpgradeActionRecordUploadForUpgrade): print("do ACTION_UPLOAD_FOR_UPGRADE") def preparation_stage(self, image): #################################################### # match device ID, manfuacturer ID, etc. device_id = self.get_device_id() header = image.header if header.device_id != device_id.device_id: raise HpmError('Device ID: image=0x%x device=0x%x' % (header.device_id, device_id.device_id)) if header.manufacturer_id != device_id.manufacturer_id: raise HpmError('Manufacturer ID: image=0x%x device=0x%x' % (header.manufacturer_id, device_id.manufacturer_id)) if header.product_id != device_id.product_id: raise HpmError('Product ID: image=0x%x device=0x%x' % (header.product_id, device_id.product_id)) # tbd check version #################################################### # compare current revision with upgrade image earlist comp rev targetCap = self.get_target_upgrade_capabilities() # tbd check version #################################################### # Match IPM Controller capabilities with Upgrade Image capabilities support = False for imageComponent in header.components: if imageComponent in targetCap.components: support = True if support is not True: raise HpmError('no supported component in image') def upgrade_stage(self, image, component): for action in image.actions: if action.components & (1 << component) == 0: continue self.initiate_upgrade_action_and_wait(1 << component, action.action_type) if isinstance(action, UpgradeActionRecordUploadForUpgrade): self.upload_binary(action.firmware_image_data) self.finish_upload_and_wait(component, action.firmware_length) def _activation_state_do_self_testing(self): pass def wait_until_new_firmware_comes_up(self, timeout, interval): start_time = time.time() while time.time() < start_time + timeout: try: self.get_upgrade_status() self.get_device_id() except IpmiTimeoutError: time.sleep(interval) except IOError: time.sleep(interval) time.sleep(5) def activation_stage(self, image, component): self.activate_firmware_and_wait( image.header.inaccessibility_timeout, 1) self.wait_until_new_firmware_comes_up( image.header.inaccessibility_timeout, 1) self._activation_state_do_self_testing() def install_component_from_image(self, image, component): self.abort_firmware_upgrade() if component not in image.header.components: raise HpmError('component=%d not in image' % component) self.preparation_stage(image) self.upgrade_stage(image, component) self.activation_stage(image, component) def install_component_from_file(self, filename, component): image = UpgradeImage(filename) self.install_component_from_image(image, component) class UpgradeStatus(State): def _from_response(self, rsp): self.command_in_progress = rsp.command_in_progress self.last_completion_code = rsp.last_completion_code def __str__(self): string = [] string.append("cmd=0x%02x cc=0x%02x" % (self.command_in_progress, self.last_completion_code)) return "\n".join(string) class TargetUpgradeCapabilities(State): def _from_response(self, rsp): self.version = rsp.hpm_1_version self.components = [] for i in range(8): if rsp.component_present & (1 << i): self.components.append(i) def __str__(self): string = [] string.append("Target Upgrade Capabilities") string.append(" HPM.1 version: %s" % self.version) string.append(" Components: %s" % self.components) return "\n".join(string) codecs.register(bcd_search) class ComponentProperty(object): def __init__(self, data=None): if (data): self._from_rsp_data(data) @staticmethod def from_data(component_id, data): if isinstance(data, str): data = [ord(c) for c in data] if component_id is PROPERTY_GENERAL_PROPERTIES: return ComponentPropertyGeneral(data) elif component_id is PROPERTY_CURRENT_VERSION: return ComponentPropertyCurrentVersion(data) elif component_id is PROPERTY_DESCRIPTION_STRING: return ComponentPropertyDescriptionString(data) elif component_id is PROPERTY_ROLLBACK_VERSION: return ComponentPropertyRollbackVersion(data) elif component_id is PROPERTY_DEFERRED_VERSION: return ComponentPropertyDeferredVersion(data) elif component_id in PROPERTY_OEM: raise NotImplementedError class ComponentPropertyGeneral(ComponentProperty): ROLLBACK_SUPPORT_MASK = 0x03 PREPARATION_SUPPORT_MASK = 0x04 COMPARISON_SUPPORT_MASK = 0x08 DEFERRED_ACTIVATION_SUPPORT_MASK = 0x10 PAYLOAD_COLD_RESET_REQ_SUPPORT_MASK = 0x20 def _from_rsp_data(self, data): support = [] cap = data[0] if cap & self.ROLLBACK_SUPPORT_MASK == 0: support.append('rollback_backup_not_supported') elif cap & self.ROLLBACK_SUPPORT_MASK == 1: support.append('rollback_is_supported') elif cap & self.ROLLBACK_SUPPORT_MASK == 2: support.append('rollback_is_supported') elif cap & self.ROLLBACK_SUPPORT_MASK == 3: support.append('reserved') if cap & self.PREPARATION_SUPPORT_MASK: support.append('prepartion') if cap & self.COMPARISON_SUPPORT_MASK: support.append('comparison') if cap & self.DEFERRED_ACTIVATION_SUPPORT_MASK: support.append('deferred_activation') if cap & self.PAYLOAD_COLD_RESET_REQ_SUPPORT_MASK: support.append('payload_cold_reset_required') self.general = support class ComponentPropertyCurrentVersion(ComponentProperty): def _from_rsp_data(self, data): self.version = VersionField(data) class ComponentPropertyDescriptionString(ComponentProperty): def _from_rsp_data(self, data): self.description = py3dec_unic_bytes_fix(array('B', data).tostring()) # strip '\x00' self.description = self.description.replace('\0', '') class ComponentPropertyRollbackVersion(ComponentProperty): def _from_rsp_data(self, data): self.version = VersionField(data) class ComponentPropertyDeferredVersion(ComponentProperty): def _from_rsp_data(self, data): self.version = VersionField(data) class ComponentPropertyOem(ComponentProperty): def _from_rsp_data(self, data): self.oem_data = data class SelfTestResult(State): CORRUPTED_OR_INACCESSIBLE_DATA_OR_DEVICES = 0x57 def _from_response(self, rsp): self.status = rsp.selftest_result_1 result2 = rsp.selftest_result_2 if self.status != self.CORRUPTED_OR_INACCESSIBLE_DATA_OR_DEVICES: self.fail_sel = (result2 & 0x80) >> 7 self.fail_sdrr = (result2 & 0x40) >> 6 self.fail_bmc_fru = (result2 & 0x20) >> 5 self.fail_ipmb = (result2 & 0x10) >> 4 self.fail_sdrr_empty = (result2 & 0x08) >> 3 self.fail_bmc_fru_interanl_area = (result2 & 0x04) >> 2 self.fail_bootblock = (result2 & 0x02) >> 1 self.fail_mc = (result2 & 0x01) >> 0 class RollbackStatus(object): def __init__(self, rsp=None): if rsp: self._from_rsp(rsp) def _from_rsp(self, rsp): if rsp.completion_estimate: self.percent_complete = rsp.completion_estimate image_header = collections.namedtuple('image_header', ['field_name', 'format', 'start', 'len']) class UpgradeImageHeaderRecord(object): FORMAT = [ image_header('format_version', 'B', 8, 1), image_header('device_id', 'B', 9, 1), image_header('product_id', ' record_length: length = record_length - offset try: (next_id, data) = get_fn(reservation_id, record_id, offset, length) except CompletionCodeError as e: if e.cc == constants.CC_CANT_RET_NUM_REQ_BYTES: # reduce max lenght max_req_len -= 4 if max_req_len <= 0: retry = 0 else: raise CompletionCodeError(e.cc) record_data.extend(data[:]) offset = len(record_data) if len(record_data) >= record_length: break return (next_id, record_data) INITIATE_ERASE = 0xaa GET_ERASE_STATUS = 0x00 ERASURE_IN_PROGRESS = 0x0 ERASURE_COMPLETED = 0x1 def _clear_repository(reserve_fn, clear_fn, ctrl, retry, reservation): while True: retry -= 1 if retry <= 0: raise RetryError() try: in_progress = clear_fn(ctrl, reservation) except CompletionCodeError as e: if e.cc == constants.CC_RES_CANCELED: time.sleep(0.2) reservation = reserve_fn() continue else: check_completion_code(e.cc) if in_progress == ERASURE_IN_PROGRESS: time.sleep(0.5) continue break return reservation def clear_repository_helper(reserve_fn, clear_fn, retry=5, reservation=None): """Helper function to start repository erasure and wait until finish. This helper is used by clear_sel and clear_sdr_repository. """ if reservation is None: reservation = reserve_fn() # start erasure reservation = _clear_repository(reserve_fn, clear_fn, INITIATE_ERASE, retry, reservation) # give some time to clear time.sleep(0.5) # wait until finish reservation = _clear_repository(reserve_fn, clear_fn, GET_ERASE_STATUS, retry, reservation) python-ipmi-0.4.2/pyipmi/sdr.py0000664000372000037200000005462413574451473017335 0ustar travistravis00000000000000# Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from __future__ import absolute_import from __future__ import division import math from . import errors from .errors import DecodingError from .utils import check_completion_code, ByteBuffer, py3dec_unic_bytes_fix from .msgs import create_request_by_name from .helper import get_sdr_data_helper, clear_repository_helper from .helper import get_sdr_chunk_helper from .state import State SDR_TYPE_FULL_SENSOR_RECORD = 0x01 SDR_TYPE_COMPACT_SENSOR_RECORD = 0x02 SDR_TYPE_EVENT_ONLY_SENSOR_RECORD = 0x03 SDR_TYPE_ENTITY_ASSOCIATION_RECORD = 0x08 SDR_TYPE_FRU_DEVICE_LOCATOR_RECORD = 0x11 SDR_TYPE_MANAGEMENT_CONTROLLER_DEVICE_LOCATOR_RECORD = 0x12 SDR_TYPE_MANAGEMENT_CONTROLLER_CONFIRMATION_RECORD = 0x13 SDR_TYPE_BMC_MESSAGE_CHANNEL_INFO_RECORD = 0x14 SDR_TYPE_OEM_SENSOR_RECORD = 0xC0 GET_INITIALIZATION_AGENT_STATUS = 0 RUN_INITIALIZATION_AGENT = 1 L_LINEAR = 0 L_LN = 1 L_LOG = 2 L_LOG2 = 3 L_E = 4 L_EXP10 = 5 L_EXP2 = 6 L_1_X = 7 L_SQR = 8 L_CUBE = 9 L_SQRT = 10 L_CUBERT = 11 class Sdr(object): def __init__(self): pass def get_sdr_repository_info(self): return SdrRepositoryInfo( self.send_message_with_name('GetSdrRepositoryInfo')) def get_sdr_repository_allocation_info(self): return SdrRepositoryAllocationInfo( self.send_message_with_name('GetSdrRepositoryAllocationInfo')) def reserve_sdr_repository(self): rsp = self.send_message_with_name('ReserveSdrRepository') return rsp.reservation_id def _get_sdr_chunk(self, reservation_id, record_id, offset, length): req = create_request_by_name('GetSdr') req.reservation_id = reservation_id req.record_id = record_id req.offset = offset req.bytes_to_read = length rsp = get_sdr_chunk_helper(self.send_message, req, self.reserve_device_sdr_repository) return (rsp.next_record_id, rsp.record_data) def get_repository_sdr(self, record_id, reservation_id=None): (next_id, record_data) = get_sdr_data_helper( self.reserve_sdr_repository, self._get_sdr_chunk, record_id, reservation_id) return SdrCommon.from_data(record_data, next_id) def sdr_repository_entries(self): """A generator that returns the SDR list. Starting with ID=0x0000 and end when ID=0xffff is returned. """ reservation_id = self.reserve_sdr_repository() record_id = 0 while True: s = self.get_repository_sdr(record_id, reservation_id) yield s if s.next_id == 0xffff: break record_id = s.next_id def get_repository_sdr_list(self, reservation_id=None): """Returns the complete SDR list. """ return list(self.sdr_repository_entries()) def partial_add_sdr(self, reservation_id, record_id, offset, progress, data): req = create_request_by_name('PartialAddSdr') req.reservation_id = reservation_id req.record_id = record_id req.offset = offset req.status.in_progress = progress req.data = data rsp = self.send_message(req) check_completion_code(rsp.completion_code) return rsp.record_id def delete_sdr(self, record_id): """ Deletes the sensor record specified by 'record_id'. """ reservation_id = self.reserve_device_sdr_repository() rsp = self.send_message_with_name('DeleteSdr', reservation_id=reservation_id, record_id=record_id) return rsp.record_id def _clear_sdr_repository(self, cmd, reservation_id): rsp = self.send_message_with_name('ClearSdrRepository', reservation_id=reservation_id, cmd=cmd) return rsp.status.erase_in_progress def clear_sdr_repository(self, retry=5): clear_repository_helper(self.reserve_sdr_repository, self._clear_sdr_repository, retry) def _run_initialization_agent(self, cmd): rsp = self.send_message_with_name('RunInitializationAgent', cmd=cmd) return rsp.status.initialization_completed def start_initialization_agent(self): self._run_initialization_agent(RUN_INITIALIZATION_AGENT) def get_initialization_agent_status(self): return self._run_initialization_agent(GET_INITIALIZATION_AGENT_STATUS) class SdrRepositoryInfo(State): def __init__(self, rsp): if rsp: self._from_response(rsp) def _from_response(self, rsp): self.sdr_version = rsp.sdr_version self.record_count = rsp.record_count self.free_space = rsp.free_space self.most_recent_addition = rsp.most_recent_addition self.support_get_allocation_info = rsp.support.get_allocation_info self.support_reserve = rsp.support.reserve self.support_partial_add = rsp.support.partial_add self.support_delete = rsp.support.delete self.support_update_type = rsp.support.update_type self.support_overflow_flag = rsp.support.overflow_flag class SdrRepositoryAllocationInfo(State): def __init__(self, rsp): if rsp: self._from_response(rsp) def _from_response(self, rsp): self.number_of_units = rsp.number_of_units self.unit_size = rsp.unit_size self.free_units = rsp.free_units self.largest_free_block = rsp.largest_free_block self.maximum_record_size = rsp.maximum_record_size class SdrCommon(object): def __init__(self, data=None, next_id=None): if data: self.data = data self._common_header(data) if hasattr(self, '_from_data'): self._from_data(data) if next_id: self.next_id = next_id def __str__(self): s = '["%-16s"] [%s]' % \ (self.device_id_string, ' '.join(['%02x' % b for b in self.data])) return s def _common_header(self, data): buffer = ByteBuffer(data[:]) try: self.id = buffer.pop_unsigned_int(2) self.version = buffer.pop_unsigned_int(1) self.type = buffer.pop_unsigned_int(1) self.length = buffer.pop_unsigned_int(1) except: raise DecodingError('Invalid SDR length (%d)' % len(data)) def _common_record_key(self, buffer): self.owner_id = buffer.pop_unsigned_int(1) self.owner_lun = buffer.pop_unsigned_int(1) & 0x3 self.number = buffer.pop_unsigned_int(1) def _entity(self, buffer): self.entity_id = buffer.pop_unsigned_int(1) self.entity_instance = buffer.pop_unsigned_int(1) def _device_id_string(self, buffer): self.device_id_string_type_length = buffer.pop_unsigned_int(1) self.device_id_string = \ buffer.pop_string(self.device_id_string_type_length & 0x3f) @staticmethod def from_data(data, next_id=None): sdr_type = data[3] try: cls = { SDR_TYPE_FULL_SENSOR_RECORD: SdrFullSensorRecord, SDR_TYPE_COMPACT_SENSOR_RECORD: SdrCompactSensorRecord, SDR_TYPE_EVENT_ONLY_SENSOR_RECORD: SdrEventOnlySensorRecord, SDR_TYPE_FRU_DEVICE_LOCATOR_RECORD: SdrFruDeviceLocator, SDR_TYPE_MANAGEMENT_CONTROLLER_DEVICE_LOCATOR_RECORD: SdrManagementControllerDeviceLocator, SDR_TYPE_OEM_SENSOR_RECORD: SdrOEMSensorRecord, }[sdr_type] except KeyError: raise DecodingError('Unsupported SDR type(0x%02x)' % sdr_type) return cls(data, next_id) ### # SDR type 0x01 ################################################## class SdrFullSensorRecord(SdrCommon): DATA_FMT_UNSIGNED = 0 DATA_FMT_1S_COMPLEMENT = 1 DATA_FMT_2S_COMPLEMENT = 2 DATA_FMT_NONE = 3 def __init__(self, data=None, next_id=None): super(SdrFullSensorRecord, self).__init__(data, next_id) if data: self._from_data(data) def __str__(self): s = '["%-16s"] [%s:%s] [%s]' \ % (self.device_id_string, self.entity_id, self.entity_instance, ' '.join(['%02x' % b for b in self.data])) return s def convert_sensor_raw_to_value(self, raw): if raw is None: return None fmt = self.analog_data_format if (fmt == self.DATA_FMT_1S_COMPLEMENT): if raw & 0x80: raw = -((raw & 0x7f) ^ 0x7f) elif (fmt == self.DATA_FMT_2S_COMPLEMENT): if raw & 0x80: raw = -((raw & 0x7f) ^ 0x7f) - 1 raw = float(raw) return self.l((self.m * raw + (self.b * 10**self.k1)) * 10**self.k2) def convert_sensor_value_to_raw(self, value): linearization = self.linearization & 0x7f if linearization is not L_LINEAR: raise NotImplementedError() raw = ((float(value) * 10**(-1 * self.k2)) / self.m) - (self.b * 10**self.k1) fmt = self.analog_data_format if (fmt == self.DATA_FMT_1S_COMPLEMENT): if value < 0: raise NotImplementedError() elif (fmt == self.DATA_FMT_2S_COMPLEMENT): if value < 0: raise NotImplementedError() raw = int(round(raw)) if raw > 0xff: raise ValueError() return raw @property def l(self): try: return { L_LN: math.log, L_LOG: lambda x: math.log(x, 10), L_LOG2: lambda x: math.log(x, 2), L_E: math.exp, L_EXP10: lambda x: math.pow(10, x), L_EXP2: lambda x: math.pow(2, x), L_1_X: lambda x: 1.0 / x, L_SQR: lambda x: math.pow(x, 2), L_CUBE: lambda x: math.pow(x, 3), L_SQRT: math.sqrt, L_CUBERT: lambda x: math.pow(x, 1.0/3), L_LINEAR: lambda x: x, }[self.linearization & 0x7f] except KeyError: raise errors.DecodingError('unknown linearization %d' % (self.linearization & 0x7f)) @staticmethod def _convert_complement(value, size): if (value & (1 << (size - 1))): value = -(1 << size) + value return value def _decode_capabilities(self, capabilities): self.capabilities = [] # ignore sensor if capabilities & 0x80: self.capabilities.append('ignore_sensor') # sensor auto re-arm support if capabilities & 0x40: self.capabilities.append('auto_rearm') # sensor hysteresis support HYSTERESIS_MASK = 0x30 HYSTERESIS_IS_NOT_SUPPORTED = 0x00 HYSTERESIS_IS_READABLE = 0x10 HYSTERESIS_IS_READ_AND_SETTABLE = 0x20 HYSTERESIS_IS_FIXED = 0x30 if capabilities & HYSTERESIS_MASK == HYSTERESIS_IS_NOT_SUPPORTED: self.capabilities.append('hysteresis_not_supported') elif capabilities & HYSTERESIS_MASK == HYSTERESIS_IS_READABLE: self.capabilities.append('hysteresis_readable') elif capabilities & HYSTERESIS_MASK == HYSTERESIS_IS_READ_AND_SETTABLE: self.capabilities.append('hysteresis_read_and_setable') elif capabilities & HYSTERESIS_MASK == HYSTERESIS_IS_FIXED: self.capabilities.append('hysteresis_fixed') # sensor threshold support THRESHOLD_MASK = 0x0C THRESHOLD_IS_NOT_SUPPORTED = 0x00 THRESHOLD_IS_READABLE = 0x08 THRESHOLD_IS_READ_AND_SETTABLE = 0x04 THRESHOLD_IS_FIXED = 0x0C if capabilities & THRESHOLD_MASK == THRESHOLD_IS_NOT_SUPPORTED: self.capabilities.append('threshold_not_supported') elif capabilities & THRESHOLD_MASK == THRESHOLD_IS_READABLE: self.capabilities.append('threshold_readable') elif capabilities & THRESHOLD_MASK == THRESHOLD_IS_READ_AND_SETTABLE: self.capabilities.append('threshold_read_and_setable') elif capabilities & THRESHOLD_MASK == THRESHOLD_IS_FIXED: self.capabilities.append('threshold_fixed') # sensor event message control support if (capabilities & 0x03) is 0: pass if (capabilities & 0x03) is 1: pass if (capabilities & 0x03) is 2: pass if (capabilities & 0x03) is 3: pass def _from_data(self, data): buffer = ByteBuffer(data[5:]) # record key bytes self._common_record_key(buffer.pop_slice(3)) # record body bytes self._entity(buffer.pop_slice(2)) # byte 11 initialization = buffer.pop_unsigned_int(1) self.initialization = [] if initialization & 0x40: self.initialization.append('scanning') if initialization & 0x20: self.initialization.append('events') if initialization & 0x10: self.initialization.append('thresholds') if initialization & 0x08: self.initialization.append('hysteresis') if initialization & 0x04: self.initialization.append('type') if initialization & 0x02: self.initialization.append('default_event_generation') if initialization & 0x01: self.initialization.append('default_scanning') # byte 12 - sensor capabilities self._decode_capabilities(buffer.pop_unsigned_int(1)) self.sensor_type_code = buffer.pop_unsigned_int(1) self.event_reading_type_code = buffer.pop_unsigned_int(1) self.assertion_mask = buffer.pop_unsigned_int(2) self.deassertion_mask = buffer.pop_unsigned_int(2) self.discrete_reading_mask = buffer.pop_unsigned_int(2) # byte 21, 22, 23 self.units_1 = buffer.pop_unsigned_int(1) self.units_2 = buffer.pop_unsigned_int(1) self.units_3 = buffer.pop_unsigned_int(1) self.analog_data_format = (self.units_1 >> 6) & 0x3 self.rate_unit = (self.units_1 >> 3) >> 0x7 self.modifier_unit = (self.units_1 >> 1) & 0x2 self.percentage = self.units_1 & 0x1 # byte 24 self.linearization = buffer.pop_unsigned_int(1) & 0x7f # byte 25, 26 m = buffer.pop_unsigned_int(1) m_tol = buffer.pop_unsigned_int(1) self.m = (m & 0xff) | ((m_tol & 0xc0) << 2) # NAC: Bug fix. Upstream did not properly account for # 'M' being a twos complement value. self.m = self._convert_complement(self.m, 10) self.tolerance = (m_tol & 0x3f) # byte 27, 28, 29 b = buffer.pop_unsigned_int(1) b_acc = buffer.pop_unsigned_int(1) acc_accexp = buffer.pop_unsigned_int(1) self.b = (b & 0xff) | ((b_acc & 0xc0) << 2) self.b = self._convert_complement(self.b, 10) self.accuracy = (b_acc & 0x3f) | ((acc_accexp & 0xf0) << 4) self.accuracy_exp = (acc_accexp & 0x0c) >> 2 # byte 30 rexp_bexp = buffer.pop_unsigned_int(1) self.k2 = (rexp_bexp & 0xf0) >> 4 # convert 2s complement self.k2 = self._convert_complement(self.k2, 4) self.k1 = rexp_bexp & 0x0f # convert 2s complement self.k1 = self._convert_complement(self.k1, 4) # byte 31 analog_characteristics = buffer.pop_unsigned_int(1) self.analog_characteristic = [] if analog_characteristics & 0x01: self.analog_characteristic.append('nominal_reading') if analog_characteristics & 0x02: self.analog_characteristic.append('normal_max') if analog_characteristics & 0x04: self.analog_characteristic.append('normal_min') self.nominal_reading = buffer.pop_unsigned_int(1) self.normal_maximum = buffer.pop_unsigned_int(1) self.normal_minimum = buffer.pop_unsigned_int(1) self.sensor_maximum_reading = buffer.pop_unsigned_int(1) self.sensor_minimum_reading = buffer.pop_unsigned_int(1) self.threshold = {} self.threshold['unr'] = buffer.pop_unsigned_int(1) self.threshold['ucr'] = buffer.pop_unsigned_int(1) self.threshold['unc'] = buffer.pop_unsigned_int(1) self.threshold['lnr'] = buffer.pop_unsigned_int(1) self.threshold['lcr'] = buffer.pop_unsigned_int(1) self.threshold['lnc'] = buffer.pop_unsigned_int(1) self.hysteresis = {} self.hysteresis['positive_going'] = buffer.pop_unsigned_int(1) self.hysteresis['negative_going'] = buffer.pop_unsigned_int(1) self.reserved = buffer.pop_unsigned_int(2) self.oem = buffer.pop_unsigned_int(1) self._device_id_string(buffer) ### # SDR type 0x02 ################################################## class SdrCompactSensorRecord(SdrCommon): def __init__(self, data=None, next_id=None): super(SdrCompactSensorRecord, self).__init__(data, next_id) if data: self._from_data(data) def __str__(self): s = '["%-16s"] [%s]' \ % (self.device_id_string, ' '.join(['%02x' % b for b in self.data])) return s def _from_data(self, data): buffer = ByteBuffer(data[5:]) # record key bytes self._common_record_key(buffer.pop_slice(3)) # record body bytes self._entity(buffer.pop_slice(2)) self.sensor_initialization = buffer.pop_unsigned_int(1) self.capabilities = buffer.pop_unsigned_int(1) self.sensor_type_code = buffer.pop_unsigned_int(1) self.event_reading_type_code = buffer.pop_unsigned_int(1) self.assertion_mask = buffer.pop_unsigned_int(2) self.deassertion_mask = buffer.pop_unsigned_int(2) self.discrete_reading_mask = buffer.pop_unsigned_int(2) self.units_1 = buffer.pop_unsigned_int(1) self.units_2 = buffer.pop_unsigned_int(1) self.units_3 = buffer.pop_unsigned_int(1) self.record_sharing = buffer.pop_unsigned_int(2) self.positive_going_hysteresis = buffer.pop_unsigned_int(1) self.negative_going_hysteresis = buffer.pop_unsigned_int(1) self.reserved = buffer.pop_unsigned_int(3) self.oem = buffer.pop_unsigned_int(1) self._device_id_string(buffer) ### # SDR type 0x03 ################################################## class SdrEventOnlySensorRecord(SdrCommon): def __init__(self, data=None, next_id=None): super(SdrEventOnlySensorRecord, self).__init__(data, next_id) if data: self._from_data(data) def __str__(self): return 'Not supported yet.' def _from_data(self, data): buffer = ByteBuffer(data[5:]) # record key bytes self._common_record_key(buffer.pop_slice(3)) # record body bytes self._entity(buffer.pop_slice(2)) self.sensor_type = buffer.pop_unsigned_int(1) self.event_reading_type_code = buffer.pop_unsigned_int(1) self.record_sharing = buffer.pop_unsigned_int(2) self.reserved = buffer.pop_unsigned_int(1) self.oem = buffer.pop_unsigned_int(1) self._device_id_string(buffer) ### # SDR type 0x11 ################################################## class SdrFruDeviceLocator(SdrCommon): def __init__(self, data=None, next_id=None): super(SdrFruDeviceLocator, self).__init__(data, next_id) if data: self._from_data(data) def __str__(self): s = '["%-16s"] [%s]' \ % (self.device_id_string, ' '.join(['%02x' % b for b in self.data])) return s def _from_data(self, data): buffer = ByteBuffer(data[5:]) self.device_access_address = buffer.pop_unsigned_int(1) >> 1 self.fru_device_id = buffer.pop_unsigned_int(1) self.logical_physical = buffer.pop_unsigned_int(1) self.channel_number = buffer.pop_unsigned_int(1) self.reserved = buffer.pop_unsigned_int(1) self.device_type = buffer.pop_unsigned_int(1) self.device_type_modifier = buffer.pop_unsigned_int(1) self._entity(buffer.pop_slice(2)) self.oem = buffer.pop_unsigned_int(1) self._device_id_string(buffer) ### # SDR type 0x12 ################################################## class SdrManagementControllerDeviceLocator(SdrCommon): def __init__(self, data=None, next_id=None): super(SdrManagementControllerDeviceLocator, self).__init__( data, next_id) if data: self._from_data(data) def __str__(self): s = '["%-16s"] [%s]' \ % (self.device_id_string, ' '.join(['%02x' % b for b in self.data])) return s def _from_data(self, data): buffer = ByteBuffer(data[5:]) self.device_slave_address = buffer.pop_unsigned_int(1) >> 1 self.channel_number = buffer.pop_unsigned_int(1) & 0xf self.power_state_notification = buffer.pop_unsigned_int(1) self.global_initialization = 0 self.device_capabilities = buffer.pop_unsigned_int(1) self.reserved = buffer.pop_unsigned_int(3) self._entity(buffer.pop_slice(2)) self.oem = buffer.pop_unsigned_int(1) self._device_id_string(buffer) ### # SDR type 0xC0 ################################################## class SdrOEMSensorRecord(SdrCommon): def __init__(self, data=None, next_id=None): super(SdrOEMSensorRecord, self).__init__(data, next_id) if data: self._from_data(data) def __str__(self): return 'Not supported yet.' def _from_data(self, data): buffer = ByteBuffer(data[5:]) # record key bytes self._common_record_key(buffer.pop_slice(3)) python-ipmi-0.4.2/pyipmi/fields.py0000664000372000037200000000232613574451473020003 0ustar travistravis00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- import array from .errors import DecodingError class VersionField(object): """This class represent the Version fields defines by IPMI. Introduced with HPM the version field can hold additional auxiliary bytes. """ VERSION_FIELD_LEN = 2 VERSION_WITH_AUX_FIELD_LEN = 6 def __init__(self, data=None): self.major = None self.minor = None if data: self._from_data(data) def _from_data(self, data): if isinstance(data, str): data = [ord(c) for c in data] data = array.array('B', data) self.version = self._decode_data(data[0:2]) if len(data) == self.VERSION_WITH_AUX_FIELD_LEN: self.auxiliary = data[2:6] def __str__(self): return self.version_to_string() def _decode_data(self, data): """`data` is array.array""" self.major = data[0] if data[1] is 0xff: self.minor = data[1] elif data[1] <= 0x99: self.minor = int(data[1:2].tostring().decode('bcd+')) else: raise DecodingError() def version_to_string(self): return ''.join("%s.%s" % (self.major, self.minor)) python-ipmi-0.4.2/pyipmi/ipmitool.py0000775000372000037200000005366613574451473020411 0ustar travistravis00000000000000#!/usr/bin/env python # Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from __future__ import print_function import sys import getopt import logging import traceback from array import array from collections import namedtuple import pyipmi import pyipmi.interfaces Command = namedtuple('Command', 'name fn') CommandHelp = namedtuple('CommandHelp', 'name arguments help') def _print(s): print(s) def _get_command_function(name): for cmd in COMMANDS: if cmd.name == name: return cmd.fn return None def cmd_bmc_info(ipmi, args): device_id = ipmi.get_device_id() print(''' Device ID: %(device_id)s Device Revision: %(revision)s Firmware Revision: %(fw_revision)s IPMI Version: %(ipmi_version)s Manufacturer ID: %(manufacturer_id)d (0x%(manufacturer_id)04x) Product ID: %(product_id)d (0x%(product_id)04x) Device Available: %(available)d Provides SDRs: %(provides_sdrs)d Additional Device Support: '''[1:-1] % device_id.__dict__) functions = ( ('SENSOR', 'Sensor Device'), ('SDR_REPOSITORY', 'SDR Repository Device'), ('SEL', 'SEL Device'), ('FRU_INVENTORY', 'FRU Inventory Device'), ('IPMB_EVENT_RECEIVER', 'IPMB Event Receiver'), ('IPMB_EVENT_GENERATOR', 'IPMB Event Generator'), ('BRIDGE', 'Bridge'), ('CHASSIS', 'Chassis Device') ) for n, s in functions: if device_id.supports_function(n): print(' %s' % s) if device_id.aux is not None: print('Aux Firmware Rev Info: [{:s}]'.format( ' '.join('%02x' % d for d in device_id.aux))) def cmd_sel_clear(ipmi, args): ipmi.clear_sel() def cmd_sensor_rearm(ipmi, args): if len(args) < 1: return number = int(args[0], 0) ipmi.rearm_sensor_events(number) def sdr_show(ipmi, s): print("SDR record ID: 0x%04x" % s.id) print("SDR type: 0x%02x" % s.type) print("Device Id string: %s" % s.device_id_string) print("Entity: %s.%s" % (s.entity_id, s.entity_instance)) if s.type is pyipmi.sdr.SDR_TYPE_FULL_SENSOR_RECORD: (raw, states) = ipmi.get_sensor_reading(s.number, s.owner_lun) value = s.convert_sensor_raw_to_value(raw) if value is None: value = "na" t_unr = s.convert_sensor_raw_to_value(s.threshold['unr']) t_ucr = s.convert_sensor_raw_to_value(s.threshold['ucr']) t_unc = s.convert_sensor_raw_to_value(s.threshold['unc']) t_lnc = s.convert_sensor_raw_to_value(s.threshold['lnc']) t_lcr = s.convert_sensor_raw_to_value(s.threshold['lcr']) t_lnr = s.convert_sensor_raw_to_value(s.threshold['lnr']) print("Reading value: %s" % value) print("Reading state: 0x%x" % states) print("UNR: %s" % t_unr) print("UCR: %s" % t_ucr) print("UNC: %s" % t_unc) print("LNC: %s" % t_lnc) print("LCR: %s" % t_lcr) print("LNR: %s" % t_lnr) elif s.type is pyipmi.sdr.SDR_TYPE_COMPACT_SENSOR_RECORD: (raw, states) = ipmi.get_sensor_reading(s.number) print("Reading: %s" % raw) print("Reading state: 0x%x" % states) def cmd_sdr_show_raw(ipmi, args): if len(args) != 1: usage() return try: sdr = ipmi.get_device_sdr(int(args[0], 0)) print(' '.join(['0x%02x' % b for b in sdr.data])) except ValueError: print('') def cmd_sdr_show(ipmi, args): if len(args) != 1: usage() return try: s = ipmi.get_device_sdr(int(args[0], 0)) sdr_show(ipmi, s) except ValueError: print('') def cmd_sdr_show_all(ipmi, args): for s in ipmi.device_sdr_entries(): try: sdr_show(ipmi, s) except ValueError: print('') print("\n") def print_sdr_list_entry(record_id, number, id_string, value, states): if number: number = str(number) else: number = 'na' if states: states = hex(states) else: states = 'na' print("0x%04x | %3s | %-18s | %9s | %s" % (record_id, number, id_string, value, states)) def cmd_sdr_list(ipmi, args): iter_fct = None device_id = ipmi.get_device_id() if device_id.supports_function('sdr_repository'): iter_fct = ipmi.sdr_repository_entries elif device_id.supports_function('sensor'): iter_fct = ipmi.device_sdr_entries print("SDR-ID | | Device String |") print("=======|=====|====================|====================") for s in iter_fct(): try: number = None value = None states = None if s.type is pyipmi.sdr.SDR_TYPE_FULL_SENSOR_RECORD: (value, states) = ipmi.get_sensor_reading(s.number) number = s.number if value is not None: value = s.convert_sensor_raw_to_value(value) elif s.type is pyipmi.sdr.SDR_TYPE_COMPACT_SENSOR_RECORD: (value, states) = ipmi.get_sensor_reading(s.number) number = s.number print_sdr_list_entry(s.id, number, s.device_id_string, value, states) except pyipmi.errors.CompletionCodeError as e: if s.type in (pyipmi.sdr.SDR_TYPE_COMPACT_SENSOR_RECORD, pyipmi.sdr.SDR_TYPE_FULL_SENSOR_RECORD): print('0x{:04x} | {:3d} | {:18s} | ERR: CC=0x{:02x}'.format( s.id, s.number, s.device_id_string, e.cc)) def cmd_fru_print(ipmi, args): fru_id = 0 print_all = False if len(args) > 0: fru_id = int(args[0]) if len(args) > 1 and args[1] == 'all': print_all = True inv = ipmi.get_fru_inventory(fru_id) # Chassis Info Area area = inv.chassis_info_area if area: print(''' Chassis Info Area: Type: %(type)d Part Number: %(part_number)s Serial Number: %(serial_number)s '''[1:-1] % area.__dict__) if len(area.custom_chassis_info) != 0: print(' Custom Chassis Info Records:') for field in area.custom_chassis_info: print(' %s' % field) # Board Info Area area = inv.board_info_area if area: print(''' Board Info Area: Mfg. Date / Time: %(mfg_date)s Manufacturer: %(manufacturer)s Product Name: %(product_name)s Serial Number: %(serial_number)s Part Number: %(part_number)s FRU File ID: %(fru_file_id)s '''[1:-1] % area.__dict__) if len(area.custom_mfg_info) != 0: print(' Custom Board Info Records:') for field in area.custom_mfg_info: print(' %s' % field) # Product Info Area area = inv.product_info_area if area: print(''' Product Info Area: Manufacturer: %(manufacturer)s Name: %(name)s Part/Model Number: %(part_number)s Version: %(version)s Serial Number: %(serial_number)s Asset: %(asset_tag)s FRU File ID: %(fru_file_id)s '''[1:-1] % area.__dict__) if len(area.custom_mfg_info) != 0: print(' Custom Board Info Records:') for field in area.custom_mfg_info: print(' %s' % field) # Multirecords area = inv.multirecord_area if area: print('Multirecord Area:') if print_all: for record in area.records: print(' %s' % record) else: print(' Skipped. Use "print all"') def cmd_raw(ipmi, args): lun = 0 if len(args) > 1 and args[0] == 'lun': lun = int(args[1], 0) args = args[2:] if len(args) < 2: usage() return netfn = int(args[0], 0) raw_bytes = array('B', [int(d, 0) for d in args[1:]]) rsp = ipmi.raw_command(lun, netfn, raw_bytes.tostring()) print(' '.join('%02x' % d for d in array('B', rsp))) def cmd_hpm_capabilities(ipmi, args): cap = ipmi.get_target_upgrade_capabilities() for c in cap.components: properties = ipmi.get_component_properties(c) print("Component ID: %d" % c) for prop in properties: print(" %s" % prop) def cmd_hpm_check_file(ipmi, args): if len(args) < 1: return cap = ipmi.open_upgrade_image(args[0]) print(cap.header) for action in cap.actions: print(action) def cmd_hpm_install(ipmi, args): if len(args) < 2: print('missing argument') return ipmi.install_component_from_file(args[0], int(args[1])) def cmd_chassis_status(ipmi, args): status = ipmi.get_chassis_status() print(''' Power ON: %(power_on)s Overload: %(overload)s Interlock: %(interlock)s Fault: %(fault)s Ctrl Fault: %(control_fault)s Restore Policy: %(restore_policy)s '''[1:-1] % status.__dict__) for event in status.last_event: print(event) for state in status.chassis_state: print(state) def cmd_picmg_get_power(ipmi, args): pwr = ipmi.get_power_level(0, 0) print(pwr) def print_link_state(p, s): intf_str = pyipmi.picmg.LinkDescriptor().get_interface_string(p.interface) link_str = pyipmi.picmg.LinkDescriptor().get_link_type_string( p.type, p.extension, p.sig_class) print('CH=%02d INTF=%d FLAGS=0x%x TYPE=%d SIG=%d EXT=%d STATE=%d (%s/%s)' % (p.channel, p.interface, p.link_flags, p.type, p.sig_class, p.extension, s, intf_str, link_str)) def cmd_picmg_get_portstate_all(ipmi, args): for interface in range(3): for channel in range(16): try: (p, s) = ipmi.get_port_state(channel, interface) print_link_state(p, s) except pyipmi.errors.CompletionCodeError as e: if e.cc is 0xcc: continue def cmd_picmg_get_portstate(ipmi, args): if len(args) < 2: return channel = int(args[0]) interface = int(args[1]) (p, s) = ipmi.get_port_state(channel, interface) print_link_state(p, s) def cmd_picmg_frucontrol_cold_reset(ipmi, args): ipmi.fru_control_cold_reset(0) def usage(toplevel=False): commands = [] maxlen = 0 if toplevel: argv = [] else: argv = sys.argv[1:] # (1) try to find help for commands on exactly one level above for cmd in COMMAND_HELP: subcommands = cmd.name.split(' ') if (len(subcommands) == len(argv) + 1 and subcommands[:len(argv)] == argv): commands.append(cmd) if cmd.arguments: maxlen = max(maxlen, len(cmd.name)+len(cmd.arguments)+1) else: maxlen = max(maxlen, len(cmd.name)) # (2) if nothing found, try to find help on any level above if maxlen == 0: for cmd in COMMAND_HELP: subcommands = cmd.name.split(' ') if (len(subcommands) > len(argv) + 1 and subcommands[:len(argv)] == argv): commands.append(cmd) if cmd.arguments: maxlen = max(maxlen, len(cmd.name)+len(cmd.arguments)+1) else: maxlen = max(maxlen, len(cmd.name)) # (3) find help on same level if maxlen == 0: for cmd in COMMAND_HELP: subcommands = cmd.name.split(' ') if (len(subcommands) == len(argv) and subcommands[:len(argv)] == argv): commands.append(cmd) if cmd.arguments: maxlen = max(maxlen, len(cmd.name)+len(cmd.arguments)+1) else: maxlen = max(maxlen, len(cmd.name)) # if still nothing found, print toplevel usage if maxlen == 0: usage(toplevel=True) return if len(argv) == 0: version() print('usage: ipmitool [options...] ') print(''' Options: -t Set target IPMB address -b Set target channel -r Set target routing (not supported atm) -h Show this help -v Be verbose -V Print version -I Set interface (available: rmcp, aardvark, ipmitool) -H Set RMCP host -U Set RMCP user -P Set RMCP password -o Set interface specific options (name=value, separated by commas, see below for available options). '''[1:]) print(''' Aardvark interface options: serial= Serial number of the device pullups= Enable/disable pullups power= Enable/disable target power Ipmitool interface options: interface_type Set the interface type to be used (lan, lanplus, serial) '''[1:]) print('Commands:') for cmd in commands: name = cmd.name if cmd.arguments: name = '%s %s' % (name, cmd.arguments) print(' %-*s %s' % (maxlen, name, cmd.help)) def version(): print('ipmitool v%s' % pyipmi.__version__) def parse_interface_options(interface_name, options): if options: options = options.split(',') interface_options = {} for option in options: (name, value) = option.split('=', 1) if interface_name == 'aardvark': if name == 'serial': interface_options['serial_number'] = value elif (name, value) == ('pullups', 'on'): interface_options['enable_i2c_pullups'] = True elif (name, value) == ('pullups', 'off'): interface_options['enable_i2c_pullups'] = False elif (name, value) == ('power', 'on'): interface_options['enable_target_power'] = True elif (name, value) == ('power', 'off'): interface_options['enable_target_power'] = False else: print('Warning: unknown option %s' % name) elif interface_name == 'ipmitool': if name == 'interface_type': interface_options['interface_type'] = value else: print('Warning: unknown option %s' % name) return interface_options def main(): try: opts, args = getopt.getopt(sys.argv[1:], 't:hvVI:H:U:P:o:b:p:r:') except getopt.GetoptError as err: print(str(err)) usage() sys.exit(2) verbose = False interface_name = 'aardvark' target_address = 0x20 target_routing = None rmcp_host = None rmcp_port = 623 rmcp_user = '' rmcp_password = '' interface_options = list() for o, a in opts: if o == '-v': verbose = True elif o == '-h': usage() sys.exit() elif o == '-V': version() sys.exit() elif o == '-t': target_address = int(a, 0) elif o == '-b': target_routing = [(0x20, int(a), 0)] elif o == '-r': target_routing = a elif o == '-H': rmcp_host = a elif o == '-p': rmcp_port = int(a, 0) elif o == '-U': rmcp_user = a elif o == '-P': rmcp_password = a elif o == '-I': interface_name = a elif o == '-o': interface_options = a #interface_options = a.split(',') else: assert False, 'unhandled option' # fake sys.argv sys.argv = [sys.argv[0]] + args if len(args) == 0: usage() sys.exit(1) handler = logging.StreamHandler() if verbose: handler.setLevel(logging.DEBUG) else: handler.setLevel(logging.INFO) pyipmi.logger.add_log_handler(handler) pyipmi.logger.set_log_level(logging.DEBUG) for i in range(len(args)): cmd = _get_command_function(' '.join(args[0:i+1])) if cmd is not None: args = args[i+1:] break else: usage() sys.exit(1) interface_options = parse_interface_options(interface_name, interface_options) try: interface = pyipmi.interfaces.create_interface(interface_name, **interface_options) except RuntimeError as e: print(e) sys.exit(1) ipmi = pyipmi.create_connection(interface) ipmi.target = pyipmi.Target(target_address) if target_routing is not None: ipmi.target.set_routing(target_routing) if rmcp_host is not None: ipmi.session.set_session_type_rmcp(rmcp_host, rmcp_port) ipmi.session.set_auth_type_user(rmcp_user, rmcp_password) ipmi.session.establish() try: cmd(ipmi, args) except pyipmi.errors.CompletionCodeError as e: print('Command returned with completion code 0x%02x' % e.cc) if verbose: traceback.print_exc() sys.exit(1) except pyipmi.errors.IpmiTimeoutError as e: print('Command timed out') if verbose: traceback.print_exc() sys.exit(1) except KeyboardInterrupt as e: if verbose: traceback.print_exc() sys.exit(1) finally: if rmcp_host is not None: ipmi.session.close() COMMANDS = ( Command('bmc info', cmd_bmc_info), Command('bmc reset cold', lambda i, a: i.cold_reset()), Command('bmc reset warm', lambda i, a: i.warm_reset()), Command('sel list', lambda i, a: list(map(_print, i.sel_entries()))), Command('sel clear', cmd_sel_clear), Command('sensor rearm', cmd_sensor_rearm), Command('sdr list', cmd_sdr_list), Command('sdr raw', cmd_sdr_show_raw), Command('sdr show', cmd_sdr_show), Command('sdr showall', cmd_sdr_show_all), Command('fru print', cmd_fru_print), Command('picmg frucontrol cr', cmd_picmg_frucontrol_cold_reset), Command('picmg power get', cmd_picmg_get_power), Command('picmg portstate get', cmd_picmg_get_portstate), Command('picmg portstate getall', cmd_picmg_get_portstate_all), Command('raw', cmd_raw), Command('hpm capabilities', cmd_hpm_capabilities), Command('hpm check', cmd_hpm_check_file), Command('hpm install', cmd_hpm_install), Command('chassis status', cmd_chassis_status), Command('chassis power off', lambda i, a: i.chassis_control_power_down()), Command('chassis power on', lambda i, a: i.chassis_control_power_up()), Command('chassis power cycle', lambda i, a: i.chassis_control_power_cycle()), Command('chassis power reset', lambda i, a: i.chassis_control_hard_reset()), Command('chassis power diag', lambda i, a: i.chassis_control_power_diagnostic_interrupt()), Command('chassis power soft', lambda i, a: i.chassis_control_power_soft_shutdown()), ) COMMAND_HELP = ( CommandHelp('raw', None, 'Send a RAW IPMI request and print response'), CommandHelp('fru', None, 'Print built-in FRU and scan SDR for FRU locators'), CommandHelp('sensor', None, None), CommandHelp('sensor rearm', '', 'Rearm Sensor Events'), CommandHelp('sel', None, 'Print System Event Log (SEL)'), CommandHelp('sel list', None, 'List all SEL entries'), CommandHelp('sel clear', None, 'Clear SEL'), CommandHelp('sdr', None, 'Print Sensor Data Repository entries and readings'), CommandHelp('sdr list', None, 'List all SDRs'), CommandHelp('sdr raw', '', 'Show SDR raw data'), CommandHelp('sdr show', '', 'Show detail for one SDR'), CommandHelp('sdr showall', None, 'Show detail for all SDRs'), CommandHelp('bmc', None, 'Management Controller status and global enables'), CommandHelp('bmc info', None, 'BMC Device ID inforamtion'), CommandHelp('bmc reset', '', 'BMC reset control'), CommandHelp('picmg', None, 'PICMG commands'), CommandHelp('picmg frucontrol', '', 'Issue frucontrol'), CommandHelp('picmg power get', 'get PICMG power level', 'Request the power level'), CommandHelp('picmg portstate getall', '', 'Request all portstates for all interfaces'), CommandHelp('picmg portstate get', ' ', 'Request the portstate for an interface'), CommandHelp('hpm', None, 'HPM.1 commands'), CommandHelp('hpm capabilities', 'HPM.1 target upgrade capabilities', 'Request the target upgrade capabilities'), CommandHelp('hpm check', 'HPM.1 file check', 'Check the specified HPM.1 file'), CommandHelp('hpm install', ' ', 'Install the specified HPM.1 file to the controller'), CommandHelp('chassis', None, 'Get chassis status and set power state'), CommandHelp('chassis status', '', 'Get chassis status'), CommandHelp('chassis power', '', 'Set power state') ) if __name__ == '__main__': main() python-ipmi-0.4.2/pyipmi/utils.py0000664000372000037200000000746013574451473017701 0ustar travistravis00000000000000# Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import sys import codecs from array import array from .msgs import constants from .errors import DecodingError, CompletionCodeError def py3enc_unic_bytes_fix(dat): # python 3 unicode fix if isinstance(dat, str) and int(sys.version[0]) > 2: dat = dat.encode('raw_unicode_escape') return dat def py3dec_unic_bytes_fix(dat): # python 3 unicode fix if int(sys.version[0]) > 2: return dat.decode('raw_unicode_escape') return dat def bytes2(dat, enc): # python 2-3 workaround if int(sys.version[0]) > 2: return bytes(dat, enc) return dat def check_completion_code(cc): if cc != constants.CC_OK: raise CompletionCodeError(cc) def chunks(data, count): for i in range(0, len(data), count): yield data[i:i+count] class ByteBuffer(object): def __init__(self, data=None): if data is not None: self.array = array('B', data) else: self.array = array('B') def push_unsigned_int(self, value, length): for i in range(length): self.array.append((value >> (8*i) & 0xff)) def pop_unsigned_int(self, length): value = 0 for i in range(length): try: value |= self.array.pop(0) << (8*i) except IndexError: raise DecodingError('Data too short for message') return value def push_string(self, value): self.array.fromstring(value) def pop_string(self, length): string = self.array[0:length] del self.array[0:length] return string.tostring() # return py3dec_unic_bytes_fix(string.tostring()) def pop_slice(self, length): if len(self.array) < length: raise DecodingError('Data too short for message') c = ByteBuffer(self.array[0:length]) self.__delslice__(0, length) return c def tostring(self): return self.array.tostring() def extend(self, data): self.array.extend(data) def append_array(self, a): self.array.extend(a) def __getslice__(self, a, b): return self.array[a:b] def __delslice__(self, a, b): del self.array[a:b] def __len__(self): return len(self.array) def __getitem__(self, idx): return self.array[idx] BCD_MAP = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' ', '-', '.'] def bcd_encode(input, errors='strict'): raise NotImplementedError() def bcd_decode(encoded_input): chars = list() try: for data in encoded_input: if int(sys.version[0]) == 2: data = ord(data) chars.append(BCD_MAP[data >> 4 & 0xf] + BCD_MAP[data & 0xf]) return (''.join(chars), len(encoded_input) * 2) except IndexError: raise ValueError() def bcd_search(name): if name != 'bcd+': return None return codecs.CodecInfo(name='bcd+', encode=bcd_encode, decode=bcd_decode) def is_string(string): if sys.version_info[0] >= 3: return isinstance(string, str) return isinstance(string, basestring) python-ipmi-0.4.2/pyipmi/fru.py0000664000372000037200000003451513574451473017336 0ustar travistravis00000000000000# Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import array import codecs import datetime import os from .errors import DecodingError, CompletionCodeError from .msgs import constants from .utils import bcd_search, chunks codecs.register(bcd_search) class Fru(object): def __init__(self): self.write_length = 16 def get_fru_inventory_area_info(self, fru_id=0): rsp = self.send_message_with_name('GetFruInventoryAreaInfo', fru_id=fru_id) return rsp.area_size def write_fru_data(self, data, offset=0, fru_id=0): for chunk in chunks(data, self.write_length): write_rsp = self.send_message_with_name('WriteFruData', fru_id=fru_id, offset=offset, data=chunk) # check if device wrote the same number of bytes sent if write_rsp.count_written != len(chunk): raise Exception('sent {:} bytes but device wrote {:} bytes' .format(len(chunk), write_rsp.count_written)) offset += len(chunk) def read_fru_data(self, offset=None, count=None, fru_id=0): req_size = 32 data = array.array('B') # first check for maximum area size if offset is None: area_size = self.get_fru_inventory_area_info(fru_id) off = 0 else: area_size = offset + count off = offset while off < area_size: if (off + req_size) > area_size: req_size = area_size - off try: rsp = self.send_message_with_name('ReadFruData', fru_id=fru_id, offset=off, count=req_size) except CompletionCodeError as ex: if ex.cc in (constants.CC_CANT_RET_NUM_REQ_BYTES, constants.CC_REQ_DATA_FIELD_EXCEED, constants.CC_PARAM_OUT_OF_RANGE): req_size -= 2 if req_size <= 0: raise continue else: raise data.extend(rsp.data) off += rsp.count return data.tostring() def get_fru_inventory(self, fru_id=0): return FruInventory(self.read_fru_data(fru_id=fru_id)) def get_fru_inventory_from_file(filename): try: file = open(filename, "rb") except IOError: print('Error open file "%s"' % filename) ################################ # get file size file_size = os.stat(filename).st_size file_data = file.read(file_size) data = array.array('B', file_data) file.close() return FruInventory(data) class FruDataField(object): TYPE_BINARY = 0 TYPE_BCD_PLUS = 1 TYPE_6BIT_ASCII = 2 TYPE_ASCII_OR_UTF16 = 3 def __init__(self, data=None, offset=0, force_lang_english=False): if data: self._from_data(data, offset, force_lang_english) def __str__(self): if self.field_type is FruDataField.TYPE_BINARY: return ' '.join('%02x' % b for b in self.raw) else: return self.value.replace('\x00', '') def _from_data(self, data, offset=0, force_lang_english=False): self.offset = offset self.field_type = data[offset] >> 6 & 0x3 self.length = data[offset] & 0x3f self.raw = data[offset+1:offset+1+self.length] chr_data = ''.join([chr(c) for c in self.raw]) if self.field_type == self.TYPE_BCD_PLUS: self.value = chr_data.decode('bcd+') elif self.field_type == self.TYPE_6BIT_ASCII: self.value = chr_data.decode('6bitascii') else: self.value = chr_data CUSTOM_FIELD_END = 0xc1 def _decode_custom_fields(data): offset = 0 fields = [] while data[offset] != CUSTOM_FIELD_END: field = FruDataField(data, offset) fields.append(field) offset += field.length + 1 return fields class FruData(object): def __init__(self, data=None): if data: if isinstance(data, str): data = [ord(c) for c in data] self.data = data if hasattr(self, '_from_data'): self._from_data(data) class InventoryCommonHeader(FruData): def _from_data(self, data): if len(data) != 8: raise DecodingError('InventoryCommonHeader length != 8') self.format_version = data[0] & 0x0f self.internal_use_area_offset = data[1] * 8 or None self.chassis_info_area_offset = data[2] * 8 or None self.board_info_area_offset = data[3] * 8 or None self.product_info_area_offset = data[4] * 8 or None self.multirecord_area_offset = data[5] * 8 or None if sum(data) % 256 != 0: raise DecodingError('InventoryCommonHeader checksum failed') class CommonInfoArea(FruData): def _from_data(self, data): self.format_version = data[0] & 0x0f if self.format_version != 1: raise DecodingError('unsupported format version (%d)' % self.format_version) self.length = data[1] * 8 if sum(data[:self.length]) % 256 != 0: raise DecodingError('checksum failed') class InventoryChassisInfoArea(CommonInfoArea): TYPE_OTHER = 1 TYPE_UNKNOWN = 2 TYPE_DESKTOP = 3 TYPE_LOW_PROFILE_DESKTOP = 4 TYPE_PIZZA_BOX = 5 TYPE_MINI_TOWER = 6 TYPE_TOWER = 7 TYPE_PORTABLE = 8 TYPE_LAPTOP = 9 TYPE_NOTEBOOK = 10 TYPE_HAND_HELD = 11 TYPE_DOCKING_STATION = 12 TYPE_ALL_IN_ONE = 13 TYPE_SUB_NOTEBOOK = 14 TYPE_SPACE_SAVING = 15 TYPE_LUNCH_BOX = 16 TYPE_MAIN_SERVER_CHASSIS = 17 TYPE_EXPANSION_CHASSIS = 18 TYPE_SUB_CHASSIS = 19 TYPE_BUS_EXPANSION_CHASSIS = 20 TYPE_PERIPHERAL_CHASSIS = 21 TYPE_RAID_CHASSIS = 22 TYPE_RACK_MOUNT_CHASSIS = 23 def _from_data(self, data): CommonInfoArea._from_data(self, data) self.type = data[2] offset = 3 self.part_number = FruDataField(data, offset) offset += self.part_number.length + 1 self.serial_number = FruDataField(data, offset, True) offset += self.serial_number.length + 1 self.custom_chassis_info = _decode_custom_fields(data[offset:]) class InventoryBoardInfoArea(CommonInfoArea): def _from_data(self, data): CommonInfoArea._from_data(self, data) self.language_code = data[2] minutes = data[5] << 16 | data[4] << 8 | data[3] self.mfg_date = (datetime.datetime(1996, 1, 1) + datetime.timedelta(minutes=minutes)) offset = 6 self.manufacturer = FruDataField(data, offset) offset += self.manufacturer.length + 1 self.product_name = FruDataField(data, offset) offset += self.product_name.length + 1 self.serial_number = FruDataField(data, offset, True) offset += self.serial_number.length + 1 self.part_number = FruDataField(data, offset) offset += self.part_number.length + 1 self.fru_file_id = FruDataField(data, offset, True) offset += self.fru_file_id.length + 1 self.custom_mfg_info = _decode_custom_fields(data[offset:]) class InventoryProductInfoArea(CommonInfoArea): def _from_data(self, data): CommonInfoArea._from_data(self, data) self.language_code = data[2] offset = 3 self.manufacturer = FruDataField(data, offset) offset += self.manufacturer.length + 1 self.name = FruDataField(data, offset) offset += self.name.length + 1 self.part_number = FruDataField(data, offset) offset += self.part_number.length + 1 self.version = FruDataField(data, offset) offset += self.version.length + 1 self.serial_number = FruDataField(data, offset, True) offset += self.serial_number.length + 1 self.asset_tag = FruDataField(data, offset) offset += self.asset_tag.length + 1 self.fru_file_id = FruDataField(data, offset, True) offset += self.fru_file_id.length + 1 self.custom_mfg_info = list() self.custom_mfg_info = _decode_custom_fields(data[offset:]) class FruDataMultiRecord(FruData): TYPE_POWER_SUPPLY_INFORMATION = 0 TYPE_DC_OUTPUT = 1 TYPE_DC_LOAD = 2 TYPE_MANAGEMENT_ACCESS_RECORD = 3 TYPE_BASE_COMPATIBILITY_RECORD = 4 TYPE_EXTENDED_COMPATIBILITY_RECORD = 5 TYPE_OEM = list(range(0x0c, 0x100)) TYPE_OEM_PICMG = 0xc0 def __str__(self): return '%02x: %s' % (self.record_type_id, ' '.join('%02x' % b for b in self.raw)) def _from_data(self, data): if len(data) < 5: raise DecodingError('data too short') self.record_type_id = data[0] self.format_version = data[1] & 0x0f self.end_of_list = bool(data[1] & 0x80) self.length = data[2] if sum(data[:5]) % 256 != 0: raise DecodingError('FruDataMultiRecord header checksum failed') self.raw = data[5:5+self.length] if (sum(self.raw) + data[3]) % 256 != 0: raise DecodingError('FruDataMultiRecord record checksum failed') @staticmethod def create_from_record_id(data): if data[0] == FruDataMultiRecord.TYPE_OEM_PICMG: return FruPicmgRecord.create_from_record_id(data) else: return FruDataUnknown(data) class FruDataUnknown(FruDataMultiRecord): """This class is used to indicate undecoded picmg record.""" pass class FruPicmgRecord(FruDataMultiRecord): PICMG_RECORD_ID_BACKPLANE_PTP_CONNECTIVITY = 0x04 PICMG_RECORD_ID_ADDRESS_TABLE = 0x10 PICMG_RECORD_ID_SHELF_POWER_DISTRIBUTION = 0x11 PICMG_RECORD_ID_SHMC_ACTIVATION_MANAGEMENT = 0x12 PICMG_RECORD_ID_SHMC_IP_CONNECTION = 0x13 PICMG_RECORD_ID_BOARD_PTP_CONNECTIVITY = 0x14 PICMG_RECORD_ID_RADIAL_IPMB0_LINK_MAPPING = 0x15 PICMG_RECORD_ID_MODULE_CURRENT_REQUIREMENTS = 0x16 PICMG_RECORD_ID_CARRIER_ACTIVATION_MANAGEMENT = 0x17 PICMG_RECORD_ID_CARRIER_PTP_CONNECTIVITY = 0x18 PICMG_RECORD_ID_AMC_PTP_CONNECTIVITY = 0x19 PICMG_RECORD_ID_CARRIER_INFORMATION = 0x1a PICMG_RECORD_ID_MTCA_FRU_INFORMATION_PARTITION = 0x20 PICMG_RECORD_ID_MTCA_CARRIER_MANAGER_IP_LINK = 0x21 PICMG_RECORD_ID_MTCA_CARRIER_INFORMATION = 0x22 PICMG_RECORD_ID_MTCA_SHELF_INFORMATION = 0x23 PICMG_RECORD_ID_MTCA_SHELF_MANAGER_IP_LINK = 0x24 PICMG_RECORD_ID_MTCA_CARRIER_POWER_POLICY = 0x25 PICMG_RECORD_ID_MTCA_CARRIER_ACTIVATION_AND_POWER = 0x26 PICMG_RECORD_ID_MTCA_POWER_MODULE_CAPABILITY = 0x27 PICMG_RECORD_ID_MTCA_FAN_GEOGRAPHY = 0x28 PICMG_RECORD_ID_OEM_MODULE_DESCRIPTION = 0x29 PICMG_RECORD_ID_CARRIER_CLOCK_PTP_CONNECTIVITY = 0x2C PICMG_RECORD_ID_CLOCK_CONFIGURATION = 0x2d PICMG_RECORD_ID_ZONE_3_INTERFACE_COMPATIBILITY = 0x30 PICMG_RECORD_ID_CARRIER_BUSED_CONNECTIVITY = 0x31 PICMG_RECORD_ID_ZONE_3_INTERFACE_DOCUMENTATION = 0x32 def __init__(self, data): FruDataMultiRecord.__init__(self, data) @staticmethod def create_from_record_id(data): picmg_record = FruPicmgRecord(data) if picmg_record.picmg_record_type_id ==\ FruPicmgRecord.PICMG_RECORD_ID_MTCA_POWER_MODULE_CAPABILITY: return FruPicmgPowerModuleCapabilityRecord(data) return FruPicmgRecord(data) def _from_data(self, data): if len(data) < 10: raise DecodingError('data too short') data = array.array('B', data) FruDataMultiRecord._from_data(self, data) self.manufacturer_id = \ data[5] | data[6] << 8 | data[7] << 16 self.picmg_record_type_id = data[8] self.format_version = data[9] class FruPicmgPowerModuleCapabilityRecord(FruPicmgRecord): def _from_data(self, data): if len(data) < 12: raise DecodingError('data too short') FruPicmgRecord._from_data(self, data) maximum_current_output = ord(data[10]) | ord(data[11]) << 8 self.maximum_current_output = float(maximum_current_output/10) class InventoryMultiRecordArea(object): def __init__(self, data): if data: self._from_data(data) def _from_data(self, data): self.records = list() offset = 0 while True: record = FruDataMultiRecord.create_from_record_id(data[offset:]) self.records.append(record) offset += record.length + 5 if record.end_of_list: break class FruInventory(object): def __init__(self, data=None): self.chassis_info_area = None self.board_info_area = None self.product_info_area = None self.multirecord_area = None if data: self._from_data(data) def _from_data(self, data): self.raw = data self.common_header = InventoryCommonHeader(data[:8]) if self.common_header.chassis_info_area_offset: self.chassis_info_area = InventoryChassisInfoArea( data[self.common_header.chassis_info_area_offset:]) if self.common_header.board_info_area_offset: self.board_info_area = InventoryBoardInfoArea( data[self.common_header.board_info_area_offset:]) if self.common_header.product_info_area_offset: self.product_info_area = InventoryProductInfoArea( data[self.common_header.product_info_area_offset:]) if self.common_header.multirecord_area_offset: self.multirecord_area = InventoryMultiRecordArea( data[self.common_header.multirecord_area_offset:]) python-ipmi-0.4.2/pyipmi/messaging.py0000664000372000037200000000513313574451473020511 0ustar travistravis00000000000000# Copyright (c) 2016 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from .session import Session from .msgs import create_request_by_name from .utils import check_completion_code from .state import State class Messaging(object): def get_channel_authentication_capabilities(self, channel, priv_lvl): req = create_request_by_name('GetChannelAuthenticationCapabilities') req.channel.number = channel req.privilege_level.requested = priv_lvl rsp = self.send_and_receive(req) check_completion_code(rsp.completion_code) caps = ChannelAuthenticationCapabilities(rsp) return caps class ChannelAuthenticationCapabilities(State): _functions = { 'none': Session.AUTH_TYPE_NONE, 'md2': Session.AUTH_TYPE_MD2, 'md5': Session.AUTH_TYPE_MD5, 'straight': Session.AUTH_TYPE_PASSWORD, 'oem_proprietary': Session.AUTH_TYPE_OEM, } def _from_response(self, rsp): self.channel= rsp.channel_number self.auth_types = [] self.ipmi_1_5 = False self.ipmi_2_0 = False if rsp.support.ipmi_2_0: self.ipmi_2_0 = True else: self.ipmi_1_5 = True for function in self._functions.keys(): if hasattr(rsp.support, function): if getattr(rsp.support, function): self.auth_types.append(function) def get_max_auth_type(self): for auth_type in ('md5', 'md2', 'straight', 'oem_proprietary', 'none'): if auth_type in self.auth_types: return self._functions[auth_type] return None def __str__(self): s = 'Authentication Capabilities:\n' s += ' IPMI v1.5: %s\n' % self.ipmi_1_5 s += ' IPMI v2.0: %s\n' % self.ipmi_2_0 s += ' Auth. types: %s\n' % ' '.join(self.auth_types) s += ' Max Auth. type: %s\n' % self.get_max_auth_type() return s python-ipmi-0.4.2/pyipmi/event.py0000664000372000037200000000300113574451473017645 0ustar travistravis00000000000000# Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from .utils import check_completion_code from .msgs import create_request_by_name EVENT_ASSERTION = 0 EVENT_DEASSERTION = 1 class Event(object): def set_event_receiver(self, ipmb_address, lun): req = create_request_by_name('SetEventReceiver') req.event_receiver.ipmb_i2c_slave_address = ipmb_address req.event_receiver.lun = lun rsp = self.send_message(req) check_completion_code(rsp.completion_code) def get_event_receiver(self): req = create_request_by_name('GetEventReceiver') rsp = self.send_message(req) check_completion_code(rsp.completion_code) ipmb_address = rsp.event_receiver.ipmb_i2c_slave_address lun = rsp.event_receiver.lun return (ipmb_address, lun) python-ipmi-0.4.2/pyipmi/version.py0000664000372000037200000000010013574451533020203 0ustar travistravis00000000000000# This file was autogenerated by setup.py __version__ = '0.4.2' python-ipmi-0.4.2/pyipmi/picmg.py0000664000372000037200000004435713574451473017646 0ustar travistravis00000000000000# Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from .errors import DecodingError, EncodingError from .msgs import create_request_by_name from .msgs import picmg from .utils import check_completion_code from .state import State from .msgs.picmg import \ FRU_CONTROL_COLD_RESET, FRU_CONTROL_WARM_RESET, \ FRU_CONTROL_GRACEFUL_REBOOT, FRU_CONTROL_ISSUE_DIAGNOSTIC_INTERRUPT, \ FRU_ACTIVATION_FRU_ACTIVATE, FRU_ACTIVATION_FRU_DEACTIVATE class Picmg(object): def get_picmg_properties(self): return self.send_message_with_name('GetPicmgProperties') def fru_control(self, fru_id, option): rsp = self.send_message_with_name('FruControl', fru_id=fru_id, option=option) return rsp.rsp_data def fru_control_cold_reset(self, fru_id=0): self.fru_control(fru_id, FRU_CONTROL_COLD_RESET) def fru_control_warm_reset(self, fru_id=0): self.fru_control(fru_id, FRU_CONTROL_WARM_RESET) def fru_control_graceful_reboot(self, fru_id=0): self.fru_control(fru_id, FRU_CONTROL_GRACEFUL_REBOOT) def fru_control_diagnostic_interrupt(self, fru_id=0): return self.fru_control(fru_id, FRU_CONTROL_ISSUE_DIAGNOSTIC_INTERRUPT) def get_power_level(self, fru_id, power_type): rsp = self.send_message_with_name('GetPowerLevel', fru_id=fru_id, power_type=power_type) return PowerLevel(rsp) def get_fan_speed_properties(self, fru_id): rsp = self.send_message_with_name('GetFanSpeedProperties', fru_id=fru_id) return FanSpeedProperties(rsp) def set_fan_level(self, fru_id, fan_level): self.send_message_with_name('SetFanLevel', fru_id=fru_id, fan_level=fan_level) def get_fan_level(self, fru_id): rsp = self.send_message_with_name('GetFanLevel', fru_id=fru_id) local_control_fan_level = None if rsp.data: local_control_fan_level = rsp.data[0] return (rsp.override_fan_level, local_control_fan_level) def get_led_state(self, fru_id, led_id): rsp = self.send_message_with_name('GetFruLedState', fru_id=fru_id, led_id=led_id) return LedState(rsp) def set_led_state(self, led): req = create_request_by_name('SetFruLedState') req = led.to_request(req) rsp = self.send_message(req) check_completion_code(rsp.completion_code) def _set_fru_activation(self, fru_id, control): self.send_message_with_name('SetFruActivation', fru_id=fru_id, control=control) def set_fru_activation(self, fru_id): self._set_fru_activation(fru_id, FRU_ACTIVATION_FRU_ACTIVATE) def set_fru_deactivation(self, fru_id): self._set_fru_activation(fru_id, FRU_ACTIVATION_FRU_DEACTIVATE) ACTIVATION_LOCK_SET = 0 ACTIVATION_LOCK_CLEAR = 1 DEACTIVATION_LOCK_SET = 2 DEACTIVATION_LOCK_CLEAR = 3 def set_fru_activation_policy(self, fru_id, ctrl): req = create_request_by_name('SetFruActivationPolicy') req.fru_id = fru_id if ctrl == self.ACTIVATION_LOCK_SET: req.mask.activation_locked = 1 req.set.activation_locked = 1 elif ctrl == self.ACTIVATION_LOCK_CLEAR: req.mask.activation_locked = 1 req.set.activation_locked = 0 elif ctrl == self.DEACTIVATION_LOCK_SET: req.mask.deactivation_locked = 1 req.set.deactivation_locked = 1 elif ctrl == self.DEACTIVATION_LOCK_CLEAR: req.mask.deactivation_locked = 1 req.set.deactivation_locked = 0 rsp = self.send_message(req) check_completion_code(rsp.completion_code) def set_fru_activation_lock(self, fru_id): self.set_fru_activation_policy(fru_id, self.ACTIVATION_LOCK_SET) def clear_fru_activation_lock(self, fru_id): self.set_fru_activation_policy(fru_id, self.ACTIVATION_LOCK_CLEAR) def set_fru_deactivation_lock(self, fru_id): self.set_fru_activation_policy(fru_id, self.DEACTIVATION_LOCK_SET) def clear_fru_deactivation_lock(self, fru_id): self.set_fru_activation_policy(fru_id, self.DEACTIVATION_LOCK_CLEAR) def set_port_state(self, link_descr, state): req = create_request_by_name('SetPortState') req.link_info.channel = link_descr.channel req.link_info.interface = link_descr.interface req.link_info.port_0 = (link_descr.link_flags >> 0) & 1 req.link_info.port_1 = (link_descr.link_flags >> 1) & 1 req.link_info.port_2 = (link_descr.link_flags >> 2) & 1 req.link_info.port_3 = (link_descr.link_flags >> 3) & 1 req.link_info.type = link_descr.type req.link_info.sig_class = link_descr.sig_class req.link_info.type_extension = link_descr.extension req.link_info.grouping_id = link_descr.grouping_id req.state = state rsp = self.send_message(req) check_completion_code(rsp.completion_code) def get_port_state(self, channel_number, channel_interface): req = create_request_by_name('GetPortState') req.channel.number = channel_number req.channel.interface = channel_interface rsp = self.send_message(req) check_completion_code(rsp.completion_code) if len(rsp.data) > 4: link = LinkDescriptor() link.channel = rsp.data[0] & 0x3F link.interface = rsp.data[0] >> 6 & 0x3 link.link_flags = rsp.data[1] & 0xf link.type = rsp.data[1] >> 4 & 0xf link.sig_class = rsp.data[2] & 0xf link.extension = rsp.data[2] >> 4 & 0xf link.grouping_id = rsp.data[3] state = rsp.data[4] return (link, state) def get_pm_global_status(self): rsp = self.send_message_with_name('GetPowerChannelStatus', starting_power_channel_number=1, power_channel_count=1) return GlobalStatus(rsp) def get_power_channel_status(self, start): rsp = self.send_message_with_name('GetPowerChannelStatus', starting_power_channel_number=start, power_channel_count=1) return PowerChannelStatus(rsp) def set_signaling_class(self, interface, channel, signaling_class): req = create_request_by_name('SetSignalingClass') req.channel_info.channel_number = channel req.channel_info.interface = interface req.channel_signaling.class_capability = signaling_class rsp = self.send_message(req) check_completion_code(rsp.completion_code) def get_signaling_class(self, interface, channel): req = create_request_by_name('GetSignalingClass') req.channel_info.channel_number = channel req.channel_info.interface = interface rsp = self.send_message(req) check_completion_code(rsp.completion_code) return rsp.channel_signaling.class_capability class LinkDescriptor(State): # TODO dont duplicate exports, import them instead INTERFACE_BASE = picmg.LINK_INTERFACE_BASE INTERFACE_FABRIC = picmg.LINK_INTERFACE_FABRIC INTERFACE_UPDATE_CHANNEL = picmg.LINK_INTERFACE_UPDATE_CHANNEL TYPE_BASE = picmg.LINK_TYPE_BASE TYPE_ETHERNET_FABRIC = picmg.LINK_TYPE_ETHERNET_FABRIC TYPE_INFINIBAND_FABRIC = picmg.LINK_TYPE_INFINIBAND_FABRIC TYPE_STARFABRIC_FABRIC = picmg.LINK_TYPE_STARFABRIC_FABRIC TYPE_PCIEXPRESS_FABRIC = picmg.LINK_TYPE_PCIEXPRESS_FABRIC TYPE_OEM0 = picmg.LINK_TYPE_OEM0 TYPE_OEM1 = picmg.LINK_TYPE_OEM1 TYPE_OEM2 = picmg.LINK_TYPE_OEM2 TYPE_OEM3 = picmg.LINK_TYPE_OEM3 TYPE_EXT_BASE0 = picmg.LINK_TYPE_EXT_BASE0 TYPE_EXT_BASE1 = picmg.LINK_TYPE_EXT_BASE1 SIGNALING_CLASS_BASIC = picmg.LINK_SIGNALING_CLASS_BASIC SIGNALING_CLASS_10_3125_GBD = picmg.LINK_SIGNALING_CLASS_10_3125_GBD TYPE_EXT_ETHERNET_FIX1000_BX = picmg.LINK_TYPE_EXT_ETHERNET_FIX1000_BX TYPE_EXT_ETHERNET_FIX10G_BX4 = picmg.LINK_TYPE_EXT_ETHERNET_FIX10G_BX4 TYPE_EXT_ETHERNET_FCPI = picmg.LINK_TYPE_EXT_ETHERNET_FCPI TYPE_EXT_ETHERNET_FIX1000_KX = picmg.LINK_TYPE_EXT_ETHERNET_FIX1000_KX TYPE_EXT_ETHERNET_FIX10G_KX4 = picmg.LINK_TYPE_EXT_ETHERNET_FIX10G_KX4 TYPE_EXT_ETHERNET_FIX10G_KR = picmg.LINK_TYPE_EXT_ETHERNET_FIX10G_KR TYPE_EXT_ETHERNET_FIX40G_KR4 = picmg.LINK_TYPE_EXT_ETHERNET_FIX40G_KR4 TYPE_EXT_OEM_LINK_TYPE_EXT_0 = picmg.LINK_TYPE_EXT_OEM_LINK_TYPE_EXT_0 FLAGS_LANE0 = picmg.LINK_FLAGS_LANE0 FLAGS_LANE0123 = picmg.LINK_FLAGS_LANE0123 STATE_DISABLE = picmg.LINK_STATE_DISABLE STATE_ENABLE = picmg.LINK_STATE_ENABLE __properties__ = [ # (propery, description) ('channel', ''), ('interface', ''), ('link_flags', ''), ('type', ''), ('sig_class', ''), ('extension', ''), ('grouping_id', ''), ] INTERFACE_DESCR_STRING = [ # Interface, 'STRING' (INTERFACE_BASE, 'Base'), (INTERFACE_FABRIC, 'Fabric'), (INTERFACE_UPDATE_CHANNEL, 'Update Channel'), ] def get_interface_string(self, interf): for desc in self.INTERFACE_DESCR_STRING: if desc[0] == interf: return desc[1] return 'unknown' LINK_TYPE_DESCR_STRING = [ # Type, Extension, class, 'STRING' (TYPE_BASE, TYPE_EXT_BASE0, SIGNALING_CLASS_BASIC, '10/100/1000 BASE-T'), (TYPE_BASE, TYPE_EXT_BASE1, SIGNALING_CLASS_BASIC, '10/100 BASE-T ShMC Cross-connect'), (TYPE_ETHERNET_FABRIC, TYPE_EXT_ETHERNET_FIX1000_BX, SIGNALING_CLASS_BASIC, 'Fixed 1000BASE-BX'), (TYPE_ETHERNET_FABRIC, TYPE_EXT_ETHERNET_FIX10G_BX4, SIGNALING_CLASS_BASIC, 'Fixed 10GBASE-BX4 (XAUI)'), (TYPE_ETHERNET_FABRIC, TYPE_EXT_ETHERNET_FCPI, SIGNALING_CLASS_BASIC, 'FC-PI'), (TYPE_ETHERNET_FABRIC, TYPE_EXT_ETHERNET_FIX1000_KX, SIGNALING_CLASS_BASIC, 'Fixed 1000BASE-KX'), (TYPE_ETHERNET_FABRIC, TYPE_EXT_ETHERNET_FIX10G_KX4, SIGNALING_CLASS_BASIC, 'Fixed 10GBASE-KX4'), (TYPE_ETHERNET_FABRIC, TYPE_EXT_ETHERNET_FIX10G_KR, SIGNALING_CLASS_10_3125_GBD, 'Fixed 10GBASE-KR'), (TYPE_ETHERNET_FABRIC, TYPE_EXT_ETHERNET_FIX40G_KR4, SIGNALING_CLASS_10_3125_GBD, 'Fixed 40GBASE-KR4'), ] def get_link_type_string(self, link_type, ext, cls=0): for desc in self.LINK_TYPE_DESCR_STRING: if desc[0] == link_type and desc[1] == ext and desc[2] == cls: return desc[3] return 'unknown' class PowerLevel(State): def _from_response(self, rsp): self.dynamic_power_configuration = \ rsp.properties.dynamic_power_configuration self.power_level = rsp.properties.power_level self.delay_to_stable = rsp.delay_to_stable_power self.power_mulitplier = rsp.power_multiplier self.power_levels = rsp.power_draw class FanSpeedProperties(State): def _from_response(self, rsp): self.minimum_speed_level = rsp.minimum_speed_level self.maximum_speed_level = rsp.maximum_speed_level self.normal_operation_level = rsp.normal_operation_level self.local_control_supported = rsp.properties.local_control_supported class LedState(State): COLOR_BLUE = picmg.LED_COLOR_BLUE COLOR_RED = picmg.LED_COLOR_RED COLOR_GREEN = picmg.LED_COLOR_GREEN COLOR_AMBER = picmg.LED_COLOR_AMBER COLOR_ORANGE = picmg.LED_COLOR_ORANGE COLOR_WHITE = picmg.LED_COLOR_WHITE FUNCTION_OFF = 1 FUNCTION_BLINKING = 2 FUNCTION_ON = 3 FUNCTION_LAMP_TEST = 4 __properties__ = [ # (propery, description) ('fru_id', ''), ('led_id', ''), ('local_state_available', ''), ('override_enabled', ''), ('lamp_test_enabled', ''), ('local_function', ''), ('local_off_duration', ''), ('local_on_duration', ''), ('local_color', ''), ('override_function', ''), ('override_off_duration', ''), ('override_on_duration', ''), ('override_color', ''), ('lamp_test_duration', ''), ] def __init__(self, rsp=None, fru_id=None, led_id=None, color=None, function=None): super(LedState, self).__init__(rsp) if fru_id is not None: self.fru_id = fru_id if led_id is not None: self.led_id = led_id if color is not None: self.override_color = color if function is not None: self.override_function = function def __str__(self): string = '[flags ' string += self.local_state_available and ' LOCAL_STATE' or '' string += self.override_enabled and ' OVR_EN' or '' string += self.lamp_test_enabled and ' LAMP_TEST_EN' or '' if not self.local_state_available and not self.override_enabled \ and not self.lamp_test_enabled: string += ' NONE' if self.local_state_available: string += ' local_function %s local_color %s' % ( self.local_function, self.local_color) if self.override_enabled: string += ' override_function %s override_color %s' % ( self.override_function, self.override_color) string += ']' return string def _from_response(self, res): self.local_state_available = bool(res.led_states.local_avail) self.override_enabled = bool(res.led_states.override_en) self.lamp_test_enabled = bool(res.led_states.lamp_test_en) if res.local_function == picmg.LED_FUNCTION_OFF: self.local_function = self.FUNCTION_OFF elif res.local_function == picmg.LED_FUNCTION_ON: self.local_function = self.FUNCTION_ON elif res.local_function in picmg.LED_FUNCTION_BLINKING_RANGE: self.local_function = self.FUNCTION_BLINKING self.local_off_duration = res.local_function * 10 if res.local_on_duration not in picmg.LED_FUNCTION_BLINKING_RANGE: raise DecodingError() self.local_on_duration = res.local_on_duration * 10 else: raise DecodingError() self.local_color = res.local_color if self.override_enabled: if res.override_function == picmg.LED_FUNCTION_OFF: self.override_function = self.FUNCTION_OFF elif res.override_function == picmg.LED_FUNCTION_ON: self.override_function = self.FUNCTION_ON elif res.override_function in picmg.LED_FUNCTION_BLINKING_RANGE: self.override_function = self.FUNCTION_BLINKING self.override_off_duration = res.local_function * 10 else: raise DecodingError() self.override_off_duration = res.override_on_duration * 10 self.override_color = res.override_color if self.lamp_test_enabled: self.lamp_test_duration = res.lamp_test_duration * 100 def to_request(self, req): req.fru_id = self.fru_id req.led_id = self.led_id req.color = self.override_color if self.override_function == self.FUNCTION_ON: req.led_function = picmg.LED_FUNCTION_ON req.on_duration = 0 elif self.override_function == self.FUNCTION_OFF: req.led_function = picmg.LED_FUNCTION_OFF req.on_duration = 0 elif self.override_function == self.FUNCTION_BLINKING: if self.override_off_duration not in \ picmg.LED_FUNCTION_BLINKING_RANGE: raise EncodingError() req.led_function = self.override_off_duration req.on_duration = self.override_on_duration elif self.override_function == self.FUNCTION_LAMP_TEST: req.led_function = picmg.LED_FUNCTION_LAMP_TEST req.on_duration = self.lamp_test_duration else: raise AssertionError() return req class GlobalStatus(State): __properties__ = [ # (propery, description) ('role', ''), ('management_power_good', ''), ('payload_power_good', ''), ('unidentified_fault', ''), ] def _from_response(self, rsp): self.role = rsp.global_status.role self.management_power_good = \ bool(rsp.global_status.management_power_good) self.payload_power_good = \ bool(rsp.global_status.payload_power_good) self.unidentified_fault = \ bool(rsp.global_status.unidentified_fault) class PowerChannelStatus(State): __properties__ = [ # (propery, description) ('present', ''), ('management_power', ''), ('management_power_overcurrent', ''), ('enable', ''), ('payload_power', ''), ('payload_power_overcurrent', ''), ('pwr_on', ''), ] def _from_response(self, rsp): data = rsp.data[0] self.present = (data >> 0) & 1 self.management_power = (data >> 1) & 1 self.management_power_overcurrent = (data >> 2) & 1 self.enable = (data >> 3) & 1 self.payload_power = (data >> 4) & 1 self.payload_power_overcurrent = (data >> 5) & 1 self.pwr_on = (data >> 6) & 1 python-ipmi-0.4.2/pyipmi/interfaces/0000775000372000037200000000000013574451533020300 5ustar travistravis00000000000000python-ipmi-0.4.2/pyipmi/interfaces/aardvark.py0000664000372000037200000001525713574451473022462 0ustar travistravis00000000000000# Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import time from array import array from ..msgs import create_message, encode_message, decode_message from ..errors import IpmiTimeoutError from ..logger import log from ..interfaces.ipmb import IpmbHeaderReq, checksum, rx_filter, encode_ipmb_msg try: import pyaardvark except ImportError: # python 2 pyaardvark = None except RuntimeError: # python 3 pyaardvark = None class Aardvark(object): NAME = 'aardvark' def __init__(self, slave_address=0x20, port=0, serial_number=None, enable_i2c_pullups=None, enable_target_power=None): if pyaardvark is None: raise RuntimeError('No pyaardvark module found. You can not ' 'use this interface.') self.slave_address = slave_address self.timeout = 0.25 self.max_retries = 3 self.next_sequence_number = 0 self._dev = pyaardvark.open(port, serial_number) self._dev.enable_i2c_slave(self.slave_address >> 1) if enable_i2c_pullups: self.enable_pullups(enable_i2c_pullups) if enable_target_power: self.enable_target_power(enable_target_power) def enable_pullups(self, enabled): self._dev.i2c_pullups = enabled def enable_target_power(self, enabled): self._dev.target_power = enabled def raw_write(self, address, data): self._dev.i2c_master_write(address, data) def establish_session(self, session): # just remember session parameters here self._session = session def close_session(self): self._dev.close() def is_ipmc_accessible(self, target): header = IpmbHeaderReq() header.netfn = 6 header.rs_lun = 0 header.rs_sa = target.ipmb_address header.rq_seq = self.next_sequence_number header.rq_lun = 0 header.rq_sa = self.slave_address header.cmd_id = 1 self._send_raw(header, None) self._receive_raw(header) return True def _inc_sequence_number(self): self.next_sequence_number = (self.next_sequence_number + 1) % 64 @staticmethod def _encode_ipmb_msg_req(header, cmd_data): data = header.encode() data.extend(cmd_data) data.append(checksum(data[2:])) return data def _send_raw(self, header, raw_bytes): raw_bytes = encode_ipmb_msg(header, raw_bytes) i2c_addr = header.rs_sa >> 1 raw_bytes = array('B', raw_bytes) log().debug('I2C TX to %02Xh [%s]', i2c_addr, ' '.join(['%02x' % b for b in raw_bytes])) self._dev.i2c_master_write(i2c_addr, raw_bytes[1:]) def _receive_raw(self, header): start_time = time.time() rsp_received = False poll_returned_no_data = False while not rsp_received: timeout = self.timeout - (time.time() - start_time) if timeout <= 0 or poll_returned_no_data: raise IpmiTimeoutError() ret = self._dev.poll(int(timeout * 1000)) # poll returns an empty list if no event is pending if not ret: poll_returned_no_data = True continue (i2c_addr, rx_data) = self._dev.i2c_slave_read() rx_data = array('B', rx_data) log().debug('I2C RX from %02Xh [%s]', i2c_addr << 1, ' '.join(['%02x' % c for c in rx_data])) rq_sa = array('B', [i2c_addr << 1, ]) rsp_received = rx_filter(header, rq_sa + rx_data) return rx_data def _send_and_receive(self, target, lun, netfn, cmdid, payload): """Send and receive data using aardvark interface. target: lun: netfn: cmdid: payload: IPMI message payload as bytestring Returns the received data as bytestring """ self._inc_sequence_number() # assemble IPMB header header = IpmbHeaderReq() header.netfn = netfn header.rs_lun = lun header.rs_sa = target.ipmb_address header.rq_seq = self.next_sequence_number header.rq_lun = 0 header.rq_sa = self.slave_address header.cmd_id = cmdid retries = 0 while retries < self.max_retries: try: self._send_raw(header, payload) rx_data = self._receive_raw(header) break except IpmiTimeoutError: pass except IOError: pass retries += 1 time.sleep(retries*0.2) else: raise IpmiTimeoutError() return rx_data.tostring()[5:-1] def send_and_receive_raw(self, target, lun, netfn, raw_bytes): """Interface function to send and receive raw message. target: IPMI target lun: logical unit number netfn: network function raw_bytes: RAW bytes as bytestring Returns the IPMI message response bytestring. """ return self._send_and_receive(target=target, lun=lun, netfn=netfn, cmdid=array('B', raw_bytes)[0], payload=raw_bytes[1:]) def send_and_receive(self, req): """Interface function to send and receive an IPMI message. target: IPMI target req: IPMI message request Returns the IPMI message response. """ log().debug('IPMI Request [%s]', req) rx_data = self._send_and_receive(target=req.target, lun=req.lun, netfn=req.netfn, cmdid=req.cmdid, payload=encode_message(req)) rsp = create_message(req.netfn + 1, req.cmdid, req.group_extension) decode_message(rsp, rx_data) log().debug('IPMI Response [%s])', rsp) return rsp python-ipmi-0.4.2/pyipmi/interfaces/ipmb.py0000664000372000037200000001453013574451473021607 0ustar travistravis00000000000000# Copyright (c) 2015 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from array import array from ..logger import log from ..msgs import (create_message, create_request_by_name, encode_message, decode_message, constants) from ..utils import check_completion_code def checksum(data): csum = 0 for b in data: csum += b return -csum % 256 class IpmbHeader(object): """Representation of the IPMI message header. Request: *-------*--------------*----------*-------*---------------*--------* | rs_sa | netfn/rs_lun | checksum | rq_sa | rq_seq/rq_lun | cmd_id | *-------*--------------*----------*-------*---------------*--------* Response: *-------*--------------*----------*-------*---------------*--------* | rq_sa | netfn/rq_lun | checksum | rs_sa | rq_seq/rs_lun | cmd_id | *-------*--------------*----------*-------*---------------*--------* """ rs_sa = None rs_lun = None rq_sa = None rq_lun = None rq_seq = None netfn = None cmd_id = None checksum = None class IpmbHeaderReq(IpmbHeader): def encode(self): data = array('B') data.append(self.rs_sa) data.append(self.netfn << 2 | self.rs_lun) data.append(checksum((self.rs_sa, data[1]))) data.append(self.rq_sa) data.append(self.rq_seq << 2 | self.rq_lun) data.append(self.cmd_id) return data.tostring() def decode(self): raise NotImplementedError() class IpmbHeaderRsp(IpmbHeader): def encode(self): raise NotImplementedError() def decode(self, data): data = array('B', data) self.rq_sa = data[0] self.netfn = data[1] >> 2 self.rq_lun = data[1] & 3 self.checksum = data[2] self.rs_sa = data[3] self.rq_seq = data[4] >> 2 self.rs_lun = data[4] & 3 self.cmd_id = data[5] def encode_ipmb_msg(header, data): """Encode an IPMB message. header: IPMB header object data: IPMI message data as bytestring Returns the message as bytestring. """ msg = array('B') msg.fromstring(header.encode()) if data is not None: a = array('B') a.fromstring(data) msg.extend(a) msg.append(checksum(msg[3:])) return msg.tostring() def encode_send_message(payload, rq_sa, rs_sa, channel, seq, tracking=1): """Encode a send message command and embedd the message to be send. payload: the message to be send as bytestring rq_sa: the requester source address rs_sa: the responder source address channel: the channel seq: the sequence number tracking: tracking Returns an encode send message as bytestring """ req = create_request_by_name('SendMessage') req.channel.number = channel req.channel.tracking = tracking data = encode_message(req) header = IpmbHeaderReq() header.netfn = req.__netfn__ header.rs_lun = 0 header.rs_sa = rs_sa header.rq_seq = seq header.rq_lun = 0 header.rq_sa = rq_sa header.cmd_id = req.__cmdid__ return encode_ipmb_msg(header, data + payload) def encode_bridged_message(routing, header, payload, seq): """Encode a (multi-)bridged command and embedd the message to be send. routing: payload: the message to be send as bytestring header: seq: the sequence number Returns the encoded send message as bytestring """ # change header requester addresses for bridging header.rq_sa = routing[-1].rq_sa header.rs_sa = routing[-1].rs_sa tx_data = encode_ipmb_msg(header, payload) for bridge in reversed(routing[:-1]): tx_data = encode_send_message(tx_data, rq_sa=bridge.rq_sa, rs_sa=bridge.rs_sa, channel=bridge.channel, seq=seq) return tx_data def decode_bridged_message(rx_data): """Decode a (multi-)bridged command. rx_data: the received message as bytestring Returns the decoded message as bytestring """ while array('B', rx_data)[5] == constants.CMDID_SEND_MESSAGE: rsp = create_message(constants.NETFN_APP + 1, constants.CMDID_SEND_MESSAGE, None) decode_message(rsp, rx_data[6:]) check_completion_code(rsp.completion_code) rx_data = rx_data[7:-1] if len(rx_data) < 6: break return rx_data def rx_filter(header, data): """Check if the message in rx_data matches to the information in header. The following checks are done: - Header checksum - Payload checksum - NetFn matching - LUN matching - Command Id matching header: the header to compare with data: the received message as bytestring """ rsp_header = IpmbHeaderRsp() rsp_header.decode(data) data = array('B', data) checks = [ (checksum(data[0:3]), 0, 'Header checksum failed'), (checksum(data[3:]), 0, 'payload checksum failed'), # rsp_header.rq_sa, header.rq_sa, 'slave address mismatch'), (rsp_header.netfn, header.netfn | 1, 'NetFn mismatch'), # rsp_header.rs_sa, header.rs_sa, 'target address mismatch'), # rsp_header.rq_lun, header.rq_lun, 'request LUN mismatch'), (rsp_header.rs_lun, header.rs_lun, 'responder LUN mismatch'), (rsp_header.rq_seq, header.rq_seq, 'sequence number mismatch'), (rsp_header.cmd_id, header.cmd_id, 'command id mismatch'), ] match = True for left, right, msg in checks: if left != right: log().debug('{:s}: {:d} {:d}'.format(msg, left, right)) match = False return match python-ipmi-0.4.2/pyipmi/interfaces/mock.py0000664000372000037200000000110313574451473021601 0ustar travistravis00000000000000class Mock(object): """This interface uses the ipmitool raw command to "emulate" a RMCP session. It uses the session information to assemble the correct ipmitool parameters. Therefore, a session has to be established before any request can be sent. """ NAME = 'mock' def __init__(self): pass def establish_session(self, session): pass def is_ipmc_accessible(self, target): pass def send_and_receive_raw(self, target, lun, netfn, raw_bytes): pass def send_and_receive(self, req): pass python-ipmi-0.4.2/pyipmi/interfaces/ipmitool.py0000664000372000037200000002201613574451473022512 0ustar travistravis00000000000000# Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import re from subprocess import Popen, PIPE from array import array from ..session import Session from ..errors import IpmiTimeoutError from ..logger import log from ..msgs import encode_message, decode_message, create_message from ..msgs.constants import CC_OK from ..utils import py3dec_unic_bytes_fix, ByteBuffer class Ipmitool(object): """This interface uses the ipmitool raw command to "emulate" a RMCP session. It uses the session information to assemble the correct ipmitool parameters. Therefore, a session has to be established before any request can be sent. """ NAME = 'ipmitool' IPMITOOL_PATH = 'ipmitool' supported_interfaces = ['lan', 'lanplus', 'serial-terminal', 'open'] def __init__(self, interface_type='lan'): if interface_type in self.supported_interfaces: self._interface_type = interface_type else: raise RuntimeError('interface type %s not supported' % interface_type) self.re_completion_code = re.compile( b"Unable to send RAW command \(.*rsp=(0x[0-9a-f]+)\)") self.re_timeout = re.compile( b"Unable to send RAW command \(.*cmd=0x[0-9a-f]+\)") self._session = None def establish_session(self, session): # just remember session parameters here self._session = session def rmcp_ping(self): if self._interface_type == 'serial-terminal': raise RuntimeError( 'rcmp_ping not supported on "serial-terminal" interface') # for now this uses impitool.. cmd = self.IPMITOOL_PATH cmd += (' -I %s' % self._interface_type) cmd += (' -H %s' % self._session.rmcp_host) cmd += (' -p %s' % self._session.rmcp_port) if self._session.auth_type == Session.AUTH_TYPE_NONE: cmd += (' -A NONE') elif self._session.auth_type == Session.AUTH_TYPE_PASSWORD: cmd += (' -U "%s"' % self._session.auth_username) cmd += (' -P "%s"' % self._session.auth_password) cmd += (' session info all') _, rc = self._run_ipmitool(cmd) if rc: raise IpmiTimeoutError() def is_ipmc_accessible(self, target): try: self.rmcp_ping() accessible = True except IpmiTimeoutError: accessible = False return accessible def send_and_receive_raw(self, target, lun, netfn, raw_bytes): if self._interface_type in ['lan', 'lanplus']: cmd = self._build_ipmitool_cmd(target, lun, netfn, raw_bytes) elif self._interface_type in ['open']: cmd = self._build_open_ipmitool_cmd(target, lun, netfn, raw_bytes) elif self._interface_type in ['serial-terminal']: cmd = self._build_serial_ipmitool_cmd(target, lun, netfn, raw_bytes) else: raise RuntimeError('interface type %s not supported' % self._interface_type) output, rc = self._run_ipmitool(cmd) # check for errors match_completion_code = self.re_completion_code.match(output) match_timeout = self.re_timeout.match(output) data = array('B') if match_completion_code: cc = int(match_completion_code.group(1), 16) data.append(cc) elif match_timeout: raise IpmiTimeoutError() else: if rc != 0: raise RuntimeError('ipmitool failed with rc=%d' % rc) # completion code data.append(CC_OK) output = py3dec_unic_bytes_fix(output) output_lines = output.split('\n') # strip 'Close Session command failed' lines output_lines = [l for l in output_lines if not l.startswith( 'Close Session command failed')] output = ''.join(output_lines).replace('\r', '').strip() if len(output): for value in output.split(' '): data.append(int(value, 16)) log().debug('IPMI RX: {:s}'.format( ''.join('%02x ' % b for b in array('B', data)))) return data.tostring() def send_and_receive(self, req): log().debug('IPMI Request [%s]', req) req_data = ByteBuffer((req.cmdid,)) req_data.push_string(encode_message(req)) rsp_data = self.send_and_receive_raw(req.target, req.lun, req.netfn, req_data.tostring()) rsp = create_message(req.netfn + 1, req.cmdid, req.group_extension) decode_message(rsp, rsp_data) log().debug('IPMI Response [%s])', rsp) return rsp @staticmethod def _build_ipmitool_raw_data(lun, netfn, raw): cmd = ' -l {:d} raw '.format(lun) cmd += ' '.join(['0x%02x' % (d) for d in [netfn] + array('B', raw).tolist()]) return cmd @staticmethod def _build_ipmitool_target(target): cmd = '' if target.routing is not None: # we have to do bridging here if len(target.routing) == 1: pass if len(target.routing) == 2: # ipmitool/shelfmanager does implicit bridging cmd += (' -t 0x%02x' % target.routing[1].rs_sa) cmd += (' -b %d' % target.routing[0].channel) elif len(target.routing) == 3: cmd += (' -T 0x%02x' % target.routing[1].rs_sa) cmd += (' -B %d' % target.routing[0].channel) cmd += (' -t 0x%02x' % target.routing[2].rs_sa) cmd += (' -b %d' % target.routing[1].channel) else: raise RuntimeError('The impitool interface at most double ' 'briding %s' % target) elif target.ipmb_address: cmd += (' -t 0x%02x' % target.ipmb_address) return cmd def _build_ipmitool_cmd(self, target, lun, netfn, raw_bytes): if not hasattr(self, '_session'): raise RuntimeError('Session needs to be set') cmd = self.IPMITOOL_PATH cmd += (' -I %s' % self._interface_type) cmd += (' -H %s' % self._session.rmcp_host) cmd += (' -p %s' % self._session.rmcp_port) if self._session.auth_type == Session.AUTH_TYPE_NONE: cmd += ' -P ""' elif self._session.auth_type == Session.AUTH_TYPE_PASSWORD: cmd += (' -U "%s"' % self._session.auth_username) cmd += (' -P "%s"' % self._session.auth_password) else: raise RuntimeError('Session type %d not supported' % self._session.auth_type) cmd += self._build_ipmitool_target(target) cmd += self._build_ipmitool_raw_data(lun, netfn, raw_bytes) cmd += (' 2>&1') return cmd def _build_serial_ipmitool_cmd(self, target, lun, netfn, raw_bytes): if not hasattr(self, '_session'): raise RuntimeError('Session needs to be set') cmd = '{path!s:s} -I {interface!s:s} -D {port!s:s}:{baud!s:s}'\ .format( path=self.IPMITOOL_PATH, interface=self._interface_type, port=self._session.serial_port, baud=self._session.serial_baudrate ) cmd += self._build_ipmitool_target(target) cmd += self._build_ipmitool_raw_data(lun, netfn, raw_bytes) return cmd def _build_open_ipmitool_cmd(self, target, lun, netfn, raw_bytes): if not hasattr(self, '_session'): raise RuntimeError('Session needs to be set') cmd = self.IPMITOOL_PATH cmd += (' -I %s' % self._interface_type) cmd += self._build_ipmitool_target(target) cmd += self._build_ipmitool_raw_data(lun, netfn, raw_bytes) cmd += (' 2>&1') return cmd @staticmethod def _run_ipmitool(cmd): """Legacy call of ipmitool (will be removed in future). """ log().debug('Running ipmitool "%s"', cmd) child = Popen(cmd, shell=True, stdout=PIPE) output = child.communicate()[0] log().debug('return with rc=%d, output was:\n%s', child.returncode, output) return output, child.returncode python-ipmi-0.4.2/pyipmi/interfaces/rmcp.py0000664000372000037200000004466613574451473021636 0ustar travistravis00000000000000# Copyright (c) 2018 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import socket import struct import hashlib import random import threading from array import array from queue import Queue from .. import Target from ..session import Session from ..msgs import (create_message, create_request_by_name, encode_message, decode_message, constants) from ..messaging import ChannelAuthenticationCapabilities from ..errors import DecodingError, NotSupportedError from ..logger import log from ..interfaces.ipmb import (IpmbHeaderReq, encode_ipmb_msg, encode_bridged_message, decode_bridged_message, rx_filter) from ..utils import check_completion_code CLASS_NORMAL_MSG = 0x00 CLASS_ACK_MSG = 0x80 RMCP_CLASS_ASF = 0x06 RMCP_CLASS_IPMI = 0x07 RMCP_CLASS_OEM = 0x08 def call_repeatedly(interval, func, *args): stopped = threading.Event() def loop(): # the first call is in `interval` secs while not stopped.wait(interval): try: func(*args) except socket.timeout: pass t = threading.Thread(target=loop) t.daemon = True t.start() return stopped.set class RmcpMsg(object): RMCP_HEADER_FORMAT = '!BxBB' ASF_RMCP_V_1_0 = 6 def __init__(self, class_of_msg=None): if class_of_msg is not None: self.class_of_msg = class_of_msg def pack(self, sdu, seq_number): pdu = struct.pack(self.RMCP_HEADER_FORMAT, self.ASF_RMCP_V_1_0, seq_number, self.class_of_msg) if sdu is not None: pdu += sdu return pdu def unpack(self, pdu): header_len = struct.calcsize(self.RMCP_HEADER_FORMAT) header = pdu[:header_len] (self.version, self.seq_number, self.class_of_msg) = \ struct.unpack(self.RMCP_HEADER_FORMAT, header) sdu = pdu[header_len:] if self.version != self.ASF_RMCP_V_1_0: raise DecodingError('invalid RMCP version field') return sdu class AsfMsg(object): ASF_HEADER_FORMAT = '!IBBxB' ASF_TYPE_PRESENCE_PONG = 0x40 ASF_TYPE_PRESENCE_PING = 0x80 asf_type = 0 def __init__(self): self.iana_enterprise_number = 4542 self.tag = 0 self.data = None self.sdu = None def pack(self): if self.data: data_len = len(self.data) else: data_len = 0 pdu = struct.pack(self.ASF_HEADER_FORMAT, self.iana_enterprise_number, self.asf_type, self.tag, data_len) if self.data: pdu += self.data return pdu def unpack(self, sdu): self.sdu = sdu header_len = struct.calcsize(self.ASF_HEADER_FORMAT) header = sdu[:header_len] (self.iana_enterprise_number, self.asf_type, self.tag, data_len) = \ struct.unpack(self.ASF_HEADER_FORMAT, header) if len(sdu) < header_len + data_len: raise DecodingError('short SDU') elif len(sdu) > header_len + data_len: raise DecodingError('SDU has extra bytes') if data_len != 0: self.data = sdu[header_len:header_len + data_len] else: self.data = None if hasattr(self, 'check_header'): self.check_header() def __str__(self): if self.data: return ' '.join('%02x' % b for b in array('B', self.data)) if self.sdu: return ' '.join('%02x' % b for b in array('B', self.sdu)) return '' class AsfPing(AsfMsg): def __init__(self): AsfMsg.__init__(self) self.asf_type = self.ASF_TYPE_PRESENCE_PING def check_header(self): if self.asf_type != self.ASF_TYPE_PRESENCE_PING: raise DecodingError('type does not match') if self.data: raise DecodingError('Data length is not zero') class AsfPong(AsfMsg): DATA_FORMAT = '!IIBB6x' def __init__(self): self.asf_type = self.ASF_TYPE_PRESENCE_PONG self.oem_iana_enterprise_number = 4542 self.oem_defined = 0 self.supported_entities = 0 self.supported_interactions = 0 def unpack(self, sdu): AsfMsg.unpack(self, sdu) # header_len = struct.calcsize(self.ASF_HEADER_FORMAT) (self.oem_iana_enterprise_number, self.oem_defined, self.supported_entities, self.supported_interactions) =\ struct.unpack(self.DATA_FORMAT, self.data) self.check_data() def check_data(self): if self.oem_iana_enterprise_number == 4542 and self.oem_defined != 0: raise DecodingError('SDU malformed') if self.supported_interactions != 0: raise DecodingError('SDU malformed') def check_header(self): if self.asf_type != self.ASF_TYPE_PRESENCE_PONG: raise DecodingError('type does not match') if len(self.data) != struct.calcsize(self.DATA_FORMAT): raise DecodingError('Data length mismatch') class IpmiMsg(object): HEADER_FORMAT_NO_AUTH = '!BIIB' HEADER_FORMAT_AUTH = '!BII16BB' def __init__(self, session=None): self.session = session def _pack_session_id(self): if self.session is not None: session_id = self.session.sid else: session_id = 0 return struct.unpack("I", session_id))[0] def _pack_sequence_number(self): if self.session is not None: seq = self.session.sequence_number else: seq = 0 return struct.unpack("I", seq))[0] def _padd_password(self): """The password/key is 0 padded to 16-bytes for all specified authentication types.""" password = self.session._auth_password if isinstance(password, str): password = str.encode(password) return password.ljust(16, b'\x00') def _pack_auth_code_straight(self): """Return the auth code as bytestring.""" return self._padd_password() def _pack_auth_code_md5(self, sdu): auth_code = struct.pack('>16s I %ds I 16s' % len(sdu), self._pack_auth_code_straight(), self._pack_session_id(), sdu, self._pack_sequence_number(), self._pack_auth_code_straight()) return hashlib.md5(auth_code).digest() def pack(self, sdu): if sdu is not None: data_len = len(sdu) else: data_len = 0 if self.session is not None: auth_type = self.session.auth_type if self.session.activated: self.session.increment_sequence_number() else: auth_type = Session.AUTH_TYPE_NONE pdu = struct.pack('!BII', auth_type, self._pack_sequence_number(), self._pack_session_id()) if auth_type == Session.AUTH_TYPE_NONE: pass elif auth_type == Session.AUTH_TYPE_PASSWORD: pdu += self._pack_auth_code_straight() elif auth_type == Session.AUTH_TYPE_MD5: pdu += self._pack_auth_code_md5(sdu) else: raise NotSupportedError('authentication type %s' % auth_type) pdu += array('B', [data_len]).tostring() if sdu is not None: pdu += sdu return pdu def unpack(self, pdu): auth_type = array('B', pdu)[0] if auth_type != 0: header_len = struct.calcsize(self.HEADER_FORMAT_AUTH) header = pdu[:header_len] # TBD .. find a way to do this better self.auth_type = array('B', pdu)[0] (self.sequence_number,) = struct.unpack('!I', pdu[1:5]) (self.session_id,) = struct.unpack('!I', pdu[5:9]) self.auth_code = [a for a in struct.unpack('!16B', pdu[9:25])] data_len = array('B', pdu)[25] else: header_len = struct.calcsize(self.HEADER_FORMAT_NO_AUTH) header = pdu[:header_len] (self.auth_type, self.sequence_number, self.session_id, data_len) = struct.unpack(self.HEADER_FORMAT_NO_AUTH, header) if len(pdu) < header_len + data_len: raise DecodingError('short SDU') elif len(pdu) > header_len + data_len: raise DecodingError('SDU has extra bytes ({:d},{:d},{:d} )'.format( len(pdu), header_len, data_len)) if hasattr(self, 'check_header'): self.check_header() if data_len != 0: sdu = pdu[header_len:header_len + data_len] else: sdu = None return sdu def check_data(self): pass def check_header(self): pass class Rmcp(object): NAME = 'rmcp' _session = None def __init__(self, slave_address=0x81, host_target_address=0x20, keep_alive_interval=1): self.host = None self.port = None self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.seq_number = 0xff self.slave_address = slave_address self.host_target = Target(host_target_address) self.set_timeout(2.0) self.next_sequence_number = 0 self.keep_alive_interval = keep_alive_interval self._stop_keep_alive = None self._q = Queue() def _send_rmcp_msg(self, sdu, class_of_msg): rmcp = RmcpMsg(class_of_msg) pdu = rmcp.pack(sdu, self.seq_number) self._sock.sendto(pdu, (self.host, self.port)) if self.seq_number != 255: self.seq_number = (self.seq_number + 1) % 254 def _receive(self): (pdu, _) = self._sock.recvfrom(4096) rmcp = RmcpMsg() sdu = rmcp.unpack(pdu) return (rmcp.seq_number, rmcp.class_of_msg, sdu) def set_timeout(self, timeout): self._sock.settimeout(timeout) def _send_ipmi_msg(self, data): log().debug('IPMI TX: {:s}'.format( ' '.join('%02x' % b for b in array('B', data)))) ipmi = IpmiMsg(self._session) tx_data = ipmi.pack(data) self._send_rmcp_msg(tx_data, RMCP_CLASS_IPMI) def _receive_ipmi_msg(self): (_, class_of_msg, pdu) = self._receive() if class_of_msg != RMCP_CLASS_IPMI: raise DecodingError('invalid class field in ASF message') msg = IpmiMsg() data = msg.unpack(pdu) log().debug('IPMI RX: {:s}'.format( ' '.join('%02x' % b for b in array('B', data)))) return data def _send_asf_msg(self, msg): log().debug('ASF TX: msg') self._send_rmcp_msg(msg.pack(), RMCP_CLASS_ASF) def _receive_asf_msg(self, cls): (_, class_of_msg, data) = self._receive() log().debug('ASF RX: msg') if class_of_msg != RMCP_CLASS_ASF: raise DecodingError('invalid class field in ASF message') msg = cls() msg.unpack(data) return msg def ping(self): ping = AsfPing() self._send_asf_msg(ping) self._receive_asf_msg(AsfPong) def _get_channel_auth_cap(self): CHANNEL_NUMBER_FOR_THIS = 0xe # get channel auth cap req = create_request_by_name('GetChannelAuthenticationCapabilities') req.target = self.host_target req.channel.number = CHANNEL_NUMBER_FOR_THIS req.privilege_level.requested = Session.PRIV_LEVEL_ADMINISTRATOR rsp = self.send_and_receive(req) check_completion_code(rsp.completion_code) caps = ChannelAuthenticationCapabilities(rsp) return caps def _get_session_challenge(self, session): # get session challenge req = create_request_by_name('GetSessionChallenge') req.target = self.host_target req.authentication.type = session.auth_type if session._auth_username: req.user_name = session._auth_username.ljust(16, '\x00') rsp = self.send_and_receive(req) check_completion_code(rsp.completion_code) return rsp def _activate_session(self, session, challenge): # activate session req = create_request_by_name('ActivateSession') req.target = self.host_target req.authentication.type = session.auth_type req.privilege_level.maximum_requested =\ Session.PRIV_LEVEL_ADMINISTRATOR req.challenge_string = challenge req.session_id = self._session.sid req.initial_outbound_sequence_number = random.randrange(1, 0xffffffff) rsp = self.send_and_receive(req) check_completion_code(rsp.completion_code) return rsp def _set_session_privilege_level(self, level): req = create_request_by_name('SetSessionPrivilegeLevel') req.target = self.host_target req.privilege_level.requested = level rsp = self.send_and_receive(req) check_completion_code(rsp.completion_code) return rsp def _get_device_id(self): req = create_request_by_name('GetDeviceId') req.target = self.host_target rsp = self.send_and_receive(req) check_completion_code(rsp.completion_code) def establish_session(self, session): self._session = None self.host = session._rmcp_host self.port = session._rmcp_port # 0 - Ping self.ping() # 1 - Get Channel Authentication Capabilities log().debug('Get Channel Authentication Capabilities') caps = self._get_channel_auth_cap() log().debug('%s' % caps) # 2 - Get Session Challenge log().debug('Get Session Challenge') session.auth_type = caps.get_max_auth_type() rsp = self._get_session_challenge(session) session_challenge = rsp.challenge_string session.sid = rsp.temporary_session_id self._session = session # 3 - Activate Session log().debug('Activate Session') rsp = self._activate_session(session, session_challenge) self._session.sid = rsp.session_id self._session.sequence_number = rsp.initial_inbound_sequence_number self._session.activated = True log().debug('Set Session Privilege Level') # 4 - Set Session Privilege Level self._set_session_privilege_level(Session.PRIV_LEVEL_ADMINISTRATOR) log().debug('Session opened') if self.keep_alive_interval: self._stop_keep_alive = call_repeatedly( self.keep_alive_interval, self._get_device_id) def close_session(self): if self._stop_keep_alive: self._stop_keep_alive() if self._session.activated is False: log().debug('Session already closed') return log().debug('Close Session %s' % self._session) req = create_request_by_name('CloseSession') req.target = self.host_target req.session_id = self._session.sid rsp = self.send_and_receive(req) check_completion_code(rsp.completion_code) self._session.activated = False # self._q.join() def _inc_sequence_number(self): self.next_sequence_number = (self.next_sequence_number + 1) % 64 def _send_and_receive(self, target, lun, netfn, cmdid, payload): """Send and receive data using RMCP interface. target: lun: netfn: cmdid: raw_bytes: IPMI message payload as bytestring Returns the received data as array. """ self._inc_sequence_number() header = IpmbHeaderReq() header.netfn = netfn header.rs_lun = lun header.rs_sa = target.ipmb_address header.rq_seq = self.next_sequence_number header.rq_lun = 0 header.rq_sa = self.slave_address header.cmd_id = cmdid # Bridge message if target.routing: tx_data = encode_bridged_message(target.routing, header, payload, self.next_sequence_number) else: tx_data = encode_ipmb_msg(header, payload) self._send_ipmi_msg(tx_data) received = False while received is False: if not self._q.empty(): rx_data = self._q.get() else: rx_data = self._receive_ipmi_msg() if array('B', rx_data)[5] == constants.CMDID_SEND_MESSAGE: rx_data = decode_bridged_message(rx_data) received = rx_filter(header, rx_data) if not received: self._q.put(rx_data) return rx_data[6:-1] def send_and_receive_raw(self, target, lun, netfn, raw_bytes): """Interface function to send and receive raw message. target: IPMI target lun: logical unit number netfn: network function raw_bytes: RAW bytes as bytestring Returns the IPMI message response bytestring. """ return self._send_and_receive(target=target, lun=lun, netfn=netfn, cmdid=array('B', raw_bytes)[0], payload=raw_bytes[1:]) def send_and_receive(self, req): """Interface function to send and receive an IPMI message. target: IPMI target req: IPMI message request Returns the IPMI message response. """ rx_data = self._send_and_receive(target=req.target, lun=req.lun, netfn=req.netfn, cmdid=req.cmdid, payload=encode_message(req)) rsp = create_message(req.netfn + 1, req.cmdid, req.group_extension) decode_message(rsp, rx_data) return rsp python-ipmi-0.4.2/pyipmi/interfaces/__init__.py0000664000372000037200000000225413574451473022417 0ustar travistravis00000000000000# Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from .ipmitool import Ipmitool from .aardvark import Aardvark from .mock import Mock from .rmcp import Rmcp INTERFACES = [ Ipmitool, Aardvark, Mock, Rmcp, ] def create_interface(interface, *args, **kwargs): for intf in INTERFACES: if intf.NAME == interface: intf = intf(*args, **kwargs) return intf raise RuntimeError('unknown interface with name %s' % interface) python-ipmi-0.4.2/pyipmi/__init__.py0000664000372000037200000001704213574451473020275 0ustar travistravis00000000000000# -*- coding: utf-8 -*- # Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from __future__ import absolute_import import time import ast from . import bmc from . import chassis from . import dcmi from . import event from . import fru from . import hpm from . import lan from . import messaging from . import picmg from . import sdr from . import sel from . import sensor from . import msgs from .errors import IpmiTimeoutError, CompletionCodeError, RetryError from .msgs.registry import create_request_by_name from .session import Session from .utils import check_completion_code, is_string try: from version import __version__ except ImportError: __version__ = 'dev' def create_connection(interface): session = Session() session.interface = interface ipmi = Ipmi() ipmi.interface = interface ipmi.session = session ipmi.requester = NullRequester() return ipmi class Requester(object): '''The Requester class represents an IPMI device which initiates a request/response message exchange. ''' def __init__(self, ipmb_address): self.ipmb_address = ipmb_address class NullRequester(object): '''The NullRequester is used for interfaces which doesn't require a valid requester. ''' @property def ipmb_address(self): raise AssertionError('NullRequester does not provide an IPMB address') class Routing(object): """The Target class represents an IPMI target.""" def __init__(self, rq_sa, rs_sa, channel): self.rq_sa = rq_sa self.rs_sa = rs_sa self.channel = channel def __str__(self): s = 'Routing: Rq: %s Rs: %s Ch: %s' \ % (self.rq_sa, self.rs_sa, self.channel) return s class Target(object): '''The Target class represents an IPMI target.''' routing = None ipmb_address = None def __init__(self, ipmb_address=None, routing=None): """ `ipmb_address` is the IPMB target address `routing` is the bridging information used to build send message commands. """ if ipmb_address: self.ipmb_address = ipmb_address if routing: self.set_routing(routing) def set_routing_information(self, routing): self.set_routing(routing) def set_routing(self, routing): """Set the path over which a target is reachable. The path is given as a list of tuples in the form (address, bridge_channel). Example #1: access to an ATCA blade in a chassis slave = 0x81, target = 0x82 routing = [(0x81,0x20,0),(0x20,0x82,None)] Example #2: access to an AMC in a uTCA chassis slave = 0x81, target = 0x72 routing = [(0x81,0x20,0),(0x20,0x82,7),(0x20,0x72,None)] uTCA - MCH AMC .-------------------. .--------. | .-----------| | | | ShMC | CM | | MMC | channel=0 | | | channel=7 | | 81 ------------| 0x20 |0x82 0x20 |-------------| 0x72 | | | | | | | | | | | | `-----------| | | `-------------------´ `--------´ `------------´ `---´ `---------------´ Example #3: access to an AMC in a ATCA AMC carrier slave = 0x81, target = 0x72 routing = [(0x81,0x20,0),(0x20,0x8e,7),(0x20,0x80,None)] """ if is_string(routing): # if type(routing) in [unicode, str]: routing = ast.literal_eval(routing) self.routing = [Routing(*route) for route in routing] def __str__(self): string = 'Target: IPMB: 0x%02x\n' % self.ipmb_address if self.routing: for route in self.routing: string += ' %s\n' % route return string class Ipmi(bmc.Bmc, chassis.Chassis, dcmi.Dcmi, fru.Fru, picmg.Picmg, hpm.Hpm, sdr.Sdr, sensor.Sensor, event.Event, sel.Sel, lan.Lan, messaging.Messaging): def __init__(self): self._interface = None self._session = None self._target = None for base in Ipmi.__bases__: base.__init__(self) def is_ipmc_accessible(self): return self.interface.is_ipmc_accessible(self.target) def wait_until_ipmb_is_accessible(self, timeout, interval=0.25): start_time = time.time() while time.time() < start_time + (timeout): try: self.is_ipmc_accessible() except IpmiTimeoutError: time.sleep(interval) self.is_ipmc_accessible() def send_message(self, req, retry=3): req.target = self.target req.requester = self.requester rsp = None while retry > 0: retry -= 1 try: rsp = self.interface.send_and_receive(req) break except CompletionCodeError as e: if e.cc == msgs.constants.CC_NODE_BUSY: continue else: raise RetryError() return rsp def send_message_with_name(self, name, *args, **kwargs): req = create_request_by_name(name) for key, value in kwargs.items(): setattr(req, key, value) rsp = self.send_message(req) check_completion_code(rsp.completion_code) return rsp def raw_command(self, lun, netfn, raw_bytes): """Send the raw command data and return the raw response. lun: the logical unit number netfn: the network function raw_bytes: the raw message as bytestring Returns the response as bytestring. """ return self.interface.send_and_receive_raw(self.target, lun, netfn, raw_bytes) def _get_interface(self): try: return self._interface except AttributeError: raise RuntimeError('No interface has been set') def _get_session(self): try: return self._session except AttributeError: raise RuntimeError('No IPMI session has been set') def _get_target(self): try: return self._target except AttributeError: raise RuntimeError('No IPMI target has been set') def _set_interface(self, interface): self._interface = interface def _set_session(self, session): self._session = session def _set_target(self, target): self._target = target target = property(_get_target, _set_target) interface = property(_get_interface, _set_interface) session = property(_get_session, _set_session) python-ipmi-0.4.2/pyipmi/bmc.py0000664000372000037200000001404413574451473017276 0ustar travistravis00000000000000# Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from .msgs import create_request_by_name from .utils import check_completion_code from .state import State from .fields import VersionField class Bmc(object): def get_device_id(self): return DeviceId(self.send_message_with_name('GetDeviceId')) def cold_reset(self): self.send_message_with_name('ColdReset') def warm_reset(self): self.send_message_with_name('WarmReset') def i2c_write_read(self, bus_type, bus_id, channel, address, count, data=None): req = create_request_by_name('MasterWriteRead') req.bus_id.type = bus_type req.bus_id.id = bus_id req.bus_id.channel = channel req.bus_id.slave_address = address req.read_count = count if data: req.data = data rsp = self.send_message(req) check_completion_code(rsp.completion_code) return rsp.data def i2c_write(self, bus_type, bus_id, channel, address, data): self.i2c_write_read(bus_type, bus_id, channel, address, 0, data) def i2c_read(self, bus_type, bus_id, channel, address, count): return self.i2c_write_read(bus_type, bus_id, channel, address, count, None) def set_watchdog_timer(self, config): req = create_request_by_name('SetWatchdogTimer') req.timer_use.timer_use = config.timer_use req.timer_use.dont_stop = config.dont_stop and 1 or 0 req.timer_use.dont_log = config.dont_log and 1 or 0 req.timer_actions.pre_timeout_interrupt = config.pre_timeout_interrupt req.timer_actions.timeout_action = config.timeout_action req.pre_timeout_interval = config.pre_timeout_interval req.timer_use_expiration_flags = config.timer_use_expiration_flags req.initial_countdown = config.initial_countdown rsp = self.send_message(req) check_completion_code(rsp.completion_code) def get_watchdog_timer(self): return Watchdog(self.send_message_with_name('GetWatchdogTimer')) def reset_watchdog_timer(self): self.send_message_with_name('ResetWatchdogTimer') class Watchdog(State): TIMER_USE_OEM = 5 TIMER_USE_SMS_OS = 4 TIMER_USE_OS_LOAD = 3 TIMER_USE_BIOS_POST = 2 TIMER_USE_BIOS_FRB2 = 1 TIMEOUT_ACTION_NO_ACTION = 0 TIMEOUT_ACTION_HARD_RESET = 1 TIMEOUT_ACTION_POWER_DOWN = 2 TIMEOUT_ACTION_POWER_CYCLE = 3 __properties__ = [ # (propery, description) ('timer_use', ''), ('dont_stop', ''), ('is_running', ''), ('dont_log', ''), ('pre_timeout_interrupt', ''), ('timeout_action', ''), ('pre_timeout_interval', ''), ('timer_use_expiration_flags', ''), ('initial_countdown', ''), ('present_countdown', ''), ] def _from_response(self, rsp): self.timer_use = rsp.timer_use.timer_use self.is_running = bool(rsp.timer_use.is_running) self.dont_log = bool(rsp.timer_use.dont_log) self.pre_timeout_interrupt = rsp.timer_actions.pre_timeout_interrupt self.timeout_action = rsp.timer_actions.timeout_action self.pre_timeout_interval = rsp.pre_timeout_interval self.timer_use_expiration_flags = rsp.timer_use_expiration_flags self.initial_countdown = rsp.initial_countdown self.present_countdown = rsp.present_countdown class DeviceId(State): def __str__(self): string = 'Device ID: %d' % self.device_id string += ' revision: %d' % self.revision string += ' available: %d' % self.available string += ' fw version: %s' % (self.fw_revision) string += ' ipmi: %s' % self.ipmi_version string += ' manufacturer: %d' % self.manufacturer_id string += ' product: %d' % self.product_id return string def supports_function(self, name): """Returns if a function is supported. `name` is one of 'SENSOR', 'SDR_REPOSITORY', 'SEL', 'FRU_INVENTORY', 'IPMB_EVENT_RECEIVER', 'IPMB_EVENT_GENERATOR', 'BRIDGE', 'CHASSIS'. """ return name.lower() in self.supported_functions def _from_response(self, rsp): self.device_id = rsp.device_id self.revision = rsp.device_revision.device_revision self.provides_sdrs = bool(rsp.device_revision.provides_device_sdrs) self.available = bool(rsp.firmware_revision.device_available) self.fw_revision = VersionField( (rsp.firmware_revision.major, rsp.firmware_revision.minor)) self.ipmi_version = VersionField( (rsp.ipmi_version & 0xf, (rsp.ipmi_version >> 4) & 0xf)) self.manufacturer_id = rsp.manufacturer_id self.product_id = rsp.product_id self.supported_functions = [] functions = ('sensor', 'sdr_repository', 'sel', 'fru_inventory', 'ipmb_event_receiver', 'ipmb_event_generator', 'bridge', 'chassis') for function in functions: if hasattr(rsp.additional_support, function): if getattr(rsp.additional_support, function): self.supported_functions.append(function) self.aux = None if rsp.auxiliary is not None: self.aux = list(rsp.auxiliary) python-ipmi-0.4.2/pyipmi/errors.py0000664000372000037200000000364113574451473020052 0ustar travistravis00000000000000# Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from .msgs.constants import COMPLETION_CODE_DESCR class DecodingError(Exception): """Error on message decoding.""" pass class EncodingError(Exception): """Error on message encoding.""" pass class IpmiTimeoutError(Exception): """Timeout occurred.""" pass class CompletionCodeError(Exception): """IPMI completion code not OK.""" def __init__(self, cc, cmd_id=None): self.cc = cc self.cc_desc = self.find_cc_desc(cc) def __str__(self): return "%s cc=0x%02x desc=%s" \ % (self.__class__.__name__, self.cc, self.cc_desc) @staticmethod def find_cc_desc(error_cc): for cc in COMPLETION_CODE_DESCR: if error_cc == cc[0]: return cc[1] return "Unknown error description" class NotSupportedError(Exception): """Not supported yet.""" pass class DescriptionError(Exception): """Message description incorrect.""" pass class RetryError(Exception): """Maxium number of retries exceeded.""" pass class DataNotFound(Exception): """Requested data not found.""" pass class HpmError(Exception): """HPM.1 error""" pass python-ipmi-0.4.2/pyipmi/session.py0000664000372000037200000000723313574451473020222 0ustar travistravis00000000000000# Copyright (c) 2016 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class Session(object): AUTH_TYPE_NONE = 0x00 AUTH_TYPE_MD2 = 0x01 AUTH_TYPE_MD5 = 0x02 AUTH_TYPE_PASSWORD = 0x04 AUTH_TYPE_OEM = 0x05 PRIV_LEVEL_USER = 2 PRIV_LEVEL_OPERATOR = 3 PRIV_LEVEL_ADMINISTRATOR = 4 PRIV_LEVEL_OEM = 5 _interface = None _auth_type = AUTH_TYPE_NONE _auth_username = None _auth_password = None _rmcp_host = None _rmcp_port = None _serial_port = None _serial_baudrate = None def __init__(self): self.established = False self.sid = 0 self.sequence_number = 0 self.activated = False def _get_interface(self): try: return self._interface except AttributeError: raise RuntimeError('No interface has been set') def _set_interface(self, interface): self._interface = interface def increment_sequence_number(self): self.sequence_number += 1 if self.sequence_number > 0xffffffff: self.sequence_number = 1 def set_session_type_rmcp(self, host, port=623): self._rmcp_host = host self._rmcp_port = port @property def rmcp_host(self): return self._rmcp_host @property def rmcp_port(self): return self._rmcp_port def set_session_type_serial(self, port, baudrate): self._serial_port = port self._serial_baudrate = baudrate @property def serial_port(self): return self._serial_port @property def serial_baudrate(self): return self._serial_baudrate def _set_auth_type(self, auth_type): self._auth_type = auth_type def _get_auth_type(self): return self._auth_type def set_auth_type_user(self, username, password): self._auth_type = self.AUTH_TYPE_PASSWORD self._auth_username = username self._auth_password = password @property def auth_username(self): return self._auth_username @property def auth_password(self): return self._auth_password def establish(self): if hasattr(self.interface, 'establish_session'): self.interface.establish_session(self) def close(self): if hasattr(self.interface, 'close_session'): self.interface.close_session() def rmcp_ping(self): if hasattr(self.interface, 'rmcp_ping'): self.interface.rmcp_ping() def __str__(self): string = 'Session:\n' string += ' ID: 0x%08x\n' % self.sid string += ' Seq: 0x%08x\n' % self.sequence_number string += ' Host: %s:%s\n' % (self._rmcp_host, self._rmcp_port) string += ' Auth.: %s\n' % self.auth_type string += ' User: %s\n' % self._auth_username string += ' Password: %s\n' % self._auth_password string += '\n' return string interface = property(_get_interface, _set_interface) auth_type = property(_get_auth_type, _set_auth_type) python-ipmi-0.4.2/pyipmi/chassis.py0000664000372000037200000000771113574451473020175 0ustar travistravis00000000000000# Copyright (c) 2014 Kontron Europe GmbH # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA from __future__ import absolute_import from .msgs import create_request_by_name from .utils import check_completion_code from .state import State from .msgs.chassis import \ CONTROL_POWER_DOWN, CONTROL_POWER_UP, CONTROL_POWER_CYCLE, \ CONTROL_HARD_RESET, CONTROL_DIAGNOSTIC_INTERRUPT, \ CONTROL_SOFT_SHUTDOWN class Chassis(object): def get_chassis_status(self): return ChassisStatus(self.send_message_with_name('GetChassisStatus')) def chassis_control(self, option): req = create_request_by_name('ChassisControl') req.control.option = option rsp = self.send_message(req) check_completion_code(rsp.completion_code) def chassis_control_power_down(self): self.chassis_control(CONTROL_POWER_DOWN) def chassis_control_power_up(self): self.chassis_control(CONTROL_POWER_UP) def chassis_control_power_cycle(self): self.chassis_control(CONTROL_POWER_CYCLE) def chassis_control_hard_reset(self): self.chassis_control(CONTROL_HARD_RESET) def chassis_control_diagnostic_interrupt(self): self.chassis_control(CONTROL_DIAGNOSTIC_INTERRUPT) def chassis_control_soft_shutdown(self): self.chassis_control(CONTROL_SOFT_SHUTDOWN) class ChassisStatus(State): power_on = None overload = None interlock = None fault = None control_fault = None restore_policy = None id_cmd_state_info_support=None chassis_id_state=None front_panel_button_capabilities=None last_event = [] chassis_state = [] def _from_response(self, rsp): self.power_on = bool(rsp.current_power_state.power_on) self.overload = bool(rsp.current_power_state.power_overload) self.interlock = bool(rsp.current_power_state.interlock) self.fault = bool(rsp.current_power_state.power_fault) self.control_fault = bool(rsp.current_power_state.power_control_fault) self.restore_policy = rsp.current_power_state.power_restore_policy self.id_cmd_state_info_support=bool(rsp.misc_chassis_state.id_cmd_state_info_support) self.chassis_id_state=rsp.misc_chassis_state.chassis_id_state if rsp.front_panel_button_capabilities is not None: self.front_panel_button_capabilities=rsp.front_panel_button_capabilities if rsp.last_power_event.ac_failed: self.last_event.append('ac_failed') if rsp.last_power_event.power_overload: self.last_event.append('overload') if rsp.last_power_event.power_interlock: self.last_event.append('interlock') if rsp.last_power_event.power_fault: self.last_event.append('fault') if rsp.last_power_event.power_is_on_via_ipmi_command: self.last_event.append('power_on_via_ipmi') if rsp.misc_chassis_state.chassis_intrusion_active: self.chassis_state.append('intrusion') if rsp.misc_chassis_state.front_panel_lockout_active: self.chassis_state.append('front_panel_lockout') if rsp.misc_chassis_state.drive_fault: self.chassis_state.append('drive_fault') if rsp.misc_chassis_state.cooling_fault_detected: self.chassis_state.append('cooling_fault') python-ipmi-0.4.2/setup.cfg0000664000372000037200000000004613574451533016467 0ustar travistravis00000000000000[egg_info] tag_build = tag_date = 0 python-ipmi-0.4.2/README.rst0000664000372000037200000001211413574451473016337 0ustar travistravis00000000000000Pure Python IPMI Library ======================== |BuildStatus| |PyPiVersion| |Documentation| |PyPiPythonVersions| |Coveralls| |CodeClimate| |Codacy| Features -------- * native RMCP interface * legacy RMCP interface (using ipmitool) * IPMB interface (using the `Total Phase`_ Aardvark) Tested Devices -------------- * Kontron mTCA Carrier Manager * Kontron CompactPCI boards * Pigeon Point Shelf Manager * HPE iLO3/iLO4 Requirements ------------ For IPMB interface a `Total Phase`_ Aardvark is needed. Installation ------------ Using ``pip`` ''''''''''''' The recommended installation method is using `pip `__:: pip install python-ipmi Manual installation ''''''''''''''''''' Download the source distribution package for the library. Extract the the package to a temporary location and install:: python setup.py install Documentation ------------- You can find the most up to date documentation at: http://python-ipmi.rtfd.org Example ------- Below is an example that shows how to setup the interface and the connection using the `ipmitool`_ as backend with both network and serial interfaces. Example with lan interface: .. code:: python import pyipmi import pyipmi.interfaces # Supported interface_types for ipmitool are: 'lan' , 'lanplus', and 'serial-terminal' interface = pyipmi.interfaces.create_interface('ipmitool', interface_type='lan') connection = pyipmi.create_connection(interface) connection.target = pyipmi.Target(0x82) connection.target.set_routing([(0x81,0x20,0),(0x20,0x82,7)]) connection.session.set_session_type_rmcp('10.0.0.1', port=623) connection.session.set_auth_type_user('admin', 'admin') connection.session.establish() connection.get_device_id() ipmitool command: .. code:: shell ipmitool -I lan -H 10.0.0.1 -p 623 -U "admin" -P "admin" -t 0x82 -b 0 -l 0 raw 0x06 0x01 Example with serial interface: .. code:: python import pyipmi import pyipmi.interfaces interface = pyipmi.interfaces.create_interface('ipmitool', interface_type='serial-terminal') connection = pyipmi.create_connection(interface) connection.target = pyipmi.Target(0xb2) # set_session_type_serial(port, baudrate) connection.session.set_session_type_serial('/dev/tty2', 115200) connection.session.establish() connection.get_device_id() ipmitool command: .. code:: shell ipmitool -I serial-terminal -D /dev/tty2:115200 -t 0xb2 -l 0 raw 0x06 0x01 Compatibility ------------- Python 2.7 is currently supported. Python 3.x support is in beta Contributing ------------ Contributions are always welcome. You may send patches directly (eg. ``git send-email``), do a github pull request or just file an issue. * respect the coding style (eg. PEP8), * provide well-formed commit message (see `this blog post `_.) * add a Signed-off-by line (eg. ``git commit -s``) License ------- This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA .. _Total Phase: http://www.totalphase.com .. _ipmitool: http://sourceforge.net/projects/ipmitool/ .. |BuildStatus| image:: https://travis-ci.org/kontron/python-ipmi.png?branch=master :target: https://travis-ci.org/kontron/python-ipmi .. |PyPiVersion| image:: https://badge.fury.io/py/python-ipmi.svg :target: http://badge.fury.io/py/python-ipmi .. |Documentation| image:: https://readthedocs.org/projects/python-ipmi/badge/?version=latest :target: https://python-ipmi.readthedocs.io/en/latest/?badge=latest :alt: Documentation Status .. |PyPiPythonVersions| image:: https://img.shields.io/pypi/pyversions/python-ipmi.svg :alt: Python versions :target: http://badge.fury.io/py/python-ipmi .. |CodeClimate| image:: https://codeclimate.com/github/kontron/python-ipmi/badges/gpa.svg :target: http://codeclimate.com/github/kontron/python-ipmi .. |Coveralls| image:: https://coveralls.io/repos/github/kontron/python-ipmi/badge.svg?branch=master :target: https://coveralls.io/github/kontron/python-ipmi?branch=master .. |Codacy| image:: https://api.codacy.com/project/badge/Grade/bdda77c6596b4e9b8508d95805ba34c5 :alt: Codacy Badge :target: https://app.codacy.com/app/hthiery/python-ipmi?utm_source=github.com&utm_medium=referral&utm_content=kontron/python-ipmi&utm_campaign=Badge_Grade_Dashboard python-ipmi-0.4.2/setup.py0000664000372000037200000000474213574451473016372 0ustar travistravis00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- from setuptools import setup, find_packages import os import subprocess name = 'python-ipmi' version_py = os.path.join(os.path.dirname(__file__), 'pyipmi', 'version.py') def git_pep440_version(): full = subprocess.check_output( ['git', 'describe', '--tags', '--always', '--dirty=.dirty'], stderr=subprocess.STDOUT).decode().strip() tag = subprocess.check_output( ['git', 'describe', '--tags', '--always', '--abbrev=0'], stderr=subprocess.STDOUT).decode().strip() tail = full[len(tag):] return tag + tail.replace('-', '.dev', 1).replace('-', '+', 1) try: version = git_pep440_version() with open(version_py, 'w') as f: f.write('# This file was autogenerated by setup.py\n') f.write('__version__ = \'%s\'\n' % (version,)) except (OSError, subprocess.CalledProcessError, IOError) as e: try: with open(version_py, 'r') as f: d = dict() exec(f.read(), d) version = d['__version__'] except IOError: version = 'unknown' with open('README.rst') as f: readme = f.read() setup(name=name, version=version, description='Pure python IPMI library', long_description=readme, url='https://github.com/kontron/python-ipmi', download_url='https://github.com/kontron/python-ipmi/tarball/' + version, author='Michael Walle, Heiko Thiery', author_email='michael.walle@kontron.com, heiko.thiery@kontron.com', packages=find_packages(exclude="test"), license='LGPLv2+', platforms=["any"], classifiers=[ 'Development Status :: 3 - Alpha', 'Environment :: Console', 'License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)', 'Natural Language :: English', 'Operating System :: OS Independent', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Topic :: Software Development :: Libraries :: Python Modules', ], entry_points={ 'console_scripts': [ 'ipmitool.py = pyipmi.ipmitool:main', ] }, test_suite='tests', install_requires=[ 'markdown', 'future', ], ) python-ipmi-0.4.2/tests/0000775000372000037200000000000013574451533016010 5ustar travistravis00000000000000python-ipmi-0.4.2/tests/test_chassis.py0000664000372000037200000000166413574451473021070 0ustar travistravis00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- from nose.tools import eq_, ok_ from pyipmi.chassis import ChassisStatus import pyipmi.msgs.chassis from pyipmi.msgs import decode_message def test_chassisstatus_object(): msg = pyipmi.msgs.chassis.GetChassisStatusRsp() decode_message(msg, b'\x00\xff\xff\xff') status = ChassisStatus(msg) eq_(status.power_on, True) eq_(status.overload, True) eq_(status.interlock, True) eq_(status.fault, True) eq_(status.control_fault, True) eq_(status.restore_policy, 3) ok_('ac_failed' in status.last_event) ok_('overload' in status.last_event) ok_('interlock' in status.last_event) ok_('fault' in status.last_event) ok_('power_on_via_ipmi' in status.last_event) ok_('intrusion', status.chassis_state) ok_('front_panel_lockout', status.chassis_state) ok_('drive_fault', status.chassis_state) ok_('cooling_fault', status.chassis_state) python-ipmi-0.4.2/tests/test_helper.py0000664000372000037200000000145313574451473020706 0ustar travistravis00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- from mock import MagicMock, call from nose.tools import eq_ from pyipmi.helper import (clear_repository_helper, ERASURE_COMPLETED, ERASURE_IN_PROGRESS, INITIATE_ERASE, GET_ERASE_STATUS) def test_clear_repository_helper(): reserve_fn = MagicMock() reserve_fn.return_value = (0x1234) clear_fn = MagicMock() clear_fn.side_effect = [ ERASURE_COMPLETED, ERASURE_IN_PROGRESS, ERASURE_COMPLETED, ] clear_repository_helper(reserve_fn, clear_fn) clear_calls = [ call(INITIATE_ERASE, 0x1234), call(GET_ERASE_STATUS, 0x1234), call(GET_ERASE_STATUS, 0x1234), ] clear_fn.assert_has_calls(clear_calls) eq_(clear_fn.call_count, 3) python-ipmi-0.4.2/tests/test_bmc.py0000664000372000037200000000253513574451473020172 0ustar travistravis00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- from nose.tools import eq_ from pyipmi.bmc import DeviceId, Watchdog import pyipmi.msgs.bmc from pyipmi.msgs import decode_message def test_watchdog_object(): msg = pyipmi.msgs.bmc.GetWatchdogTimerRsp() decode_message(msg, b'\x00\x41\x42\x33\x44\x55\x66\x77\x88') wdt = Watchdog(msg) eq_(wdt.timer_use, 1) eq_(wdt.is_running, 1) eq_(wdt.dont_log, 0) eq_(wdt.timeout_action, 2) eq_(wdt.pre_timeout_interrupt, 4) eq_(wdt.pre_timeout_interval, 0x33) eq_(wdt.timer_use_expiration_flags, 0x44) eq_(wdt.initial_countdown, 0x6655) eq_(wdt.present_countdown, 0x8877) def test_deviceid_object(): rsp = pyipmi.msgs.bmc.GetDeviceIdRsp() decode_message(rsp, b'\x00\x12\x84\x05\x67\x51\x55\x12\x34\x56\x44\x55') dev = DeviceId(rsp) eq_(dev.device_id, 18) eq_(dev.revision, 4) eq_(dev.provides_sdrs, True) eq_(str(dev.fw_revision), '5.67') eq_(str(dev.ipmi_version), '1.5') eq_(dev.manufacturer_id, 5649426) eq_(dev.product_id, 21828) eq_(dev.aux, None) def test_deviceid_object_with_aux(): msg = pyipmi.msgs.bmc.GetDeviceIdRsp() decode_message(msg, b'\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x01\x02\x03\x04') device_id = DeviceId(msg) eq_(device_id.aux, [1, 2, 3, 4]) python-ipmi-0.4.2/tests/test_picmg.py0000664000372000037200000000340013574451473020520 0ustar travistravis00000000000000#!/usr/bin/env python from nose.tools import eq_ from pyipmi.picmg import LedState from pyipmi.msgs.picmg import SetFruLedStateReq def test_to_request(): req = SetFruLedStateReq() led = LedState(fru_id=1, led_id=2, color=LedState.COLOR_GREEN, function=LedState.FUNCTION_ON) led.to_request(req) eq_(req.fru_id, 1) eq_(req.led_id, 2) eq_(req.color, led.COLOR_GREEN) eq_(req.led_function, 0xff) eq_(req.on_duration, 0) def test_to_request_function_on(): req = SetFruLedStateReq() led = LedState(fru_id=1, led_id=2, color=LedState.COLOR_RED) led.override_function = led.FUNCTION_ON led.to_request(req) eq_(req.color, LedState.COLOR_RED) eq_(req.led_function, 0xff) eq_(req.on_duration, 0) def test_to_request_function_off(): req = SetFruLedStateReq() led = LedState(fru_id=1, led_id=2, color=LedState.COLOR_RED) led.override_function = led.FUNCTION_OFF led.to_request(req) eq_(req.color, LedState.COLOR_RED) eq_(req.led_function, 0) eq_(req.on_duration, 0) def test_to_request_function_blinking(): req = SetFruLedStateReq() led = LedState(fru_id=1, led_id=2, color=LedState.COLOR_RED) led.override_function = led.FUNCTION_BLINKING led.override_off_duration = 3 led.override_on_duration = 4 led.to_request(req) eq_(req.color, LedState.COLOR_RED) eq_(req.led_function, 3) eq_(req.on_duration, 4) def test_to_request_function_lamp_test(): req = SetFruLedStateReq() led = LedState(fru_id=1, led_id=2, color=LedState.COLOR_RED) led.override_function = led.FUNCTION_LAMP_TEST led.lamp_test_duration = 3 led.to_request(req) eq_(req.color, LedState.COLOR_RED) eq_(req.led_function, 0xfb) eq_(req.on_duration, 3) python-ipmi-0.4.2/tests/msgs/0000775000372000037200000000000013574451533016761 5ustar travistravis00000000000000python-ipmi-0.4.2/tests/msgs/test_message.py0000664000372000037200000000330613574451473022023 0ustar travistravis00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- from nose.tools import eq_ from array import array from pyipmi.utils import ByteBuffer from pyipmi.msgs.message import Message, UnsignedInt, RemainingBytes, String class TestMessage(object): def __init__(self, field): setattr(self, field.name, field.create()) self.field = field def encode(self): data = ByteBuffer() self.field.encode(self, data) return data def decode(self, data): data = ByteBuffer(data) self.field.decode(self, data) def test_unsignedint_encode(): t = TestMessage(UnsignedInt('test', 4)) t.test = 0x12345678 byte_buffer = t.encode() eq_(byte_buffer.array, array('B', [0x78, 0x56, 0x34, 0x12])) t = TestMessage(UnsignedInt('test', 8)) t.test = 0x12345678 byte_buffer = t.encode() eq_(byte_buffer.array, array('B', [0x78, 0x56, 0x34, 0x12, 0, 0, 0, 0])) def test_unsignedint_decode(): t = TestMessage(UnsignedInt('test', 1)) t.decode(b'\x12') eq_(t.test, 0x12) t.decode(b'\xd7') eq_(t.test, 0xd7) def test_string_encode(): t = TestMessage(String('test', 10)) t.test = '1234' byte_buffer = t.encode() eq_(byte_buffer.array, array('B', [0x31, 0x32, 0x33, 0x34])) def test_string_decode(): t = TestMessage(String('test', 10)) t.decode(b'abcdef') eq_(t.test, b'abcdef') def test_remainingbytes_encode(): t = TestMessage(RemainingBytes('test')) t.test = [0xb4, 1] byte_buffer = t.encode() eq_(byte_buffer.array, array('B', [0xb4, 0x01])) def test_message(): msg = Message() msg.__netfn__ = 0x1 msg.__cmdid__ = 0x2 eq_(msg.lun, 0) eq_(msg.netfn, 1) eq_(msg.cmdid, 2) python-ipmi-0.4.2/tests/msgs/test_chassis.py0000664000372000037200000000325613574451473022040 0ustar travistravis00000000000000#!/usr/bin/env python from nose.tools import eq_ import pyipmi.msgs.chassis from pyipmi.msgs import encode_message, decode_message def test_getchassisstatus_encode_valid_req(): m = pyipmi.msgs.chassis.GetChassisStatusReq() data = encode_message(m) eq_(m.__netfn__, 0) eq_(m.__cmdid__, 1) eq_(data, b'') def test_getchassisstatus_decode_valid_rsp(): m = pyipmi.msgs.chassis.GetChassisStatusRsp() decode_message(m, b'\x00\xea\xaa\xaa') eq_(m.completion_code, 0x00) eq_(m.current_power_state.power_on, 0) eq_(m.current_power_state.power_overload, 1) eq_(m.current_power_state.interlock, 0) eq_(m.current_power_state.power_fault, 1) eq_(m.current_power_state.power_control_fault, 0) eq_(m.current_power_state.power_restore_policy, 3) eq_(m.last_power_event.ac_failed, 0) eq_(m.last_power_event.power_overload, 1) eq_(m.last_power_event.power_interlock, 0) eq_(m.last_power_event.power_fault, 1) eq_(m.last_power_event.power_is_on_via_ipmi_command, 0) eq_(m.misc_chassis_state.chassis_intrusion_active, 0) eq_(m.misc_chassis_state.front_panel_lockout_active, 1) eq_(m.misc_chassis_state.drive_fault, 0) eq_(m.misc_chassis_state.cooling_fault_detected, 1) def test_getchassisstatus_decode_valid_optional_byte_rsp(): m = pyipmi.msgs.chassis.GetChassisStatusRsp() decode_message(m, b'\x00\x00\x00\00\xaa') eq_(m.completion_code, 0x00) eq_(m.front_panel_button_capabilities, 0xaa) def test_chassiscontrol_encode_valid_req(): m = pyipmi.msgs.chassis.ChassisControlReq() m.control.option = 1 data = encode_message(m) eq_(m.__netfn__, 0) eq_(m.__cmdid__, 2) eq_(data, b'\x01') python-ipmi-0.4.2/tests/msgs/test_bmc.py0000664000372000037200000001070613574451473021142 0ustar travistravis00000000000000#!/usr/bin/env python from array import array from nose.tools import eq_ import pyipmi.msgs.bmc from pyipmi.msgs import decode_message def test_getdeviceid_decode_rsp_with_cc(): m = pyipmi.msgs.bmc.GetDeviceIdRsp() decode_message(m, b'\xc0') eq_(m.completion_code, 0xc0) def test_getdeviceid_decode_valid_res(): m = pyipmi.msgs.bmc.GetDeviceIdRsp() decode_message(m, b'\x00\x0c\x89\x00\x00\x02\x3d\x98' b'\x3a\x00\xbe\x14\x04\x00\x02\x00') eq_(m.completion_code, 0) eq_(m.device_id, 0x0c) eq_(m.device_revision.device_revision, 9) eq_(m.device_revision.provides_device_sdrs, 1) eq_(m.firmware_revision.major, 0) eq_(m.firmware_revision.device_available, 0) eq_(m.firmware_revision.minor, 0) eq_(m.ipmi_version, 2) eq_(m.additional_support.sensor, 1) eq_(m.additional_support.sdr_repository, 0) eq_(m.additional_support.sel, 1) eq_(m.additional_support.fru_inventory, 1) eq_(m.additional_support.ipmb_event_receiver, 1) eq_(m.additional_support.ipmb_event_generator, 1) eq_(m.additional_support.bridge, 0) eq_(m.additional_support.chassis, 0) eq_(m.manufacturer_id, 15000) eq_(m.product_id, 5310) eq_(m.auxiliary, array('B', [4, 0, 2, 0])) def test_getdeviceid_decode_valid_res_wo_aux(): m = pyipmi.msgs.bmc.GetDeviceIdRsp() decode_message(m, b'\x00\x0c\x89\x00\x00\x02\x3d\x98' b'\x3a\x00\xbe\x14') eq_(m.completion_code, 0) eq_(m.device_id, 0x0c) eq_(m.device_revision.device_revision, 9) eq_(m.device_revision.provides_device_sdrs, 1) eq_(m.firmware_revision.major, 0) eq_(m.firmware_revision.device_available, 0) eq_(m.firmware_revision.minor, 0) eq_(m.ipmi_version, 2) eq_(m.additional_support.sensor, 1) eq_(m.additional_support.sdr_repository, 0) eq_(m.additional_support.sel, 1) eq_(m.additional_support.fru_inventory, 1) eq_(m.additional_support.ipmb_event_receiver, 1) eq_(m.additional_support.ipmb_event_generator, 1) eq_(m.additional_support.bridge, 0) eq_(m.additional_support.chassis, 0) eq_(m.manufacturer_id, 15000) eq_(m.product_id, 5310) def test_getselftestresults_decode_test_passed_rsp(): m = pyipmi.msgs.bmc.GetSelftestResultsRsp() decode_message(m, b'\x00\x55\x00') eq_(m.completion_code, 0x00) eq_(m.result, 0x55) eq_(int(m.status), 0x00) def test_getselftestresults_decode_test_fail_not_implemented_rsp(): m = pyipmi.msgs.bmc.GetSelftestResultsRsp() decode_message(m, b'\x00\x56\x00') eq_(m.completion_code, 0x00) eq_(m.result, 0x56) eq_(int(m.status), 0x00) def test_getselftestresults_decode_test_fail_corrupted_sel_rsp(): m = pyipmi.msgs.bmc.GetSelftestResultsRsp() decode_message(m, b'\x00\x57\x80') eq_(m.completion_code, 0x00) eq_(m.result, 0x57) eq_(int(m.status), 0x80) eq_(m.status.cannot_access_sel_device, 1) eq_(m.status.cannot_access_sdr_device, 0) eq_(m.status.cannot_access_bmc_fru_device, 0) eq_(m.status.ipmb_signal_lines_do_not_respond, 0) eq_(m.status.sdr_repository_empty, 0) eq_(m.status.internal_use_area_corrupted, 0) eq_(m.status.controller_bootblock_corrupted, 0) eq_(m.status.controller_firmware_corrupted, 0) def test_getselftestresults_decode_test_fail_corrupted_sdr_rsp(): m = pyipmi.msgs.bmc.GetSelftestResultsRsp() decode_message(m, b'\x00\x57\x40') eq_(m.completion_code, 0x00) eq_(m.result, 0x57) eq_(int(m.status), 0x40) eq_(m.status.cannot_access_sel_device, 0) eq_(m.status.cannot_access_sdr_device, 1) eq_(m.status.cannot_access_bmc_fru_device, 0) eq_(m.status.ipmb_signal_lines_do_not_respond, 0) eq_(m.status.sdr_repository_empty, 0) eq_(m.status.internal_use_area_corrupted, 0) eq_(m.status.controller_bootblock_corrupted, 0) eq_(m.status.controller_firmware_corrupted, 0) def test_getselftestresults_decode_test_fail_corrupted_fru_rsp(): m = pyipmi.msgs.bmc.GetSelftestResultsRsp() decode_message(m, b'\x00\x57\x20') eq_(m.completion_code, 0x00) eq_(m.result, 0x57) eq_(int(m.status), 0x20) eq_(m.status.cannot_access_sel_device, 0) eq_(m.status.cannot_access_sdr_device, 0) eq_(m.status.cannot_access_bmc_fru_device, 1) eq_(m.status.ipmb_signal_lines_do_not_respond, 0) eq_(m.status.sdr_repository_empty, 0) eq_(m.status.internal_use_area_corrupted, 0) eq_(m.status.controller_bootblock_corrupted, 0) eq_(m.status.controller_firmware_corrupted, 0) python-ipmi-0.4.2/tests/msgs/test_device_messaging.py0000664000372000037200000002534413574451473023701 0ustar travistravis00000000000000#!/usr/bin/env python from array import array from nose.tools import eq_ import pyipmi.msgs.device_messaging from pyipmi.msgs import encode_message from pyipmi.msgs import decode_message def test_setbmcglobalenables_encode_all_disabled_req(): m = pyipmi.msgs.device_messaging.SetBmcGlobalEnablesReq() m.enables.oem_2 = 0 m.enables.oem_1 = 0 m.enables.oem_0 = 0 m.enables.system_event_logging = 0 m.enables.event_message_buffer = 0 m.enables.event_message_buffer_full_interrupt = 0 m.enables.receive_message_queue_interrupt = 0 data = encode_message(m) eq_(data, b'\x00') def test_setbmcglobalenables_encode_enable_oem_2_req(): m = pyipmi.msgs.device_messaging.SetBmcGlobalEnablesReq() m.enables.oem_2 = 1 m.enables.oem_1 = 0 m.enables.oem_0 = 0 m.enables.system_event_logging = 0 m.enables.event_message_buffer = 0 m.enables.event_message_buffer_full_interrupt = 0 m.enables.receive_message_queue_interrupt = 0 data = encode_message(m) eq_(data, b'\x80') def test_setbmcglobalenables_encode_enable_oem_1_req(): m = pyipmi.msgs.device_messaging.SetBmcGlobalEnablesReq() m.enables.oem_2 = 0 m.enables.oem_1 = 1 m.enables.oem_0 = 0 m.enables.system_event_logging = 0 m.enables.event_message_buffer = 0 m.enables.event_message_buffer_full_interrupt = 0 m.enables.receive_message_queue_interrupt = 0 data = encode_message(m) eq_(data, b'\x40') def test_setbmcglobalenables_encode_enable_oem_0_req(): m = pyipmi.msgs.device_messaging.SetBmcGlobalEnablesReq() m.enables.oem_2 = 0 m.enables.oem_1 = 0 m.enables.oem_0 = 1 m.enables.system_event_logging = 0 m.enables.event_message_buffer = 0 m.enables.event_message_buffer_full_interrupt = 0 m.enables.receive_message_queue_interrupt = 0 data = encode_message(m) eq_(data, b'\x20') def test_setbmcglobalenables_encode_enable_receive_queue_interrupt_req(): m = pyipmi.msgs.device_messaging.SetBmcGlobalEnablesReq() m.enables.oem_2 = 0 m.enables.oem_1 = 0 m.enables.oem_0 = 0 m.enables.system_event_logging = 0 m.enables.event_message_buffer = 0 m.enables.event_message_buffer_full_interrupt = 0 m.enables.receive_message_queue_interrupt = 1 data = encode_message(m) eq_(data, b'\x01') def test_getbmcglobalenables_decode_all_disabled_rsp(): m = pyipmi.msgs.device_messaging.GetBmcGlobalEnablesRsp() decode_message(m, b'\x00\x00') eq_(m.completion_code, 0x00) eq_(m.enables.oem_2, 0) eq_(m.enables.oem_1, 0) eq_(m.enables.oem_0, 0) eq_(m.enables.system_event_logging, 0) eq_(m.enables.event_message_buffer, 0) eq_(m.enables.event_message_buffer_full_interrupt, 0) eq_(m.enables.receive_message_queue_interrupt, 0) def test_getbmcglobalenables_decode_oem_2_enabled_rsp(): m = pyipmi.msgs.device_messaging.GetBmcGlobalEnablesRsp() decode_message(m, b'\x00\x80') eq_(m.completion_code, 0x00) eq_(m.enables.oem_2, 1) eq_(m.enables.oem_1, 0) eq_(m.enables.oem_0, 0) eq_(m.enables.system_event_logging, 0) eq_(m.enables.event_message_buffer, 0) eq_(m.enables.event_message_buffer_full_interrupt, 0) eq_(m.enables.receive_message_queue_interrupt, 0) def test_getbmcglobalenables_decode_oem_0_enabled_rsp(): m = pyipmi.msgs.device_messaging.GetBmcGlobalEnablesRsp() decode_message(m, b'\x00\x20') eq_(m.completion_code, 0x00) eq_(m.enables.oem_2, 0) eq_(m.enables.oem_1, 0) eq_(m.enables.oem_0, 1) eq_(m.enables.system_event_logging, 0) eq_(m.enables.event_message_buffer, 0) eq_(m.enables.event_message_buffer_full_interrupt, 0) eq_(m.enables.receive_message_queue_interrupt, 0) def test_clearmessageflags_encode_clear_none_req(): m = pyipmi.msgs.device_messaging.ClearMessageFlagsReq() m.clear.oem_2 = 0 m.clear.oem_1 = 0 m.clear.oem_0 = 0 m.clear.watchdog_pretimeout_interrupt_flag = 0 m.clear.event_message_buffer = 0 m.clear.receive_message_queue = 0 data = encode_message(m) eq_(data, b'\x00') def test_clearmessageflags_encode_clear_oem_2_req(): m = pyipmi.msgs.device_messaging.ClearMessageFlagsReq() m.clear.oem_2 = 1 m.clear.oem_1 = 0 m.clear.oem_0 = 0 m.clear.watchdog_pretimeout_interrupt_flag = 0 m.clear.event_message_buffer = 0 m.clear.receive_message_queue = 0 data = encode_message(m) eq_(data, b'\x80') def test_clearmessageflags_encode_clear_oem_0_req(): m = pyipmi.msgs.device_messaging.ClearMessageFlagsReq() m.clear.oem_2 = 0 m.clear.oem_1 = 0 m.clear.oem_0 = 1 m.clear.watchdog_pretimeout_interrupt_flag = 0 m.clear.event_message_buffer = 0 m.clear.receive_message_queue = 0 data = encode_message(m) eq_(data, b'\x20') def test_clearmessageflags_encode_clear_receive_message_queue_req(): m = pyipmi.msgs.device_messaging.ClearMessageFlagsReq() m.clear.oem_2 = 0 m.clear.oem_1 = 0 m.clear.oem_0 = 0 m.clear.watchdog_pretimeout_interrupt_flag = 0 m.clear.event_message_buffer = 0 m.clear.receive_message_queue = 1 data = encode_message(m) eq_(data, b'\x01') def test_getmessageflags_decode_not_flag_set_rsp(): m = pyipmi.msgs.device_messaging.GetMessageFlagsRsp() decode_message(m, b'\x00\x00') eq_(m.completion_code, 0x00) eq_(m.flag.oem_2, 0) eq_(m.flag.oem_1, 0) eq_(m.flag.oem_0, 0) eq_(m.flag.watchdog_pretimeout_interrupt_occurred, 0) eq_(m.flag.event_message_buffer_full, 0) eq_(m.flag.receive_message_available, 0) def test_getmessageflags_decode_oem_2_set_rsp(): m = pyipmi.msgs.device_messaging.GetMessageFlagsRsp() decode_message(m, b'\x00\x80') eq_(m.completion_code, 0x00) eq_(m.flag.oem_2, 1) eq_(m.flag.oem_1, 0) eq_(m.flag.oem_0, 0) eq_(m.flag.watchdog_pretimeout_interrupt_occurred, 0) eq_(m.flag.event_message_buffer_full, 0) eq_(m.flag.receive_message_available, 0) def test_getmessageflags_decode_event_message_full_set_rsp(): m = pyipmi.msgs.device_messaging.GetMessageFlagsRsp() decode_message(m, b'\x00\x02') eq_(m.completion_code, 0x00) eq_(m.flag.oem_2, 0) eq_(m.flag.oem_1, 0) eq_(m.flag.oem_0, 0) eq_(m.flag.watchdog_pretimeout_interrupt_occurred, 0) eq_(m.flag.event_message_buffer_full, 1) eq_(m.flag.receive_message_available, 0) def test_enablemessagechannelreceive_encode_all_off_req(): m = pyipmi.msgs.device_messaging.EnableMessageChannelReceiveReq() m.channel.number = 0 m.channel.state = 0 data = encode_message(m) eq_(data, b'\x00\x00') def test_enablemessagechannelreceive_encode_channel1_enable_req(): m = pyipmi.msgs.device_messaging.EnableMessageChannelReceiveReq() m.channel.number = 1 m.channel.state = 1 data = encode_message(m) eq_(data, b'\x01\x01') def test_enablemessagechannelreceive_encode_channel2_enable_req(): m = pyipmi.msgs.device_messaging.EnableMessageChannelReceiveReq() m.channel.number = 2 m.channel.state = 1 data = encode_message(m) eq_(data, b'\x02\x01') def test_enablemessagechannelreceive_decode_channel1_enabled_rsp(): m = pyipmi.msgs.device_messaging.EnableMessageChannelReceiveRsp() decode_message(m, b'\x00\x01\x01') eq_(m.completion_code, 0x00) eq_(m.channel.number, 1) eq_(m.channel.state, 1) def test_getmessage_decode_no_data_rsp(): m = pyipmi.msgs.device_messaging.GetMessageRsp() decode_message(m, b'\x00\x21') eq_(m.completion_code, 0x00) eq_(m.channel.number, 1) eq_(m.channel.privilege_level, 2) def test_getmessage_decode_with_data_rsp(): m = pyipmi.msgs.device_messaging.GetMessageRsp() decode_message(m, b'\x00\x21\xaa\xff\xff\xee') eq_(m.completion_code, 0x00) eq_(m.channel.number, 1) eq_(m.channel.privilege_level, 2) eq_(m.data, array('B', [0xaa, 0xff, 0xff, 0xee])) def test_readeventmessagebuffer_decode_rsp(): m = pyipmi.msgs.device_messaging.ReadEventMessageBufferRsp() decode_message(m, b'\x00\x00\x01\x02\x03\x04\x05\x06\x07' b'\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f') eq_(m.completion_code, 0x00) eq_(m.event_data, array('B', b'\x00\x01\x02\x03\x04' b'\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f')) def test_masterwriteread_encode_req_all_zero_read(): m = pyipmi.msgs.device_messaging.MasterWriteReadReq() m.bus_id.type = 0 m.bus_id.id = 0 m.bus_id.channel = 0 m.bus_id.slave_address = 0 m.read_count = 0 data = encode_message(m) eq_(data, b'\x00\x00\x00') def test_masterwriteread_encode_req_for_read(): m = pyipmi.msgs.device_messaging.MasterWriteReadReq() m.bus_id.type = 1 m.bus_id.id = 2 m.bus_id.channel = 4 m.bus_id.slave_address = 0x3a m.read_count = 5 data = encode_message(m) eq_(data, b'\x45\x74\x05') def test_masterwriteread_encode_req_for_write(): m = pyipmi.msgs.device_messaging.MasterWriteReadReq() m.bus_id.type = 0 m.bus_id.id = 0 m.bus_id.channel = 0 m.bus_id.slave_address = 0 m.read_count = 0 m.data = [1, 0x23, 0x45] data = encode_message(m) eq_(data, b'\x00\x00\x00\x01\x23\x45') def test_masterwriteread_decode_rsp(): m = pyipmi.msgs.device_messaging.MasterWriteReadRsp() decode_message(m, b'\x00\x11\x22\x33\x44') eq_(m.completion_code, 0x00) eq_(m.data, array('B', [0x11, 0x22, 0x33, 0x44])) def test_get_channel_authentication_capabilities_req(): m = pyipmi.msgs.device_messaging.GetChannelAuthenticationCapabilitiesReq() m.channel.number = 6 m.channel.type = 1 m.privilege_level.requested = 5 data = encode_message(m) eq_(m.cmdid, 0x38) eq_(m.netfn, 6) eq_(data, b'\x86\x05') def test_get_channel_authentication_capabilities_rsp(): m = pyipmi.msgs.device_messaging.GetChannelAuthenticationCapabilitiesRsp() decode_message(m, b'\x00\x01\x15\x19\x44\x55\x66\x77\x88') eq_(m.cmdid, 0x38) eq_(m.netfn, 7) eq_(m.completion_code, 0x00) eq_(m.channel_number, 1) eq_(m.support.none, 1) eq_(m.support.md2, 0) eq_(m.support.md5, 1) eq_(m.support.straight, 1) eq_(m.support.oem_proprietary, 0) eq_(m.status.anonymous_login_enabled, 1) eq_(m.status.anonymous_login_null_user, 0) eq_(m.status.anonymous_login_non_null, 0) eq_(m.status.user_level, 1) eq_(m.status.per_message, 1) eq_(m.status.kg, 0) def test_get_session_challenge_req(): m = pyipmi.msgs.device_messaging.GetSessionChallengeReq() m.authentication.type = 1 # m.user_name = "helloworld" data = encode_message(m) eq_(m.cmdid, 0x39) eq_(m.netfn, 6) eq_(data, b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') m.authentication.type = 1 m.user_name = '0123456789abcdef' data = encode_message(m) eq_(m.cmdid, 0x39) eq_(m.netfn, 6) eq_(data, b'\x010123456789abcdef') python-ipmi-0.4.2/tests/msgs/test_picmg.py0000664000372000037200000001141213574451473021473 0ustar travistravis00000000000000#!/usr/bin/env python from nose.tools import eq_ import pyipmi.msgs.bmc import pyipmi.msgs.sel import pyipmi.msgs.event import pyipmi.msgs.hpm import pyipmi.msgs.sensor from pyipmi.msgs import constants, decode_message, encode_message from pyipmi.msgs.picmg import PICMG_IDENTIFIER def test_get_picmg_properties_req(): msg = pyipmi.msgs.picmg.GetPicmgPropertiesReq() eq_(msg.cmdid, constants.CMDID_GET_PICMG_PROPERTIES) eq_(msg.netfn, constants.NETFN_GROUP_EXTENSION) eq_(msg.group_extension, PICMG_IDENTIFIER) def test_get_address_info_picmg_2_9_rsp(): m = pyipmi.msgs.picmg.GetAddressInfoRsp() decode_message(m, b'\x00\x00\x01\x02\x03') eq_(m.completion_code, 0x00) eq_(m.picmg_identifier, 0x00) eq_(m.hardware_address, 0x01) eq_(m.ipmb_0_address, 0x02) eq_(m.ipmb_1_address, 0x03) eq_(m.fru_id, None) eq_(m.site_id, None) eq_(m.site_type, None) eq_(m.carrier_number, None) def test_get_address_info_picmg_3_0_rsp(): m = pyipmi.msgs.picmg.GetAddressInfoRsp() decode_message(m, b'\x00\x00\x01\x02\xff\x04\x05\x06') eq_(m.completion_code, 0x00) eq_(m.picmg_identifier, 0x00) eq_(m.hardware_address, 0x01) eq_(m.ipmb_0_address, 0x02) eq_(m.ipmb_1_address, 0xff) eq_(m.fru_id, 0x04) eq_(m.site_id, 0x05) eq_(m.site_type, 0x06) eq_(m.carrier_number, None) def test_get_address_info_mtca_rsp(): m = pyipmi.msgs.picmg.GetAddressInfoRsp() decode_message(m, b'\x00\x00\x01\x02\x03\x04\x05\x06\x07') eq_(m.completion_code, 0x00) eq_(m.picmg_identifier, 0x00) eq_(m.hardware_address, 0x01) eq_(m.ipmb_0_address, 0x02) eq_(m.ipmb_1_address, 0x03) eq_(m.fru_id, 0x04) eq_(m.site_id, 0x05) eq_(m.site_type, 0x06) eq_(m.carrier_number, 0x07) def test_get_shelf_address_info_rsp(): m = pyipmi.msgs.picmg.GetShelfAddressInfoRsp() decode_message(m, b'\x00\x00\x01\x02') eq_(m.completion_code, 0x00) eq_(m.picmg_identifier, 0x00) eq_(m.shelf_address[0], 0x01) eq_(m.shelf_address[1], 0x02) def test_clear_activation_lock_req(): m = pyipmi.msgs.picmg.SetFruActivationPolicyReq() m.fru_id = 1 m.mask.activation_locked = 1 m.set.activation_locked = 0 data = encode_message(m) eq_(data, b'\x00\x01\x01\x00') def test_set_activation_lock_req(): m = pyipmi.msgs.picmg.SetFruActivationPolicyReq() m.fru_id = 1 m.mask.activation_locked = 1 m.set.activation_locked = 1 data = encode_message(m) eq_(data, b'\x00\x01\x01\x01') def test_clear_deactivation_lock_req(): m = pyipmi.msgs.picmg.SetFruActivationPolicyReq() m.fru_id = 1 m.mask.deactivation_locked = 1 m.set.deactivation_locked = 0 data = encode_message(m) eq_(data, b'\x00\x01\x02\x00') def test_set_deactivation_lock_req(): m = pyipmi.msgs.picmg.SetFruActivationPolicyReq() m.fru_id = 1 m.mask.deactivation_locked = 1 m.set.deactivation_locked = 1 data = encode_message(m) eq_(data, b'\x00\x01\x02\x02') def test_decode_rsp_local_control_state(): m = pyipmi.msgs.picmg.GetFruLedStateRsp() decode_message(m, b'\x00\x00\x01\xff\x00\x02') eq_(m.completion_code, 0x00) eq_(m.led_states.local_avail, 1) eq_(m.local_function, 0xff) eq_(m.local_on_duration, 0) eq_(m.local_color, 2) def test_decode_rsp_override_mode(): m = pyipmi.msgs.picmg.GetFruLedStateRsp() decode_message(m, b'\x00\x00\x03\xff\x00\x03\xff\x00\x03') eq_(m.completion_code, 0x00) eq_(m.led_states.local_avail, 1) eq_(m.local_function, 0xff) eq_(m.local_on_duration, 0) eq_(m.local_color, 3) eq_(m.led_states.override_en, 1) eq_(m.override_function, 0xff) eq_(m.override_on_duration, 0) eq_(m.override_color, 3) eq_(m.led_states.lamp_test_en, 0) def test_decode_rsp_lamp_test_and_override_mode(): m = pyipmi.msgs.picmg.GetFruLedStateRsp() decode_message(m, b'\x00\x00\x07\xff\x00\x02\xff\x00\x02\x7f') eq_(m.completion_code, 0x00) eq_(m.led_states.local_avail, 1) eq_(m.local_function, 0xff) eq_(m.local_on_duration, 0) eq_(m.local_color, 2) eq_(m.led_states.override_en, 1) eq_(m.override_function, 0xff) eq_(m.override_on_duration, 0) eq_(m.override_color, 2) eq_(m.led_states.lamp_test_en, 1) eq_(m.lamp_test_duration, 0x7f) def test_decode_rsp_only_lamp_test_mode(): m = pyipmi.msgs.picmg.GetFruLedStateRsp() decode_message(m, b'\x00\x00\x04\xff\x00\x02\xff\x00\x02\x7f') eq_(m.completion_code, 0x00) eq_(m.led_states.local_avail, 0) eq_(m.local_function, 0xff) eq_(m.local_on_duration, 0) eq_(m.local_color, 2) eq_(m.led_states.override_en, 0) eq_(m.override_function, 0xff) eq_(m.override_on_duration, 0) eq_(m.override_color, 2) eq_(m.led_states.lamp_test_en, 1) eq_(m.lamp_test_duration, 0x7f) python-ipmi-0.4.2/tests/msgs/test_hpm.py0000664000372000037200000000230313574451473021157 0ustar travistravis00000000000000#!/usr/bin/env python from nose.tools import eq_ import pyipmi.msgs.hpm from pyipmi.msgs import encode_message from pyipmi.msgs import decode_message def test_uploadfirmwareblockreq_encode(): m = pyipmi.msgs.hpm.UploadFirmwareBlockReq() m.number = 1 m.data = [0, 1, 2, 3] data = encode_message(m) eq_(data, b'\x00\x01\x00\x01\x02\x03') def test_activatefirmwarereq_decode_valid_req(): m = pyipmi.msgs.hpm.ActivateFirmwareReq() decode_message(m, b'\x00\x01') eq_(m.picmg_identifier, 0) eq_(m.rollback_override_policy, 1) def test_activatefirmwarereq_encode_valid_req(): m = pyipmi.msgs.hpm.ActivateFirmwareReq() m.picmg_identifier = 0 m.rollback_override_policy = 0x1 data = encode_message(m) eq_(data, b'\x00\x01') def test_activatefirmwarereq_decode_valid_req_wo_optional(): m = pyipmi.msgs.hpm.ActivateFirmwareReq() decode_message(m, b'\x00') eq_(m.picmg_identifier, 0) eq_(m.rollback_override_policy, None) def test_activatefirmwarereq_encode_valid_req_wo_optional(): m = pyipmi.msgs.hpm.ActivateFirmwareReq() m.picmg_identifier = 0 m.rollback_override_policy = None data = encode_message(m) eq_(data, b'\x00') python-ipmi-0.4.2/tests/msgs/test_sensor.py0000664000372000037200000001656413574451473021722 0ustar travistravis00000000000000#!/usr/bin/env python from array import array from nose.tools import eq_ import pyipmi.msgs.sensor from pyipmi.msgs import encode_message from pyipmi.msgs import decode_message def test_getdevicesdrinfo_encode_req(): m = pyipmi.msgs.sensor.GetDeviceSdrInfoReq() data = encode_message(m) eq_(data, b'') def test_getdevicesdrinfo_encode_rsp(): m = pyipmi.msgs.sensor.GetDeviceSdrInfoRsp() decode_message(m, b'\x00\x03\x05') eq_(m.completion_code, 0x00) eq_(m.number_of_sensors, 3) eq_(m.flags.lun0_has_sensors, 1) eq_(m.flags.lun1_has_sensors, 0) eq_(m.flags.lun2_has_sensors, 1) eq_(m.flags.lun3_has_sensors, 0) eq_(m.flags.dynamic_population, 0) def test_getdevicesdrinfo_encode_rsp_with_timestamp(): m = pyipmi.msgs.sensor.GetDeviceSdrInfoRsp() decode_message(m, b'\x00\x12\x01\xaa\xbb\xcc\xdd') eq_(m.completion_code, 0x00) eq_(m.number_of_sensors, 0x12) eq_(m.flags.lun0_has_sensors, 1) eq_(m.flags.lun1_has_sensors, 0) eq_(m.flags.lun2_has_sensors, 0) eq_(m.flags.lun3_has_sensors, 0) eq_(m.flags.dynamic_population, 0) eq_(m.sensor_population_change, 0xddccbbaa) def test_getdevicesdr_encode_req(): m = pyipmi.msgs.sensor.GetDeviceSdrReq() m.reservation_id = 0x0123 m.record_id = 0x4567 m.offset = 0x89 m.bytes_to_read = 0xab data = encode_message(m) eq_(data, b'\x23\x01\x67\x45\x89\xab') def test_getdevicesdr_decode_rsp(): m = pyipmi.msgs.sensor.GetDeviceSdrRsp() decode_message(m, b'\x00\x01\x23\xaa\xbb') eq_(m.completion_code, 0x00) eq_(m.next_record_id, 0x2301) eq_(m.record_data, array('B', [0xaa, 0xbb]) ) def test_setsensorhysteresis_encode_req(): m = pyipmi.msgs.sensor.SetSensorHysteresisReq() m.sensor_number = 0xab m.positive_going_hysteresis = 0xaa m.negative_going_hysteresis = 0xbb data = encode_message(m) eq_(data, b'\xab\xff\xaa\xbb') def test_getsensorhysteresis_encode_req(): m = pyipmi.msgs.sensor.GetSensorHysteresisReq() m.sensor_number = 0xab data = encode_message(m) eq_(data, b'\xab\xff') def test_getsensorhysteresis_decode_rsp(): m = pyipmi.msgs.sensor.GetSensorHysteresisRsp() decode_message(m, b'\x00\xaa\xbb') eq_(m.completion_code, 0x00) eq_(m.positive_going_hysteresis, 0xaa) eq_(m.negative_going_hysteresis, 0xbb) def test_setsensorthresholds_encode_req_set_unr(): m = pyipmi.msgs.sensor.SetSensorThresholdsReq() m.sensor_number = 0x55 m.set_mask.unr = 1 m.threshold.unr = 0xaa data = encode_message(m) eq_(data, b'\x55\x20\x00\x00\x00\x00\x00\xaa') def test_setsensorthresholds_encode_req_set_ucr(): m = pyipmi.msgs.sensor.SetSensorThresholdsReq() m.sensor_number = 0x55 m.set_mask.ucr = 1 m.threshold.ucr = 0xaa data = encode_message(m) eq_(data, b'\x55\x10\x00\x00\x00\x00\xaa\x00') def test_setsensorthresholds_encode_req_set_unc(): m = pyipmi.msgs.sensor.SetSensorThresholdsReq() m.sensor_number = 0x55 m.set_mask.unc = 1 m.threshold.unc = 0xaa data = encode_message(m) eq_(data, b'\x55\x08\x00\x00\x00\xaa\x00\x00') def test_setsensorthresholds_encode_req_set_lnr(): m = pyipmi.msgs.sensor.SetSensorThresholdsReq() m.sensor_number = 0x55 m.set_mask.lnr = 1 m.threshold.lnr = 0xaa data = encode_message(m) eq_(data, b'\x55\x04\x00\x00\xaa\x00\x00\x00') def test_setsensorthresholds_encode_req_set_lcr(): m = pyipmi.msgs.sensor.SetSensorThresholdsReq() m.sensor_number = 0x55 m.set_mask.lcr = 1 m.threshold.lcr = 0xaa data = encode_message(m) eq_(data, b'\x55\x02\x00\xaa\x00\x00\x00\x00') def test_setsensorthresholds_encode_req_set_lnc(): m = pyipmi.msgs.sensor.SetSensorThresholdsReq() m.sensor_number = 0x55 m.set_mask.lnc = 1 m.threshold.lnc = 0xaa data = encode_message(m) eq_(data, b'\x55\x01\xaa\x00\x00\x00\x00\x00') def test_setsensoreventenable_encode_req(): m = pyipmi.msgs.sensor.SetSensorEventEnableReq() m.sensor_number = 0xab m.enable.config = 0 m.enable.event_message = 0 m.enable.sensor_scanning = 0 data = encode_message(m) eq_(data, b'\xab\x00') def test_setsensoreventenable_encode_cfg_req(): m = pyipmi.msgs.sensor.SetSensorEventEnableReq() m.sensor_number = 0xab m.enable.config = 2 m.enable.event_message = 0 m.enable.sensor_scanning = 0 data = encode_message(m) eq_(data, b'\xab\x20') def test_setsensoreventenable_encode_scanning_enabled_req(): m = pyipmi.msgs.sensor.SetSensorEventEnableReq() m.sensor_number = 0xab m.enable.config = 0 m.enable.event_message = 0 m.enable.sensor_scanning = 1 data = encode_message(m) eq_(data, b'\xab\x40') def test_setsensoreventenable_encode_event_enabled_req(): m = pyipmi.msgs.sensor.SetSensorEventEnableReq() m.sensor_number = 0xab m.enable.config = 0 m.enable.event_message = 1 m.enable.sensor_scanning = 0 data = encode_message(m) eq_(data, b'\xab\x80') def test_setsensoreventenable_encode_byte3_req(): m = pyipmi.msgs.sensor.SetSensorEventEnableReq() m.sensor_number = 0xab m.enable.config = 0 m.enable.event_message = 0 m.enable.sensor_scanning = 0 m.byte3 = 0xaa data = encode_message(m) eq_(data, b'\xab\x00\xaa') def test_setsensoreventenable_encode_byte34_req(): m = pyipmi.msgs.sensor.SetSensorEventEnableReq() m.sensor_number = 0xab m.enable.config = 0 m.enable.event_message = 0 m.enable.sensor_scanning = 0 m.byte3 = 0xaa m.byte4 = 0xbb data = encode_message(m) eq_(data, b'\xab\x00\xaa\xbb') def test_getsensoreventenable_encode_req(): m = pyipmi.msgs.sensor.GetSensorEventEnableReq() m.sensor_number = 0xab data = encode_message(m) eq_(data, b'\xab') def test_getsensoreventenable_decode_event_enabled_rsp(): m = pyipmi.msgs.sensor.GetSensorEventEnableRsp() decode_message(m, b'\x00\x80') eq_(m.completion_code, 0x00) eq_(m.enabled.event_message, 1) eq_(m.enabled.sensor_scanning, 0) def test_getsensoreventenable_decode_scanning_enabled_rsp(): m = pyipmi.msgs.sensor.GetSensorEventEnableRsp() decode_message(m, b'\x00\x40') eq_(m.completion_code, 0x00) eq_(m.enabled.event_message, 0) eq_(m.enabled.sensor_scanning, 1) def test_getsensoreventenable_decode_byte3_rsp(): m = pyipmi.msgs.sensor.GetSensorEventEnableRsp() decode_message(m, b'\x00\xc0\xaa') eq_(m.completion_code, 0x00) eq_(m.enabled.event_message, 1) eq_(m.byte3, 0xaa) def test_getsensoreventenable_decode_byte34_rsp(): m = pyipmi.msgs.sensor.GetSensorEventEnableRsp() decode_message(m, b'\x00\xc0\xaa\xbb') eq_(m.completion_code, 0x00) eq_(m.enabled.event_message, 1) eq_(m.byte3, 0xaa) eq_(m.byte4, 0xbb) def test_getsensoreventenable_decode_byte3456_rsp(): m = pyipmi.msgs.sensor.GetSensorEventEnableRsp() decode_message(m, b'\x00\xc0\xaa\xbb\xcc\xdd') eq_(m.completion_code, 0x00) eq_(m.enabled.event_message, 1) eq_(m.byte3, 0xaa) eq_(m.byte4, 0xbb) eq_(m.byte5, 0xcc) eq_(m.byte6, 0xdd) def test_rearmsensorevents_encode_req(): m = pyipmi.msgs.sensor.RearmSensorEventsReq() m.sensor_number = 0xab data = encode_message(m) eq_(data, b'\xab\x00\x00\x00\x00\x00') def test_rearmsensorevents_decode_rsp(): m = pyipmi.msgs.sensor.RearmSensorEventsRsp() decode_message(m, b'\x00') eq_(m.completion_code, 0x00) python-ipmi-0.4.2/tests/msgs/test_sel.py0000664000372000037200000000202013574451473021152 0ustar travistravis00000000000000#!/usr/bin/env python from array import array from nose.tools import eq_, raises import pyipmi.msgs.sel from pyipmi.errors import DecodingError from pyipmi.msgs import encode_message from pyipmi.msgs import decode_message def test_getselentry_decode_rsp_with_cc(): m = pyipmi.msgs.sel.GetSelEntryRsp() decode_message(m, b'\xc0') eq_(m.completion_code, 0xc0) @raises(DecodingError) def test_getselentry_decode_invalid_rsp(): m = pyipmi.msgs.sel.GetSelEntryRsp() decode_message(m, b'\x00\x01') def test_getselentry_decode_valid_rsp(): m = pyipmi.msgs.sel.GetSelEntryRsp() decode_message(m, b'\x00\x02\x01\x01\x02\x03\x04') eq_(m.completion_code, 0x00) eq_(m.next_record_id, 0x0102) eq_(m.record_data, array('B', [1,2,3,4])) def test_getselentry_encode_valid_rsp(): m = pyipmi.msgs.sel.GetSelEntryRsp() m.completion_code = 0 m.next_record_id = 0x0102 m.record_data = array('B', b'\x01\x02\x03\x04') data = encode_message(m) eq_(data, b'\x00\x02\x01\x01\x02\x03\x04') python-ipmi-0.4.2/tests/msgs/test_fru.py0000664000372000037200000000622113574451473021172 0ustar travistravis00000000000000#!/usr/bin/env python from array import array from nose.tools import eq_, raises import pyipmi.msgs.fru from pyipmi.errors import DecodingError, EncodingError from pyipmi.msgs import encode_message, decode_message def test_fruinventoryareainfo_decode_valid_rsp(): m = pyipmi.msgs.fru.GetFruInventoryAreaInfoRsp() decode_message(m, b'\x00\x01\x02\x01') eq_(m.completion_code, 0x00) eq_(m.area_size, 0x0201) eq_(m.area_info.access, 1) def test_writefrudatareq_decode_valid_req(): m = pyipmi.msgs.fru.WriteFruDataReq() decode_message(m, b'\x01\x02\x03\x04\x05') eq_(m.fru_id, 1) eq_(m.offset, 0x302) eq_(m.data, array('B', b'\x04\x05')) def test_writefrudatareq_encode_valid_req(): m = pyipmi.msgs.fru.WriteFruDataReq() m.fru_id = 1 m.offset = 0x302 m.data = array('B', b'\x04\x05') data = encode_message(m) eq_(data, b'\x01\x02\x03\x04\x05') def test_writefrudatareq_decode_valid_req_wo_data(): m = pyipmi.msgs.fru.WriteFruDataReq() decode_message(m, b'\x01\x02\x03') eq_(m.fru_id, 1) eq_(m.offset, 0x302) eq_(m.data, array('B')) def test_writefrudatareq_encode_valid_req_wo_data(): m = pyipmi.msgs.fru.WriteFruDataReq() m.fru_id = 1 m.offset = 0x302 m.data = array('B') data = encode_message(m) eq_(data, b'\x01\x02\x03') @raises(DecodingError) def test_writefrudatareq_decode_invalid_req(): m = pyipmi.msgs.fru.WriteFruDataReq() decode_message(m, b'\x01\x02') def test_readfrudatareq_decode_valid_req(): m = pyipmi.msgs.fru.ReadFruDataReq() decode_message(m, b'\x01\x02\x03\x04') eq_(m.fru_id, 1) eq_(m.offset, 0x302) eq_(m.count, 4) @raises(DecodingError) def test_readfrudatareq_decode_short_req(): m = pyipmi.msgs.fru.ReadFruDataReq() decode_message(m, b'\x01\x02\x03') @raises(DecodingError) def test_readfrudatareq_decode_long_req(): m = pyipmi.msgs.fru.ReadFruDataReq() decode_message(m, b'\x01\x02\x03\04\x05') def test_readfrudatareq_encode_valid_req(): m = pyipmi.msgs.fru.ReadFruDataReq() m.fru_id = 1 m.offset = 0x302 m.count = 4 data = encode_message(m) eq_(data, b'\x01\x02\x03\x04') def test_readfrudatarsp_decode_valid_rsp(): m = pyipmi.msgs.fru.ReadFruDataRsp() decode_message(m, b'\x00\x05\x01\x02\x03\x04\x05') eq_(m.completion_code, 0) eq_(m.count, 5) eq_(m.data, array('B', b'\x01\x02\x03\x04\x05')) def test_readfrudatarsp_decode_rsp_with_cc(): m = pyipmi.msgs.fru.ReadFruDataRsp() decode_message(m, b'\xc0') eq_(m.completion_code, 0xc0) @raises(DecodingError) def test_readfrudatarsp_decode_invalid_rsp(): m = pyipmi.msgs.fru.ReadFruDataRsp() decode_message(m, b'\x00\x01\x01\x02') def test_readfrudatarsp_encode_valid_rsp(): m = pyipmi.msgs.fru.ReadFruDataRsp() m.completion_code = 0 m.count = 5 m.data = array('B', b'\x01\x02\x03\x04\x05') data = encode_message(m) eq_(data, b'\x00\x05\x01\x02\x03\x04\x05') @raises(EncodingError) def test_readfrudatarsp_encode_invalid_rsp(): m = pyipmi.msgs.fru.ReadFruDataRsp() m.completion_code = 0 m.count = 1 m.data = array('B', b'\x01\x02') encode_message(m) python-ipmi-0.4.2/tests/msgs/test_event.py0000664000372000037200000000214713574451473021522 0ustar travistravis00000000000000#!/usr/bin/env python from nose.tools import eq_ import pyipmi.msgs.event from pyipmi.msgs import encode_message from pyipmi.msgs import decode_message def test_seteventreceiver_encode_lun0_req(): m = pyipmi.msgs.event.SetEventReceiverReq() m.event_receiver.ipmb_i2c_slave_address = 0x10 m.event_receiver.lun = 0 data = encode_message(m) eq_(data, b'\x20\x00') def test_seteventreceiver_encode_lun3_req(): m = pyipmi.msgs.event.SetEventReceiverReq() m.event_receiver.ipmb_i2c_slave_address = 0x10 m.event_receiver.lun = 3 data = encode_message(m) eq_(data, b'\x20\x03') def test_geteventreceiver_decode_lun0_rsp(): m = pyipmi.msgs.event.GetEventReceiverRsp() decode_message(m, b'\x00\x20\x00') eq_(m.completion_code, 0x00) eq_(m.event_receiver.ipmb_i2c_slave_address, 0x10) eq_(m.event_receiver.lun, 0) def test_geteventreceiver_decode_lun3_rsp(): m = pyipmi.msgs.event.GetEventReceiverRsp() decode_message(m, b'\x00\x20\x03') eq_(m.completion_code, 0x00) eq_(m.event_receiver.ipmb_i2c_slave_address, 0x10) eq_(m.event_receiver.lun, 3) python-ipmi-0.4.2/tests/msgs/__init__.py0000664000372000037200000000000013574451473021063 0ustar travistravis00000000000000python-ipmi-0.4.2/tests/msgs/test_sdr.py0000664000372000037200000000750713574451473021176 0ustar travistravis00000000000000#!/usr/bin/env python from array import array from nose.tools import eq_ import pyipmi.msgs.sdr from pyipmi.msgs import encode_message from pyipmi.msgs import decode_message def test_getsdrrepositoryinfo_encode_req(): m = pyipmi.msgs.sdr.GetSdrRepositoryInfoReq() data = encode_message(m) eq_(data, b'') def test_getsdrrepositoryinfo_decode_rsp(): m = pyipmi.msgs.sdr.GetSdrRepositoryInfoRsp() decode_message(m, b'\x00\x51\x00\x11\x55\xaa\x11\x22\x33\x44\x55\x66\x77\x88\xaa') eq_(m.completion_code, 0x00) eq_(m.sdr_version, 0x51) eq_(m.record_count, 0x1100) eq_(m.free_space, 0xaa55) eq_(m.most_recent_addition, 0x44332211) eq_(m.most_recent_erase, 0x88776655) eq_(m.support.get_allocation_info, 0) eq_(m.support.reserve, 1) eq_(m.support.partial_add, 0) eq_(m.support.delete, 1) eq_(m.support.update_type, 1) eq_(m.support.overflow_flag, 1) def test_getsdrrepositoryallocationinfo_encode_req(): m = pyipmi.msgs.sdr.GetSdrRepositoryAllocationInfoReq() data = encode_message(m) eq_(data, b'') def test_getsdrrepositoryallocationinfo_decode_rsp(): m = pyipmi.msgs.sdr.GetSdrRepositoryAllocationInfoRsp() decode_message(m, b'\x00\x11\x22\x33\x44\x55\x66\x77\x88\xaa') eq_(m.completion_code, 0x00) eq_(m.number_of_units, 0x2211) eq_(m.unit_size, 0x4433) eq_(m.free_units, 0x6655) eq_(m.largest_free_block, 0x8877) eq_(m.maximum_record_size, 0xaa) def test_reservesdrrepository_encode_req(): m = pyipmi.msgs.sdr.ReserveSdrRepositoryReq() data = encode_message(m) eq_(data, b'') def test_reservesdrrepository_decode_rsp(): m = pyipmi.msgs.sdr.ReserveSdrRepositoryRsp() decode_message(m, b'\x00\x11\x22') eq_(m.completion_code, 0x00) eq_(m.reservation_id, 0x2211) def test_getsdr_encode_req(): m = pyipmi.msgs.sdr.GetSdrReq() m.reservation_id = 0x1122 m.record_id = 0x3344 m.offset = 0xaa m.bytes_to_read = 0x55 data = encode_message(m) eq_(data, b'\x22\x11\x44\x33\xaa\x55') def test_getsdr_decode_rsp(): m = pyipmi.msgs.sdr.GetSdrRsp() decode_message(m, b'\x00\x11\x22\x33\x44\x55\x66') eq_(m.completion_code, 0x00) eq_(m.next_record_id, 0x2211) eq_(m.record_data, array('B', [0x33, 0x44, 0x55, 0x66])) def test_addsdr_encode_req(): m = pyipmi.msgs.sdr.AddSdrReq() m.record_data = array('B', [0x55, 0x44]) data = encode_message(m) eq_(data, b'\x55\x44') def test_addsdr_decode_rsp(): m = pyipmi.msgs.sdr.AddSdrRsp() decode_message(m, b'\x00\x11\x22') eq_(m.completion_code, 0x00) eq_(m.record_id, 0x2211) def test_partialaddsdr_encode_req(): m = pyipmi.msgs.sdr.PartialAddSdrReq() m.reservation_id = 0x2211 m.record_id = 0x4433 m.offset = 0xaa m.status.in_progress = 0xaa m.record_data = array('B', [0x55, 0x44]) data = encode_message(m) eq_(data, b'\x11\x22\x33\x44\xaa\x0a\x55\x44') def test_partialaddsdr_decode_rsp(): m = pyipmi.msgs.sdr.PartialAddSdrRsp() decode_message(m, b'\x00\x11\x22') eq_(m.completion_code, 0x00) eq_(m.record_id, 0x2211) def test_deletesdr_encode_req(): m = pyipmi.msgs.sdr.DeleteSdrReq() m.reservation_id = 0x2211 m.record_id = 0x4433 data = encode_message(m) eq_(data, b'\x11\x22\x33\x44') def test_deletesdr_decode_rsp(): m = pyipmi.msgs.sdr.DeleteSdrRsp() decode_message(m, b'\x00\x11\x22') eq_(m.completion_code, 0x00) eq_(m.record_id, 0x2211) def test_clearsdrrepository_encode_req(): m = pyipmi.msgs.sdr.ClearSdrRepositoryReq() m.reservation_id = 0x2211 m.cmd = 1 data = encode_message(m) eq_(data, b'\x11"CLR\x01') def test_clearsdrrepository_decode_rsp(): m = pyipmi.msgs.sdr.ClearSdrRepositoryRsp() decode_message(m, b'\x00\x11') eq_(m.completion_code, 0x00) eq_(m.status.erase_in_progress, 0x1) python-ipmi-0.4.2/tests/test_hpm.py0000664000372000037200000000757013574451473020221 0ustar travistravis00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- import os from nose.tools import eq_, ok_ from pyipmi.hpm import (ComponentProperty, ComponentPropertyDescriptionString, ComponentPropertyGeneral, ComponentPropertyCurrentVersion, ComponentPropertyDeferredVersion, ComponentPropertyRollbackVersion, UpgradeActionRecord, UpgradeActionRecordBackup, UpgradeActionRecordPrepare, UpgradeActionRecordUploadForUpgrade, UpgradeActionRecordUploadForCompare, UpgradeImage, PROPERTY_GENERAL_PROPERTIES, PROPERTY_CURRENT_VERSION, PROPERTY_DESCRIPTION_STRING, PROPERTY_ROLLBACK_VERSION, PROPERTY_DEFERRED_VERSION) class TestComponentProperty(object): def test_general(self): prop = ComponentProperty().from_data(PROPERTY_GENERAL_PROPERTIES, b'\xaa') eq_(type(prop), ComponentPropertyGeneral) prop = ComponentProperty().from_data(PROPERTY_GENERAL_PROPERTIES, (0xaa,)) eq_(type(prop), ComponentPropertyGeneral) def test_currentversion(self): prop = ComponentProperty().from_data(PROPERTY_CURRENT_VERSION, b'\x01\x99') eq_(type(prop), ComponentPropertyCurrentVersion) prop = ComponentProperty().from_data( PROPERTY_CURRENT_VERSION, (0x01, 0x99)) eq_(type(prop), ComponentPropertyCurrentVersion) def test_descriptionstring(self): prop = ComponentProperty().from_data(PROPERTY_DESCRIPTION_STRING, b'\x30\x31\x32') eq_(type(prop), ComponentPropertyDescriptionString) eq_(prop.description, '012') prop = ComponentProperty().from_data( PROPERTY_DESCRIPTION_STRING, (0x33, 0x34, 0x35)) eq_(type(prop), ComponentPropertyDescriptionString) eq_(prop.description, '345') def test_descriptionstring_with_trailinge_zeros(self): prop = ComponentProperty().from_data(PROPERTY_DESCRIPTION_STRING, b'\x36\x37\x38\x00\x00') eq_(type(prop), ComponentPropertyDescriptionString) eq_(prop.description, '678') def test_rollbackversion(self): prop = ComponentProperty().from_data( PROPERTY_ROLLBACK_VERSION, (0x2, 0x88)) eq_(type(prop), ComponentPropertyRollbackVersion) def test_deferredversion(self): prop = ComponentProperty().from_data( PROPERTY_DEFERRED_VERSION, (0x3, 0x77)) eq_(type(prop), ComponentPropertyDeferredVersion) def test_upgradeactionrecord_create_from_data(): record = UpgradeActionRecord.create_from_data(b'\x00\x08\x02') eq_(record.action, 0) eq_(type(record), UpgradeActionRecordBackup) record = UpgradeActionRecord.create_from_data(b'\x01\x08\x02') eq_(record.action, 1) eq_(type(record), UpgradeActionRecordPrepare) record = \ UpgradeActionRecord.create_from_data( b'\x02\x08\x02' b'\x01\x99\xaa\xbb\xcc\xdd' b'\x30\x31\x32\x33\x34\x35\x36\x37' b'\x38\x39\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x30' b'\x04\x00\x00\x00\x11\x22\x33\x44') eq_(record.firmware_version.version_to_string(), '1.99') eq_(record.firmware_description_string, '012345678901234567890') eq_(record.firmware_length, 4) record = UpgradeActionRecord.create_from_data(b'\x03\x08\x02') eq_(record.action, 3) eq_(type(record), UpgradeActionRecordUploadForCompare) def test_upgrade_image(): path = os.path.dirname(os.path.abspath(__file__)) hpm_file = os.path.join(path, 'hpm_bin/firmware.hpm') image = UpgradeImage(hpm_file) ok_(isinstance(image.actions[0], UpgradeActionRecordPrepare)) ok_(isinstance(image.actions[1], UpgradeActionRecordUploadForUpgrade)) python-ipmi-0.4.2/tests/test_ipmi.py0000664000372000037200000001057013574451473020365 0ustar travistravis00000000000000#!/usr/bin/env python #-*- coding: utf-8 -*- from nose.tools import eq_, ok_, raises from mock import MagicMock from pyipmi import interfaces, create_connection, Target, Routing from pyipmi.errors import CompletionCodeError, RetryError from pyipmi.msgs.bmc import GetDeviceIdReq, GetDeviceIdRsp from pyipmi.msgs.sensor import GetSensorReadingReq, GetSensorReadingRsp from pyipmi.msgs.constants import CC_NODE_BUSY def test_target(): target = Target() eq_(target.ipmb_address, None) eq_(target.routing, None) target = Target(0xa0) eq_(target.ipmb_address, 0xa0) eq_(target.routing, None) target = Target(ipmb_address=0xb0) eq_(target.ipmb_address, 0xb0) eq_(target.routing, None) def test_target_routing(): target = Target(routing=[(0x82, 0x20, 0)]) eq_(len(target.routing), 1) eq_(target.routing[0].rq_sa, 0x82) eq_(target.routing[0].rs_sa, 0x20) eq_(target.routing[0].channel, 0) target = Target(routing=[(0x82, 0x20, 0), (0x20, 0x82, 7)]) eq_(len(target.routing), 2) eq_(target.routing[0].rq_sa, 0x82) eq_(target.routing[0].rs_sa, 0x20) eq_(target.routing[0].channel, 0) eq_(target.routing[1].rq_sa, 0x20) eq_(target.routing[1].rs_sa, 0x82) eq_(target.routing[1].channel, 7) def test_routing(): routing = Routing(0x82, 0x20, 7) eq_(routing.rq_sa, 0x82) eq_(routing.rs_sa, 0x20) eq_(routing.channel, 7) def test_target_set_routing(): target = Target() target.set_routing([(0x11, 0x12, 0x13)]) eq_(len(target.routing), 1) eq_(target.routing[0].rq_sa, 0x11) eq_(target.routing[0].rs_sa, 0x12) eq_(target.routing[0].channel, 0x13) target.set_routing([(0x11, 0x12, 0x13), (0x21, 0x22, 0x23)]) eq_(len(target.routing), 2) eq_(target.routing[0].rq_sa, 0x11) eq_(target.routing[0].rs_sa, 0x12) eq_(target.routing[0].channel, 0x13) eq_(target.routing[1].rq_sa, 0x21) eq_(target.routing[1].rs_sa, 0x22) eq_(target.routing[1].channel, 0x23) def test_target_set_routing_from_string(): target = Target() target.set_routing('[(0x11, 0x12, 0x13)]') eq_(len(target.routing), 1) eq_(target.routing[0].rq_sa, 0x11) eq_(target.routing[0].rs_sa, 0x12) eq_(target.routing[0].channel, 0x13) target.set_routing('[(0x11, 0x12, 0x13), (0x21, 0x22, 0x23)]') eq_(len(target.routing), 2) eq_(target.routing[0].rq_sa, 0x11) eq_(target.routing[0].rs_sa, 0x12) eq_(target.routing[0].channel, 0x13) eq_(target.routing[1].rq_sa, 0x21) eq_(target.routing[1].rs_sa, 0x22) eq_(target.routing[1].channel, 0x23) def test_ipmi_send_message_retry(): req = GetDeviceIdReq() rsp = GetDeviceIdRsp() interface = interfaces.create_interface('mock') cc = CompletionCodeError(CC_NODE_BUSY) mock = MagicMock(side_effect=(cc, 0)) mock.return_value = rsp interface.send_and_receive = mock ipmi = create_connection(interface) ipmi.target = None ipmi.send_message(req) eq_(mock.call_count, 2) @raises(RetryError) def test_ipmi_send_message_retry_error(): req = GetDeviceIdReq() rsp = GetDeviceIdRsp() interface = interfaces.create_interface('mock') cc = CompletionCodeError(CC_NODE_BUSY) mock = MagicMock(side_effect=(cc, cc, cc)) mock.return_value = rsp interface.send_and_receive = mock ipmi = create_connection(interface) ipmi.target = None ipmi.send_message(req) def test_ipmi_send_message_with_name(): rsp = GetDeviceIdRsp() rsp.completion_code = 0 mock_send_message = MagicMock() mock_send_message.return_value = rsp interface = interfaces.create_interface('mock') ipmi = create_connection(interface) ipmi.send_message = mock_send_message ipmi.send_message_with_name('GetDeviceId') args, kwargs = mock_send_message.call_args req = args[0] ok_(isinstance(req, GetDeviceIdReq)) def test_ipmi_send_message_with_name_and_kwargs(): rsp = GetSensorReadingRsp() rsp.completion_code = 0 mock_send_message = MagicMock() mock_send_message.return_value = rsp interface = interfaces.create_interface('mock') ipmi = create_connection(interface) ipmi.send_message = mock_send_message ipmi.send_message_with_name('GetSensorReading', sensor_number=5, lun=2) args, kwargs = mock_send_message.call_args req = args[0] ok_(isinstance(req, GetSensorReadingReq)) eq_(req.sensor_number, 5) eq_(req.lun, 2) python-ipmi-0.4.2/tests/test_sensor.py0000664000372000037200000000313613574451473020740 0ustar travistravis00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- from nose.tools import eq_ from mock import MagicMock from pyipmi import interfaces, create_connection from pyipmi.msgs.sensor import SetSensorThresholdsRsp def test_set_sensor_thresholds(): rsp = SetSensorThresholdsRsp() rsp.completion_code = 0 mock_send_recv = MagicMock() mock_send_recv.return_value = rsp interface = interfaces.create_interface('mock') ipmi = create_connection(interface) ipmi.send_message = mock_send_recv ipmi.set_sensor_thresholds(sensor_number=5, lun=1) args, _ = mock_send_recv.call_args req = args[0] eq_(req.lun, 1) eq_(req.sensor_number, 5) ipmi.set_sensor_thresholds(sensor_number=0, unr=10) args, _ = mock_send_recv.call_args req = args[0] eq_(req.set_mask.unr, 1) eq_(req.threshold.unr, 10) eq_(req.set_mask.ucr, 0) eq_(req.threshold.ucr, 0) eq_(req.set_mask.unc, 0) eq_(req.threshold.unc, 0) eq_(req.set_mask.lnc, 0) eq_(req.threshold.lnc, 0) eq_(req.set_mask.lcr, 0) eq_(req.threshold.lcr, 0) eq_(req.set_mask.lnr, 0) eq_(req.threshold.lnr, 0) ipmi.set_sensor_thresholds(sensor_number=5, ucr=11) args, _ = mock_send_recv.call_args req = args[0] eq_(req.lun, 0) eq_(req.set_mask.unr, 0) eq_(req.threshold.unr, 0) eq_(req.set_mask.ucr, 1) eq_(req.threshold.ucr, 11) eq_(req.set_mask.unc, 0) eq_(req.threshold.unc, 0) eq_(req.set_mask.lnc, 0) eq_(req.threshold.lnc, 0) eq_(req.set_mask.lcr, 0) eq_(req.threshold.lcr, 0) eq_(req.set_mask.lnr, 0) eq_(req.threshold.lnr, 0) python-ipmi-0.4.2/tests/test_errors.py0000664000372000037200000000163513574451473020745 0ustar travistravis00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- from nose.tools import raises from pyipmi.errors import (DecodingError, EncodingError, CompletionCodeError, NotSupportedError, DescriptionError, RetryError, DataNotFound, HpmError) @raises(DecodingError) def test_DecodingError(): raise DecodingError() @raises(EncodingError) def test_EncodingError(): raise EncodingError() @raises(CompletionCodeError) def test_CompletionCodeError(): raise CompletionCodeError(cc=0x09) @raises(NotSupportedError) def test_NotSupportedError(): raise NotSupportedError() @raises(DescriptionError) def test_DescriptionError(): raise DescriptionError() @raises(RetryError) def test_RetryError(): raise RetryError() @raises(DataNotFound) def test_DataNotFound(): raise DataNotFound() @raises(HpmError) def test_HpmError_no_msg(): raise HpmError() python-ipmi-0.4.2/tests/test_fields.py0000664000372000037200000000123113574451473020667 0ustar travistravis00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- from nose.tools import eq_, raises from pyipmi.fields import VersionField from pyipmi.errors import DecodingError def test_versionfield_object(): version = VersionField([1, 0x99]) eq_(version.major, 1) eq_(version.minor, 99) version = VersionField('\x00\x99') eq_(version.major, 0) eq_(version.minor, 99) def test_versionfield_invalid(): version = VersionField('\x00\xff') eq_(version.major, 0) eq_(version.minor, 255) @raises(DecodingError) def test_versionfield_decoding_error(): version = VersionField('\x00\x9a') eq_(version.major, 0) eq_(version.minor, 99) python-ipmi-0.4.2/tests/test_sel.py0000664000372000037200000001151013574451473020205 0ustar travistravis00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- from nose.tools import eq_, ok_ from pyipmi.msgs.registry import create_response_by_name from pyipmi.sel import SelEntry, SelInfo class TestSelInfo(object): rsp = create_response_by_name('GetSelInfo') rsp.version = 1 rsp.entries = 1023 rsp.free_bytes = 512 info = SelInfo(rsp) eq_(info.version, 1) eq_(info.entries, 1023) eq_(info.free_bytes, 512) rsp.operation_support.get_sel_allocation_info = 1 rsp.operation_support.reserve_sel = 0 rsp.operation_support.partial_add_sel_entry = 0 rsp.operation_support.delete_sel = 0 rsp.operation_support.overflow_flag = 0 info = SelInfo(rsp) ok_('get_sel_allocation_info' in info.operation_support) ok_('reserve_sel' not in info.operation_support) ok_('partial_add_sel_entry' not in info.operation_support) ok_('delete_sel' not in info.operation_support) ok_('overflow_flag' not in info.operation_support) rsp.operation_support.get_sel_allocation_info = 0 rsp.operation_support.reserve_sel = 1 rsp.operation_support.partial_add_sel_entry = 0 rsp.operation_support.delete_sel = 0 rsp.operation_support.overflow_flag = 0 info = SelInfo(rsp) ok_('get_sel_allocation_info' not in info.operation_support) ok_('reserve_sel' in info.operation_support) ok_('partial_add_sel_entry' not in info.operation_support) ok_('delete_sel' not in info.operation_support) ok_('overflow_flag' not in info.operation_support) rsp.operation_support.get_sel_allocation_info = 0 rsp.operation_support.reserve_sel = 0 rsp.operation_support.partial_add_sel_entry = 1 rsp.operation_support.delete_sel = 0 rsp.operation_support.overflow_flag = 0 info = SelInfo(rsp) ok_('get_sel_allocation_info' not in info.operation_support) ok_('reserve_sel' not in info.operation_support) ok_('partial_add_sel_entry' in info.operation_support) ok_('delete_sel' not in info.operation_support) ok_('overflow_flag' not in info.operation_support) rsp.operation_support.get_sel_allocation_info = 0 rsp.operation_support.reserve_sel = 0 rsp.operation_support.partial_add_sel_entry = 0 rsp.operation_support.delete_sel = 1 rsp.operation_support.overflow_flag = 0 info = SelInfo(rsp) ok_('get_sel_allocation_info' not in info.operation_support) ok_('reserve_sel' not in info.operation_support) ok_('partial_add_sel_entry' not in info.operation_support) ok_('delete_sel' in info.operation_support) ok_('overflow_flag' not in info.operation_support) rsp.operation_support.get_sel_allocation_info = 0 rsp.operation_support.reserve_sel = 0 rsp.operation_support.partial_add_sel_entry = 0 rsp.operation_support.delete_sel = 0 rsp.operation_support.overflow_flag = 1 info = SelInfo(rsp) ok_('get_sel_allocation_info' not in info.operation_support) ok_('reserve_sel' not in info.operation_support) ok_('partial_add_sel_entry' not in info.operation_support) ok_('delete_sel' not in info.operation_support) ok_('overflow_flag' in info.operation_support) class TestSelEnty(object): def test_from_data(self): data = [0xff, 0x03, 0x02, 0xf7, 0x61, 0xef, 0x52, 0x7e, 0x00, 0x04, 0xf2, 0x09, 0x7f, 0x00, 0xff, 0xff] entry = SelEntry(data) eq_(entry.type, 2) eq_(entry.sensor_type, 0xf2) def test_from_data_event_direction(self): data = [0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00] entry = SelEntry(data) eq_(entry.event_direction, 0) data = [0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00] entry = SelEntry(data) eq_(entry.event_direction, 1) def test_from_data_event_type(self): data = [0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00] entry = SelEntry(data) eq_(entry.event_type, 0x7f) data = [0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00] entry = SelEntry(data) eq_(entry.event_type, 0x00) def test_from_data_event_data(self): data = [0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x11, 0x22, 0x33] entry = SelEntry(data) eq_(entry.event_data[0], 0x11) eq_(entry.event_data[1], 0x22) eq_(entry.event_data[2], 0x33) def test_type_to_string(self): eq_(SelEntry.type_to_string(0), None) eq_(SelEntry.type_to_string(0x02), 'System Event') eq_(SelEntry.type_to_string(0xc0), 'OEM timestamped (0xc0)') eq_(SelEntry.type_to_string(0xe0), 'OEM non-timestamped (0xe0)') python-ipmi-0.4.2/tests/test_fru.py0000664000372000037200000000333113574451473020220 0ustar travistravis00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- import os from nose.tools import eq_ from pyipmi.fru import (FruData, InventoryCommonHeader, get_fru_inventory_from_file) def test_frudata_object(): fru_field = FruData((0, 1, 2, 3)) eq_(fru_field.data[0], 0) eq_(fru_field.data[1], 1) eq_(fru_field.data[2], 2) eq_(fru_field.data[3], 3) fru_field = FruData('\x00\x01\x02\x03') eq_(fru_field.data[0], 0) eq_(fru_field.data[1], 1) eq_(fru_field.data[2], 2) eq_(fru_field.data[3], 3) def test_commonheader_object(): InventoryCommonHeader((0, 1, 2, 3, 4, 5, 6, 235)) def test_fru_inventory_from_file(): path = os.path.dirname(os.path.abspath(__file__)) fru_file = os.path.join(path, 'fru_bin/kontron_am4010.bin') fru = get_fru_inventory_from_file(fru_file) eq_(fru.chassis_info_area, None) def test_board_area(): path = os.path.dirname(os.path.abspath(__file__)) fru_file = os.path.join(path, 'fru_bin/kontron_am4010.bin') fru = get_fru_inventory_from_file(fru_file) board_area = fru.board_info_area eq_(board_area.manufacturer.value, 'Kontron') eq_(board_area.product_name.value, 'AM4010') eq_(board_area.serial_number.value, '0023721003') eq_(board_area.part_number.value, '35943') def test_product_area(): path = os.path.dirname(os.path.abspath(__file__)) fru_file = os.path.join(path, 'fru_bin/kontron_am4010.bin') fru = get_fru_inventory_from_file(fru_file) product_area = fru.product_info_area eq_(product_area.manufacturer.value, 'Kontron') eq_(product_area.name.value, 'AM4010') eq_(product_area.serial_number.value, '0000000000000000000000000') eq_(product_area.part_number.value, '0012') python-ipmi-0.4.2/tests/interfaces/0000775000372000037200000000000013574451533020133 5ustar travistravis00000000000000python-ipmi-0.4.2/tests/interfaces/test_ipmb.py0000664000372000037200000000556313574451473022507 0ustar travistravis00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- from array import array from nose.tools import eq_, ok_ from pyipmi import Target from pyipmi.interfaces.ipmb import (checksum, IpmbHeaderReq, IpmbHeaderRsp, encode_send_message, encode_bridged_message, encode_ipmb_msg, decode_bridged_message, rx_filter) def test_checksum(): eq_(checksum([1, 2, 3, 4, 5]), 256-15) def test_header_encode(): header = IpmbHeaderReq() header.rs_lun = 0 header.rs_sa = 0x72 header.rq_seq = 2 header.rq_lun = 1 header.rq_sa = 0x20 header.netfn = 6 header.cmd_id = 1 data = header.encode() eq_(data, b'\x72\x18\x76\x20\x09\x01') def test_header_rsp_decode(): header = IpmbHeaderRsp() data = header.decode(b'\x72\x19\x76\x20\x08\x01') eq_(header.rq_sa, 0x72) eq_(header.rq_lun, 1) eq_(header.rs_sa, 0x20) eq_(header.rs_lun, 0) eq_(header.netfn, 6) def test_encode_ipmb_msg(): header = IpmbHeaderReq() header.rs_lun = 0 header.rs_sa = 0x72 header.rq_seq = 2 header.rq_lun = 0 header.rq_sa = 0x20 header.netfn = 6 header.cmd_id = 1 eq_(encode_ipmb_msg(header, b'\xaa\xbb\xcc'), b'\x72\x18\x76\x20\x08\x01\xaa\xbb\xcc\xa6') def test_encode_send_message(): data = encode_send_message(b'\xaa\xbb', 0x12, 0x20, 7, 0x22) eq_(data, b'\x20\x18\xc8\x12\x88\x34\x47\xaa\xbb\x86') def test_encode_bridged_message(): payload = array('B', b'\xaa\xbb') t = Target(0) t.set_routing([(0x81, 0x20, 7), (0x20, 0x72, None)]) header = IpmbHeaderReq() header.netfn = 6 header.rs_lun = 0 header.rq_seq = 0x11 header.rq_lun = 0 header.cmd_id = 0xaa data = encode_bridged_message(t.routing, header, payload, seq=0x22) eq_(data, b'\x20\x18\xc8\x81\x88\x34\x47\x72\x18\x76\x20\x44\xaa\xaa\xbb\x8d\x7c') def test_decode_bridged_message(): # 81 1c 63 20 14 34 00 20 1c c4 82 14 34 00 20 14 cc 74 14 22 00 ed ff 6a 36 data = b'\x81\x1c\x63\x20\x14\x34\x00\x20\x1c\xc4\x82\x14\x34\x00\x20\x14\xcc\x74\x14\x22\x00\xed\xff\x6a\x36' data = decode_bridged_message(data) eq_(len(data), 9) eq_(data, b'\x20\x14\xcc\x74\x14\x22\x00\xed\xff') def test_rx_filter(): header_req = IpmbHeaderReq() header_req.rs_lun = 1 header_req.rs_sa = 0x72 header_req.rq_seq = 2 header_req.rq_lun = 0 header_req.rq_sa = 0x20 header_req.netfn = 6 header_req.cmd_id = 1 # requester and responder fields are twisted ... (sa and lun) header_rsp = IpmbHeaderReq() header_rsp.rs_lun = 0 header_rsp.rs_sa = 0x20 header_rsp.rq_seq = 2 header_rsp.rq_lun = 1 header_rsp.rq_sa = 0x72 header_rsp.netfn = 6 + 1 header_rsp.cmd_id = 1 rx_data = encode_ipmb_msg(header_rsp, b'\xaa\xbb\xcc') ok_(rx_filter(header_req, rx_data)) python-ipmi-0.4.2/tests/interfaces/test_aardvark.py0000664000372000037200000000345013574451473023344 0ustar travistravis00000000000000#!/usr/bin/env python #-*- coding: utf-8 -*- from mock import MagicMock, patch from nose.tools import eq_, ok_ from pyipmi.interfaces.ipmb import IpmbHeader class MockPyaardvark: def enable_i2c_slave(self, d): pass class TestAardvark: pass # @classmethod # def setup_class(self): # """Mock pyaardvark import # http://erikzaadi.com/2012/07/03/mocking-python-imports/ # """ # self.pyaardvark_mock = MagicMock() # self.pyaardvark_mock.open.return_value = MockPyaardvark() # # modules = { # 'pyaardvark': self.pyaardvark_mock, # 'pyaardvark.open': self.pyaardvark_mock.open, # } # # self.module_patcher = patch.dict('sys.modules', modules) # self.module_patcher.start() # ok_('pyaardvark' in sys.modules.keys()) # ok_('pyaardvark.open' in sys.modules.keys()) # # from pyipmi.interfaces.aardvark import Aardvark # self.my_aardvark = Aardvark() # # @classmethod # def teardown_class(self): # """Let's clean up""" # self.module_patcher.stop() # # def test_rx_filter(self): # header = IpmbHeader() # header.rs_lun = 0 # header.rs_sa = 0x72 # header.rq_seq = 2 # header.rq_lun = 0 # header.rq_sa = 0x20 # header.netfn = 6 # header.cmd_id = 1 # # rx_data = (0x1c, 0xc4, 0x72, 0x08, 0x1, 0x85) # # ok_(self.my_aardvark._rx_filter(0x20, header, rx_data)) # # def test_inc_sequence_number(self): # self.my_aardvark.next_sequence_number = 0 # self.my_aardvark._inc_sequence_number() # eq_(self.my_aardvark.next_sequence_number, 1) # # self.my_aardvark.next_sequence_number = 63 # self.my_aardvark._inc_sequence_number() # eq_(self.my_aardvark.next_sequence_number, 0) python-ipmi-0.4.2/tests/interfaces/test_ipmitool.py0000664000372000037200000001302513574451473023404 0ustar travistravis00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- from mock import MagicMock from nose.tools import eq_, raises from pyipmi.errors import IpmiTimeoutError from pyipmi.interfaces import Ipmitool from pyipmi import Session, Target class TestIpmitool: def setup(self): self._interface = Ipmitool(interface_type='lan') self.session = Session() self.session.interface = self._interface self.session.set_session_type_rmcp('10.0.1.1') self.session.set_auth_type_user('admin', 'secret') self._interface.establish_session(self.session) def test_build_ipmitool_target_ipmb_address(self): target = Target(0xb0) cmd = self._interface._build_ipmitool_target(target) eq_(cmd, ' -t 0xb0') def test_build_ipmitool_target_routing_2(self): target = Target(routing=[(0x81, 0x20, 7), (0x20, 0x82, 0)]) cmd = self._interface._build_ipmitool_target(target) eq_(cmd, ' -t 0x82 -b 7') def test_build_ipmitool_target_routing_3(self): target = Target(routing=[(0x81, 0x20, 0), (0x20, 0x82, 7), (0x20, 0x72, None)]) cmd = self._interface._build_ipmitool_target(target) eq_(cmd, ' -T 0x82 -B 0 -t 0x72 -b 7') def test_send_and_receive(self): pass def test_rmcp_ping(self): mock = MagicMock() mock.return_value = (b'', 0) self._interface._run_ipmitool = mock self._interface.rmcp_ping() mock.assert_called_once_with('ipmitool -I lan -H 10.0.1.1 -p 623 ' '-U "admin" -P "secret" ' 'session info all') def test_send_and_receive_raw_valid(self): mock = MagicMock() mock.return_value = (b'', 0) self._interface._run_ipmitool = mock target = Target(0x20) self._interface.send_and_receive_raw(target, 0, 0x6, b'\x01') mock.assert_called_once_with('ipmitool -I lan -H 10.0.1.1 -p 623 ' '-U "admin" -P "secret" -t 0x20 -l 0 ' 'raw 0x06 0x01 2>&1') def test_send_and_receive_raw_lanplus(self): interface = Ipmitool(interface_type='lanplus') interface.establish_session(self.session) mock = MagicMock() mock.return_value = (b'', 0) interface._run_ipmitool = mock target = Target(0x20) interface.send_and_receive_raw(target, 0, 0x6, b'\x01') mock.assert_called_once_with('ipmitool -I lanplus -H 10.0.1.1 -p 623 ' '-U "admin" -P "secret" -t 0x20 -l 0 ' 'raw 0x06 0x01 2>&1') def test_send_and_receive_raw_no_auth(self): mock = MagicMock() mock.return_value = (b'', 0) self._interface._run_ipmitool = mock self._interface._session.auth_type = Session.AUTH_TYPE_NONE target = Target(0x20) self._interface.send_and_receive_raw(target, 0, 0x6, b'\x01') mock.assert_called_once_with('ipmitool -I lan -H 10.0.1.1 -p 623 ' '-P "" -t 0x20 -l 0 raw 0x06 0x01 2>&1') def test_send_and_receive_raw_return_value(self): mock = MagicMock() mock.return_value = (b' 10 80 01 02 51 bd 98 3a 00 a8 ' b'06 00 03 00 00\n', 0) self._interface._run_ipmitool = mock target = Target(0x20) data = self._interface.send_and_receive_raw(target, 0, 0x6, b'\x01') eq_(data, b'\x00\x10\x80\x01\x02\x51\xbd\x98\x3a\x00\xa8\x06' b'\x00\x03\x00\x00') def test_send_and_receive_raw_completion_code_timeout(self): mock = MagicMock() mock.return_value = (b'Unable to send RAW command (channel=0x0 ' b'netfn=0x6 lun=0x0 cmd=0x1 rsp=0xc3): ' b'Ignore Me\n', 1) target = Target(0x20) self._interface._run_ipmitool = mock data = self._interface.send_and_receive_raw(target, 0, 0x6, b'\x01') eq_(data, b'\xc3') def test_send_and_receive_raw_completion_code_not_ok(self): mock = MagicMock() mock.return_value = (b'Unable to send RAW command (channel=0x0 ' b'netfn=0x6 lun=0x0 cmd=0x1 rsp=0xcc): ' b'Ignore Me\n', 1) target = Target(0x20) self._interface._run_ipmitool = mock data = self._interface.send_and_receive_raw(target, 0, 0x6, b'\x01') eq_(data, b'\xcc') @raises(IpmiTimeoutError) def test_send_and_receive_raw_timeout_without_response(self): mock = MagicMock() mock.return_value = (b'Unable to send RAW command ' b'(channel=0x0 netfn=0x6 lun=0x0 cmd=0x1)\n', 1) target = Target(0x20) self._interface._run_ipmitool = mock self._interface.send_and_receive_raw(target, 0, 0x6, b'\x01') def test_send_and_receive_raw_serial(self): interface = Ipmitool(interface_type='serial-terminal') self.session.set_session_type_serial('/dev/tty2', 115200) interface.establish_session(self.session) mock = MagicMock() mock.return_value = (b'', 0) interface._run_ipmitool = mock target = Target(0x20) interface.send_and_receive_raw(target, 0, 0x6, b'\x01') mock.assert_called_once_with('ipmitool -I serial-terminal ' '-D /dev/tty2:115200 -t 0x20 -l 0 ' 'raw 0x06 0x01') python-ipmi-0.4.2/tests/interfaces/test_rmcp.py0000664000372000037200000001077313574451473022520 0ustar travistravis00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- import array from mock import MagicMock from nose.tools import eq_ from pyipmi import Target from pyipmi.session import Session from pyipmi.interfaces.rmcp import (AsfMsg, AsfPing, AsfPong, IpmiMsg, Rmcp, RmcpMsg) class TestRmcpMsg: def test_rmcpmsg_pack(self): m = RmcpMsg(0x7) pdu = m.pack(None, 0xff) eq_(pdu, b'\x06\x00\xff\x07') m = RmcpMsg(0x7) pdu = m.pack(b'\x11\x22\x33\x44', 0xff) eq_(pdu, b'\x06\x00\xff\x07\x11\x22\x33\x44') def test_rmcpmsg_unpack(self): pdu = b'\x06\x00\xee\x07\x44\x33\x22\x11' m = RmcpMsg() sdu = m.unpack(pdu) eq_(m.version, 6) eq_(m.seq_number, 0xee) eq_(m.class_of_msg, 0x7) eq_(sdu, b'\x44\x33\x22\x11') class TestAsfMsg: def test_pack(self): m = AsfMsg() pdu = m.pack() eq_(pdu, b'\x00\x00\x11\xbe\x00\x00\x00\x00') def test_unpack(self): pdu = b'\x00\x00\x11\xbe\x00\x00\x00\x00' msg = AsfMsg() msg.unpack(pdu) def test_tostr(self): m = AsfMsg() m.data = b'\xaa\xbb\xcc' eq_(str(m), 'aa bb cc') class TestAsfPing(): def test_pack(self): m = AsfPing() pdu = m.pack() eq_(pdu, b'\x00\x00\x11\xbe\x80\x00\x00\x00') class TestAsfPong(): def test_unpack(self): pdu = b'\x00\x00\x11\xbe\x40\x00\x00\x10\x00\x00\x11\xbe\x00\x00\x00\x00\x81\x00\x00\x00\x00\x00\x00\x00' m = AsfPong() m.unpack(pdu) class TestIpmiMsg: def test_ipmimsg_pack(self): m = IpmiMsg() pdu = m.pack(None) eq_(pdu, b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') def test_ipmimsg_pack_password(self): s = Session() s.set_auth_type_user('admin', 'admin') m = IpmiMsg(session=s) psw = m._padd_password() eq_(psw, b'admin\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') s = Session() s.set_auth_type_user(b'admin', b'admin') m = IpmiMsg(session=s) psw = m._padd_password() eq_(psw, b'admin\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') def test_ipmimsg_pack_with_data(self): data = array.array('B', (1, 2, 3, 4)).tostring() m = IpmiMsg() pdu = m.pack(data) eq_(pdu, b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x01\x02\x03\x04') def test_ipmimsg_pack_with_session(self): s = Session() s.set_auth_type_user('admin', 'admin') s.sequence_number = 0x14131211 s.sid = 0x18171615 m = IpmiMsg(session=s) pdu = m.pack(None) eq_(pdu, b'\x04\x11\x12\x13\x14\x15\x16\x17\x18admin\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') def test_ipmimsg_pack_auth_md5(self): s = Session() s.set_auth_type_user('admin', 'admin') s.sid = 0x02f99b85 m = IpmiMsg(session=s) sdu = b'\x20\x18\xc8\x81\x0c\x3a\x02\x04\xe1\x2c\xb4\xd3\x17\xdc\x40\xdf\xe9\x78\x1e\x6d\x8e\x10\xad\xeb\x2c\xe8\x5c\xa0\x5b' auth = m._pack_auth_code_md5(sdu) eq_(auth, b'\x40\x46\xb1\x51\x4c\x89\x7f\x73\xc2\xfb\xa7\x4d\xf8\x03\x73\x8c') def test_ipmimsg_unpack(self): pdu = b'\x00\x11\x22\x33\x44\x55\x66\x77\x88\x00' m = IpmiMsg() m.unpack(pdu) eq_(m.auth_type, 0) eq_(m.sequence_number, 0x11223344) eq_(m.session_id, 0x55667788) def test_ipmimsg_unpack_auth(self): pdu = b'\x01\x11\x22\x33\x44\x55\x66\x77\x88\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x00' m = IpmiMsg() m.unpack(pdu) eq_(m.auth_type, 1) eq_(m.sequence_number, 0x11223344) eq_(m.session_id, 0x55667788) eq_(m.auth_code, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]) class TestRmcp: # def test_send_and_receive_raw(self): # mock_send = MagicMock() # mock_recv = MagicMock() # mock_recv.return_value = (b'\x06\x00\xee\x07\x00\x00\x00\x00\x00\x00' # b'\x00\x00\x00\x06' # b'\x01\x02\x03\x04\x05\x06', 0) # # target = Target() # target.ipmb_address = 0x20 # rmcp = Rmcp() # rmcp.host = '10.10.10.10' # rmcp.port = 637 # # rmcp._sock.sendto = mock_send # rmcp._sock.recvfrom = mock_recv # # rmcp.send_and_receive_raw(target, 0, 0, b'\x00') # rmcp._send_ipmi_msg.assert_called_with(1) def test_send_and_receive(self): pass python-ipmi-0.4.2/tests/interfaces/__init__.py0000664000372000037200000000000013574451473022235 0ustar travistravis00000000000000python-ipmi-0.4.2/tests/__init__.py0000664000372000037200000000000013574451473020112 0ustar travistravis00000000000000python-ipmi-0.4.2/tests/test_utils.py0000664000372000037200000000532413574451473020570 0ustar travistravis00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- from array import array from nose.tools import eq_, raises from pyipmi.utils import ByteBuffer, chunks from pyipmi.errors import DecodingError def test_bytebuffer_init_from_list(): buf = ByteBuffer([0xf8]) eq_(buf.array, array('B', [0xf8])) def test_bytebuffer_init_from_tuple(): buf = ByteBuffer((0xf8,)) eq_(buf.array, array('B', [0xf8])) def test_bytebuffer_initi_fromstring(): buf = ByteBuffer(b'\xf8') eq_(buf.array, array('B', [0xf8])) def test_bytebuffer_push_unsigned_int(): buf = ByteBuffer((1, 0)) buf.push_unsigned_int(255, 1) eq_(buf[0], 1) eq_(buf[1], 0) eq_(buf[2], 255) buf.push_unsigned_int(255, 2) eq_(buf[3], 255) eq_(buf[4], 0) buf.push_unsigned_int(256, 2) eq_(buf[5], 0) eq_(buf[6], 1) def test_bytebuffer_pop_unsigned_int(): buf = ByteBuffer((1, 0, 0, 0)) eq_(buf.pop_unsigned_int(1), 1) buf = ByteBuffer((0, 1, 0, 0)) eq_(buf.pop_unsigned_int(2), 0x100) buf = ByteBuffer((0, 0, 1, 0)) eq_(buf.pop_unsigned_int(3), 0x10000) buf = ByteBuffer((0, 0, 0, 1)) eq_(buf.pop_unsigned_int(4), 0x1000000) @raises(DecodingError) def test_bytebuffer_pop_unsigned_int_error(): buf = ByteBuffer((0, 0)) buf.pop_unsigned_int(3) def test_bytebuffer_push_string(): buf = ByteBuffer() buf.push_string(b'0123') eq_(buf[0], 0x30) eq_(buf[1], 0x31) eq_(buf[2], 0x32) eq_(buf[3], 0x33) eq_(buf.tostring(), b'0123') buf = ByteBuffer() buf.push_string(b'\x00\xb4') eq_(buf.tostring(), b'\x00\xb4') def test_bytebuffer_pop_string(): buf = ByteBuffer(b'\x30\x31\x32\x33') eq_(buf.pop_string(2), b'01') eq_(buf.tostring(), b'23') def test_bytebuffer_tostring(): buf = ByteBuffer(b'\x30\x31\x32\x33') eq_(buf.tostring(), b'0123') def test_bytebuffer_pop_slice(): buf = ByteBuffer(b'\x30\x31\x32\x33') cut = buf.pop_slice(1) eq_(buf.tostring(), b'123') eq_(cut.tostring(), b'0') buf = ByteBuffer(b'\x30\x31\x32\x33') cut = buf.pop_slice(2) eq_(buf.tostring(), b'23') eq_(cut.tostring(), b'01') buf = ByteBuffer(b'\x30\x31\x32\x33') cut = buf.pop_slice(3) eq_(buf.tostring(), b'3') eq_(cut.tostring(), b'012') buf = ByteBuffer(b'\x30\x31\x32\x33') cut = buf.pop_slice(4) eq_(buf.tostring(), b'') eq_(cut.tostring(), b'0123') @raises(DecodingError) def test_bytebuffer_pop_slice_error(): buf = ByteBuffer(b'\x30\x31\x32\x33') buf.pop_slice(5) def test_chunks(): data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] result = list() for chunk in chunks(data, 2): result.extend(chunk) eq_(len(chunk), 2) eq_(result, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) python-ipmi-0.4.2/tests/test_sdr.py0000664000372000037200000001657113574451473020226 0ustar travistravis00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- from nose.tools import eq_, ok_, raises from pyipmi.errors import DecodingError from pyipmi.sdr import (SdrCommon, SdrFullSensorRecord, SdrCompactSensorRecord, SdrEventOnlySensorRecord, SdrFruDeviceLocator, SdrManagementControllerDeviceLocator) class TestSdrFullSensorRecord(): def test_convert_complement(self): eq_(SdrFullSensorRecord()._convert_complement(0x8, 4), -8) eq_(SdrFullSensorRecord()._convert_complement(0x80, 8), -128) eq_(SdrFullSensorRecord()._convert_complement(0x8000, 16), -32768) def test_decode_capabilities(self): record = SdrFullSensorRecord() record._decode_capabilities(0) ok_('ignore_sensor' not in record.capabilities) ok_('auto_rearm' not in record.capabilities) ok_('hysteresis_not_supported' in record.capabilities) ok_('threshold_not_supported' in record.capabilities) record._decode_capabilities(0x80) ok_('ignore_sensor' in record.capabilities) ok_('auto_rearm' not in record.capabilities) ok_('hysteresis_not_supported' in record.capabilities) ok_('threshold_not_supported' in record.capabilities) record._decode_capabilities(0x40) ok_('ignore_sensor' not in record.capabilities) ok_('auto_rearm' in record.capabilities) ok_('hysteresis_not_supported' in record.capabilities) ok_('threshold_not_supported' in record.capabilities) record._decode_capabilities(0x30) ok_('ignore_sensor' not in record.capabilities) ok_('auto_rearm' not in record.capabilities) ok_('hysteresis_fixed' in record.capabilities) ok_('threshold_not_supported' in record.capabilities) record._decode_capabilities(0x0c) ok_('ignore_sensor' not in record.capabilities) ok_('auto_rearm' not in record.capabilities) ok_('hysteresis_not_supported' in record.capabilities) ok_('threshold_fixed' in record.capabilities) @raises(DecodingError) def test_invalid_length(self): data = (0, 0, 0, 0, 0) SdrFullSensorRecord(data) @raises(DecodingError) def test_linearization_key_error(self): sdr = SdrFullSensorRecord(None) sdr.linearization = 12 sdr.l(1) def test_linearization(self): sdr = SdrFullSensorRecord(None) # linear sdr.linearization = 0 eq_(sdr.l(1), 1) eq_(sdr.l(10), 10) # ln sdr.linearization = 1 eq_(sdr.l(1), 0) # log sdr.linearization = 2 eq_(sdr.l(10), 1) eq_(sdr.l(100), 2) # log sdr.linearization = 3 eq_(sdr.l(8), 3) eq_(sdr.l(16), 4) # e sdr.linearization = 4 eq_(sdr.l(1), 2.718281828459045) # exp10 sdr.linearization = 5 eq_(sdr.l(1), 10) eq_(sdr.l(2), 100) # exp2 sdr.linearization = 6 eq_(sdr.l(3), 8) eq_(sdr.l(4), 16) # 1/x sdr.linearization = 7 eq_(sdr.l(2), 0.5) eq_(sdr.l(4), 0.25) # sqr sdr.linearization = 8 eq_(sdr.l(2), 4) # cube sdr.linearization = 9 eq_(sdr.l(2), 8) eq_(sdr.l(3), 27) # sqrt sdr.linearization = 10 eq_(sdr.l(16), 4) # cubert sdr.linearization = 11 eq_(sdr.l(8), 2) eq_(sdr.l(27), 3) def test_convert_sensor_raw_to_value(self): sdr = SdrFullSensorRecord() eq_(sdr.convert_sensor_raw_to_value(None), None) sdr.analog_data_format = sdr.DATA_FMT_UNSIGNED sdr.m = 1 sdr.b = 0 sdr.k1 = 0 sdr.k2 = 0 sdr.linearization = 0 eq_(sdr.convert_sensor_raw_to_value(1), 1) eq_(sdr.convert_sensor_raw_to_value(255), 255) sdr.analog_data_format = sdr.DATA_FMT_UNSIGNED sdr.m = 10 sdr.b = 0 sdr.k1 = 0 sdr.k2 = 0 sdr.linearization = 0 eq_(sdr.convert_sensor_raw_to_value(1), 10) eq_(sdr.convert_sensor_raw_to_value(255), 2550) sdr.analog_data_format = sdr.DATA_FMT_1S_COMPLEMENT sdr.m = 1 sdr.b = 0 sdr.k1 = 0 sdr.k2 = 0 sdr.linearization = 0 eq_(sdr.convert_sensor_raw_to_value(1), 1) eq_(sdr.convert_sensor_raw_to_value(128), -127) eq_(sdr.convert_sensor_raw_to_value(255), 0) sdr.analog_data_format = sdr.DATA_FMT_2S_COMPLEMENT sdr.m = 1 sdr.b = 0 sdr.k1 = 0 sdr.k2 = 0 sdr.linearization = 0 eq_(sdr.convert_sensor_raw_to_value(1), 1) eq_(sdr.convert_sensor_raw_to_value(128), -128) eq_(sdr.convert_sensor_raw_to_value(255), -1) def test_decocde(self): data = [0x17, 0x00, 0x51, 0x01, 0x35, 0x17, 0x00, 0x51, 0x01, 0x35, 0x17, 0x00, 0x51, 0x01, 0x35, 0x32, 0x85, 0x32, 0x1b, 0x1b, 0x00, 0x04, 0x00, 0x00, 0x3b, 0x01, 0x00, 0x01, 0x00, 0xd0, 0x07, 0xcc, 0xf4, 0xa6, 0xff, 0x00, 0x00, 0xfe, 0xf5, 0x00, 0x8e, 0xa5, 0x04, 0x04, 0x00, 0x00, 0x00, 0xca, 0x41, 0x32, 0x3a, 0x56, 0x63, 0x63, 0x20, 0x31, 0x32, 0x56] sdr = SdrFullSensorRecord(data) eq_(sdr.device_id_string, b'A2:Vcc 12V') class TestSdrCommon(): @raises(DecodingError) def test_invalid_data_length(self): data = (0x00, 0x01, 0x02, 0x03) SdrCommon(data) def test_object(self): data = (0x00, 0x01, 0x02, 0x03, 0x04) sdr = SdrCommon(data) eq_(sdr.id, 0x0100) eq_(sdr.version, 0x02) eq_(sdr.type, 0x03) eq_(sdr.length, 0x04) class TestSdrCompactSensorRecord(): @raises(DecodingError) def test_invalid_length(self): data = (0, 0, 0, 0, 0) SdrCompactSensorRecord(data) def test_decode(self): data = [0xd3, 0x00, 0x51, 0x02, 0x28, 0x82, 0x00, 0xd3, 0xc1, 0x64, 0x03, 0x40, 0x21, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc0, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcd, 0x41, 0x34, 0x3a, 0x50, 0x72, 0x65, 0x73, 0x20, 0x53, 0x46, 0x50, 0x2d, 0x31] SdrCompactSensorRecord(data) @raises(DecodingError) def test_sdreventonlysensorrecord(): data = (0, 0, 0, 0, 0) SdrEventOnlySensorRecord(data) class TestSdrFruDeviceLocatorRecord(): @raises(DecodingError) def test_invalid_length(self): data = (0, 0, 0, 0, 0) SdrFruDeviceLocator(data) def test_decode(self): data = [0x02, 0x00, 0x51, 0x11, 0x17, 0x82, 0x03, 0x80, 0x00, 0x00, 0x10, 0x02, 0xc2, 0x61, 0x00, 0xcc, 0x4b, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6e, 0x20, 0x4d, 0x43, 0x4d, 0x43] SdrFruDeviceLocator(data) class TestSdrManagementControllerDeviceRecord(): @raises(DecodingError) def test_invalid_length(self): data = (0, 0, 0, 0, 0) SdrManagementControllerDeviceLocator(data) def test_decode(self): data = [0x00, 0x01, 0x51, 0x12, 0x1b, 0x00, 0x01, 0x51, 0x12, 0x1b, 0x00, 0x01, 0x51, 0x12, 0x1b, 0xd0, 0x41, 0x32, 0x3a, 0x41, 0x4d, 0x34, 0x32, 0x32, 0x30, 0x20] sdr = SdrManagementControllerDeviceLocator(data) eq_(sdr.device_id_string, b'A2:AM4220 ')