纯pythonbastedipmi客户端由Hyve Design Solutions开发。

hyve-pyipmi的Python项目详细描述


Hyve Pyimpi公司

由Hyve Design Solutions开发的基于Python的IPMI客户端。在

这个包的最初目的是提供一个纯基于python的IPMI客户端库,用于为IPMI服务开发python测试脚本。它提供了两类:一类是用于IPMI raw命令的,另一类是用于PyIPMI命令的,这类命令类似于著名的ipmitool命令,如“ipmitool mc info”或“ipmitool sdr list”。在

通过这个纯Python库,为BMC开发人员提供了一些控制台程序。在

包中包含示例以演示如何编写测试脚本。使用这个纯Python库的性能比使用shell脚本+对ipmitool的系统调用的混合方法来开发测试脚本要快得多。在

特点

  • 支持的IPMI通道
    • RMCP
    • RMCP+
    • 从LAN到IPMB的消息桥接
  • 控制台程序
    • pyipmi-一个类似ipmitool的Python程序
    • pyipmr—Python程序支持“ipmitool raw”,并具有消息桥接功能
    • pyping-RMCP客户端
    • pysh-PyIPMI命令的交互式shell,具有自动完成和上/下键来显示以前的命令
  • 自动测试界面
    • IPMI原始命令支持(见下面的示例1-3)
    • PyIPMI命令支持(见下面的示例4-6)

安装

以下步骤在ubuntudesktop 16.04 LTS、18.04 LTS和20.04 LTS上进行了测试。在

1) 先决条件

$ sudo apt -y install git python3-pip

2) 下载源代码

^{pr2}$

3) 安装Hyve PyIPMI包和控制台程序

$ pip3 install .

测试Hyve PyIPMI

默认情况下,pip3将在$HOME/.local/lib/python3.x/site-packages中安装Hyve-PyIPMI包,并在$HOME/.local/bin中安装其控制台程序。一般来说,站点包目录已经包含在系统路径您需要自己在PATH中添加bin目录。例如,执行

$ export PATH=~/.local/bin:$PATH

然后,您就可以执行第一个PyIPMI命令。例如,我们执行与ipmitool非常相似的内容,如下所示:

$ pyipmi -H 192.168.0.169 -I lanplus -U root -P root123 raw 6 1

在第一次使用包时,它会自动在$HOME/.config/pyipmi中生成一个用户配置文件/pyipmi.conf默认设置。然后,支持的选项将覆盖某些设置。在上面的示例中,它指定了四个选项并发出一个原始IPMI命令。在

创建配置文件后,您可以选择使用配置文件中的所有设置,也可以像前面的示例一样继续覆盖某些选项。程序将自动在配置文件中记录最新的覆盖值。在

$ pyipmi sdr list   # Just use the settings in the config file
$ pyipmi -C 2 user list  # Use RMCP+ Cipher Suite 2
$ pyipmi -U hyve -P hyve456 lan print 1  # User credential hyve/hyve456

键入-h以显示所有命令选项,并使用“help”命令列出可用命令。在

$ pyipmi -h
$ pyipmi help

高级用法

程序pyipmr等于“pyipmi raw”+附加功能。它支持

  • IPMI响应LUN不是0
  • 从局域网到IPMB的IPMI消息桥接
$ pyipmr 6 1   # Get Device ID (NetFn=App, CMD=01h)
$ pyipmr -L 1 6 1  # LUN = 1
$ pyipmr -b 6 -t 0x2c raw 6 1  # Bridge Get Device ID to destination 0x2c via channel 6

测试脚本示例

Sample 1

#!/usr/bin/env python3
import sys
from pyipmi.util import PyTest

# Just overwrite the run_commands() method and you can issue
# IPMI commands like this example
class Sample1(PyTest):
    def __init__(self):
        super(Sample1, self).__init__()

    def run_commands(self, argv=None):
        # issue_raw_cmd(req, lun):
        #     req (list): [NetFn, CMD, Req_Data]
        #     lun (int): default is 0
        print('Get Device ID:')
        rsp = self.intf.issue_raw_cmd([6, 1])
        self.print_rsp(rsp)

        print('\nGet User Name 2:')
        rsp = self.intf.issue_raw_cmd([6, 0x46, 2])
        self.print_rsp(rsp)

        print('\nGet LAN Config 1:')
        rsp = self.intf.issue_raw_cmd([0x0c, 2, 1, 1, 0, 0])
        self.print_rsp(rsp)

if __name__ == '__main__':
    test = Sample1()
    sys.exit(test.run())

Sample 2

#!/usr/bin/env python3
import sys
from pyipmi.util import PyTest
from pyipmi.util.config import PyOpts

# Same as sample1, with simple checks on the response data
# and overwrite some values of the user config
class Sample2(PyTest):
    def __init__(self, opts):
        super(Sample2, self).__init__(opts)

    def run_commands(self, argv=None):
        req = ([[6, 1],                     # Get Device ID
                [6, 0x46, 2],               # Get User Name 2
                [0x0c, 2, 1, 1, 0, 0]])     # Get LAN Config 1

        rsp = ([[0, 0x22, 1, 1, 2, 2, 0x9f, 0x55, 0xda, 0, 1, 0, 0x59, 1, 0, 0],
                [0, 0x72, 0x6f, 0x6f, 0x74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                [0, 0x11, 0x15]])

        # run the commands
        count_p = 0
        count_f = 0
        for i in range(len(req)):
            rsp_one = self.intf.issue_raw_cmd(req[i])
            if rsp_one == rsp[i]:
                print('test case {0}: PASSED!'.format(i + 1))
                count_p += 1
            else:            
                print('test case {0}: FAILED!'.format(i + 1))
                count_f += 1

        # output the results            
        print('Total {0} cases executed: PASSED {1}, FAILED {2}.'
                .format(count_p + count_f, count_p, count_f))

if __name__ == '__main__':
    pyopts = PyOpts()
    pyopts.add_options()
    opts = pyopts.parse_options('-U hyve -P hyve123')

    test = Sample2(opts)
    sys.exit(test.run())

Sample 3

#!/usr/bin/env python3
import sys
from pyipmi.util import PyTest
from pyipmi.util.config import PyOpts

# Message bridging example
# Support the following configuration
# [PyIPMI] <-- LAN (RMCP/RMCP+) --> [BMC] <-- IPMB --> [ME]
class Sample3(PyTest):
    def __init__(self, opts, chnl, target):
        self.chnl = chnl
        self.target = target

        super(Sample3, self).__init__(opts)

    def bridge_cmd(self, req):
        # issue_bridging_cmd(chnl, target, req, lun):
        #     chnl (int): IPMI channel number to bridge the message
        #     target (int): I2C slave address of the bridging destination
        #     req (list): [NetFn, CMD, Req_Data]
        #     lun (int): default is 0
        return self.intf.issue_bridging_cmd(self.chnl, self.target, req) 

    def run_commands(self, argv=None):       
        print('Get Device ID:')
        rsp = self.bridge_cmd([6, 1])
        self.print_rsp(rsp)

        print('\nGet SEL Time:')
        rsp = self.bridge_cmd([0xa, 0x48])
        self.print_rsp(rsp)

        print('\nGet Event Receiver:')
        rsp = self.bridge_cmd([4, 1])
        self.print_rsp(rsp)

        print('\nGet Intel ME FW Capabilities:')
        rsp = self.bridge_cmd([0x2e, 0xde, 0x57, 1, 0, 0, 0, 0, 0, 2, 0xff, 0])
        self.print_rsp(rsp)

        print('\nGet Intel ME Factory Presets Signature:')
        rsp = self.bridge_cmd([0x2e, 0xe0, 0x57, 1, 0])
        self.print_rsp(rsp)

        print('\nGet Exception Data:')
        rsp = self.bridge_cmd([0x2e, 0xe6, 0x57, 1, 0, 0])
        self.print_rsp(rsp)

        print('\nGet Sensor Reading:')
        sensor_num = (8, 197)
        for num in sensor_num:
            rsp = self.bridge_cmd([4, 0x2d, num])
            self.print_rsp(rsp)

        print('\nGet SEL Entry:')
        req = [0xa, 0x43, 0, 0, 0, 0, 0, 0xff]
        rsp = self.bridge_cmd(req)
        id1, id2 = rsp[1:3]        
        while not (id1 == 0xff and id2 == 0xff):
            req[4], req[5] = id1, id2
            rsp = self.bridge_cmd(req)
            id1, id2 = rsp[1:3]        
            self.print_rsp(rsp)

if __name__ == '__main__':
    pyopts = PyOpts()
    pyopts.add_options()
    opts = pyopts.parse_options('-H 10.19.84.90 -I lanplus -U admin -P admin')

    test = Sample3(opts, 6, 0x2c)
    sys.exit(test.run())

Sample 4

#!/usr/bin/env python3
from pyipmi.cmds import PyCmds

if __name__ == '__main__':
    # This example shows how to use PyIPMI commands in a script
    cmd = PyCmds()
    cmd.exec_command('raw 6 1')
    cmd.exec_command('mc info')
    cmd.exec_command('chassis status')
    cmd.exec_command('power status')
    cmd.exec_command('sdr list')
    cmd.exec_command('sel list')
    cmd.exec_command('sensor list')
    cmd.exec_command('lan print 1')
    cmd.exec_command('user list')

sample 5

#!/usr/bin/env python3
from pyipmi.cmds import PyCmds
from pyipmi.util.config import PyOpts

if __name__ == '__main__':
    # Same as sample4,
    # with overwriting some of the options in the user config
    pyopts = PyOpts()
    pyopts.add_options()
    opts = pyopts.parse_options('-U hyve -P hyve123')

    cmd = PyCmds(opts)
    cmd.exec_command('raw 6 1')
    cmd.exec_command('mc info')
    cmd.exec_command('chassis status')
    cmd.exec_command('power status')
    cmd.exec_command('sdr list')
    cmd.exec_command('sel list')
    cmd.exec_command('sensor list')
    cmd.exec_command('lan print 1')
    cmd.exec_command('user list')

Sample 6

#!/usr/bin/env python3
from pyipmi.cmds import PyCmds, StrEx
from pyipmi.util.config import PyOpts

def find_line(target, src_str):
    ret = '(not found)'
    list1 = src_str.split('\n')    
    for s in list1:
        if s[:len(target)] == target:
            ret = s
            break

    return ret + '\n'

if __name__ == '__main__':
    pyopts = PyOpts()
    pyopts.add_options()
    opts = pyopts.parse_options('-U hyve -P hyve123')

    # Instead of printing out the results to the console, this sample shows
    # how to record them in a string named 'print_str'.
    print_str = StrEx()
    cmd = PyCmds(opts, print_str)

    # The results will be appended in 'print_str' when the next command is called, 
    # just like what you see from the console by running sample4 and sample5.
    # If you don't want this, you need to explictly call 'print_str.reset()'
    # before calling the next cmd.exec_command().

    # In this example, assume we'd like to retrieve specific lines from the outputs
    cmd.exec_command('raw 6 1')
    ret_all = print_str.get_str()
    print_str.reset()

    cmd.exec_command('mc info')
    ret = print_str.get_str()
    ret_all += find_line('Manufacturer ID', ret)
    print_str.reset()

    cmd.exec_command('lan print 1')
    ret = print_str.get_str()
    ret_all += find_line('RMCP+ Cipher Suites', ret)    

    print(ret_all)

联系人

如果您有任何问题或建议,您可以联系Janny Au,这个程序的主要开发人员。在

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
我可以用C++代码使用java代码吗?   java使用JSR303在派生类中提供更具体的约束   java在这个查找唯一路径数算法中我做错了什么?   java如何为2个不同的服务提供商使用2个不同的SSL证书?   java在Gridview上绘制文本   java使用连接for循环构建字符串名   java StringBuilder拆分无法处理某些文件   java事件关注EditText   Java Web Start“找不到URL的缓存资源”   java程序从命令行运行的速度比在Eclipse中慢   java为什么HttpServletRequest会截断#字符上的url输入?   java自定义折叠工具栏平滑标题大小调整   使用Mockito对安卓 java中调用另一个静态函数的函数进行单元测试   http在java客户机中使用cachecontrol头   java如何使用。是否使用Delimiter从输入文件中排除标点符号和数字?   使用上下文作为参数/参数的java   java更有效地从Jar中提取文件   java为多个JButton提供相同的actionListener