java ipmi 获取服务器硬件信息(温度,风扇转速,内存数,硬盘数等等)

本文通过vxipmi.jar获取

官方地址:http://www.veraxsystems.com/en/products/free-ipmi-library-java

 
import java.net.InetAddress;
import java.util.List;

import com.veraxsystems.vxipmi.api.async.ConnectionHandle;
import com.veraxsystems.vxipmi.api.sync.IpmiConnector;
import com.veraxsystems.vxipmi.coding.commands.IpmiVersion;
import com.veraxsystems.vxipmi.coding.commands.PrivilegeLevel;
import com.veraxsystems.vxipmi.coding.commands.sdr.GetSdr;
import com.veraxsystems.vxipmi.coding.commands.sdr.GetSdrResponseData;
import com.veraxsystems.vxipmi.coding.commands.sdr.GetSensorReading;
import com.veraxsystems.vxipmi.coding.commands.sdr.GetSensorReadingResponseData;
import com.veraxsystems.vxipmi.coding.commands.sdr.ReserveSdrRepository;
import com.veraxsystems.vxipmi.coding.commands.sdr.ReserveSdrRepositoryResponseData;
import com.veraxsystems.vxipmi.coding.commands.sdr.record.CompactSensorRecord;
import com.veraxsystems.vxipmi.coding.commands.sdr.record.FullSensorRecord;
import com.veraxsystems.vxipmi.coding.commands.sdr.record.RateUnit;
import com.veraxsystems.vxipmi.coding.commands.sdr.record.ReadingType;
import com.veraxsystems.vxipmi.coding.commands.sdr.record.SensorRecord;
import com.veraxsystems.vxipmi.coding.payload.CompletionCode;
import com.veraxsystems.vxipmi.coding.payload.lan.IPMIException;
import com.veraxsystems.vxipmi.coding.protocol.AuthenticationType;
import com.veraxsystems.vxipmi.coding.security.CipherSuite;
import com.veraxsystems.vxipmi.common.PropertiesManager;
import com.veraxsystems.vxipmi.common.TypeConverter;


import java.net.InetAddress;

/**
 * Created by Administrator on 2018/5/22 0022.
 */
public class IpmiUtil {

    /**
     * This is the value of Last Record ID (FFFFh). In order to retrieve the full set of SDR records, client must repeat
     * reading SDR records until MAX_REPO_RECORD_ID is returned as next record ID. For further information see section
     * 33.12 of the IPMI specification ver. 2.0
     */
    private static final int MAX_REPO_RECORD_ID = 65535;

    private static final String hostname = "192.168.1.247";

    private static final String username = "USERID";

    private static final String password = "PASSW0RD";

    /**
     * Size of the initial GetSdr message to get record header and size
     */
    private static final int INITIAL_CHUNK_SIZE = 8;

    /**
     * Chunk size depending on buffer size of the IPMI server. Bigger values will improve performance. If server is
     * returning "Cannot return number of requested data bytes." error during GetSdr command, CHUNK_SIZE should be
     * decreased.
     */
    private static final int CHUNK_SIZE = 16;

    /**
     * Size of SDR record header
     */
    private static final int HEADER_SIZE = 5;

    private int nextRecId;

    /**
     * @param args
     */
    public static void main(String[] args) {
        IpmiUtil runner = new IpmiUtil();
        try {
            runner.doRun();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void doRun() throws Exception {
        // ID 0指示SDR中的第一个记录。下一个IDS可以从记录中检索出来——它们被组织在一个列表中,没有BMC命令来获取所有这些ID。
        nextRecId = 0;

        // 一些BMC允许无保留地获取传感器记录,所以我们尝试这样做。
        int reservationId = 0;
        int lastReservationId = -1;

        // 创建连接器
        IpmiConnector connector = new IpmiConnector(0);

        // 启动会话到远程主机
        ConnectionHandle handle = startSession(connector, InetAddress.getByName(hostname), username, password, "",
                PrivilegeLevel.User);

        // 更改连接超时时间
        connector.setTimeout(handle, 2750);

        // 我们得到传感器数据,直到我们遇到ID=65535,这意味着这个记录是最后一个。
        while (nextRecId < MAX_REPO_RECORD_ID) {
            SensorRecord record = null;

            try {
                // 填充传感器记录并获取存储库中的下一条记录的ID
                record = getSensorData(connector, handle, reservationId);

                int recordReadingId = -1;

                // 判断接收到的数据是全部传感器记录还是压缩的记录(详见IPMI规范)
                if (record instanceof FullSensorRecord) {
                    FullSensorRecord fsr = (FullSensorRecord) record;
                    recordReadingId = TypeConverter.byteToInt(fsr.getSensorNumber());
                    System.out.println("传感器名称:" + fsr.getName());

                } else if (record instanceof CompactSensorRecord) {
                    CompactSensorRecord csr = (CompactSensorRecord) record;
                    recordReadingId = TypeConverter.byteToInt(csr.getSensorNumber());
                    System.out.println("传感器名称:" + csr.getName());
                }

                // 如果有记录,我们会得到响应数据
                GetSensorReadingResponseData data2 = null;
                try {
                    if (recordReadingId >= 0) {
                        data2 = (GetSensorReadingResponseData) connector
                                .sendMessage(handle, new GetSensorReading(IpmiVersion.V20, handle.getCipherSuite(),
                                        AuthenticationType.RMCPPlus, recordReadingId));
                        if (record instanceof FullSensorRecord) {
                            FullSensorRecord rec = (FullSensorRecord) record;
                            // 解析传感器读取的记录信息
                            System.out.println("解析传感器读取的记录信息:" + data2.getSensorReading(rec) + " " + rec.getSensorBaseUnit().toString()
                                    + (rec.getRateUnit() != RateUnit.None ? " per " + rec.getRateUnit() : ""));
                        }
                        if (record instanceof CompactSensorRecord) {
                            CompactSensorRecord rec = (CompactSensorRecord) record;
                            // 获取传感器状态
                            List<ReadingType> events = data2.getStatesAsserted(rec.getSensorType(),
                                    rec.getEventReadingType());
                            StringBuilder s = new StringBuilder();
                            for (int i = 0; i < events.size(); ++i) {
                                s.append(events.get(i)).append(", ");
                            }
                            System.out.println("传感器状态:" + s);
                        }
                    }
                } catch (IPMIException e) {
                    if (e.getCompletionCode() == CompletionCode.DataNotPresent) {
                        e.printStackTrace();
                    } else {
                        throw e;
                    }
                }
            } catch (IPMIException e) {
                System.out.println("Getting new reservation ID");
                System.out.println("156: " + e.getMessage());
                // 如果获得传感器数据失败,检查预留id是否已经失败了
                if (lastReservationId == reservationId || e.getCompletionCode() != CompletionCode.ReservationCanceled)
                    throw e;
                lastReservationId = reservationId;

                // 如果失败的原因是取消预留,我们得到新的预留ID并重试
                // 在获得所有传感器时,这会发生很多次,因为BMC不能管理并行会话,如果出现新的会话,BMC就不能管理旧的会话。
                reservationId = ((ReserveSdrRepositoryResponseData) connector.sendMessage(handle, new ReserveSdrRepository(IpmiVersion.V20, handle.getCipherSuite(),
                        AuthenticationType.RMCPPlus))).getReservationId();
            }
        }

        // 关闭会话
        connector.closeSession(handle);
        // 关闭连接
        connector.closeConnection(handle);
        connector.tearDown();
    }

    /**
     * 启动会话
     *
     * @param connector      连接器
     * @param address        连接地址
     * @param username       用户名
     * @param password       密码
     * @param bmcKey         二次校验密码
     * @param privilegeLevel 特权级别
     * @return
     * @throws Exception
     */
    public ConnectionHandle startSession(IpmiConnector connector, InetAddress address, String username, String password, String bmcKey, PrivilegeLevel privilegeLevel) throws Exception {
        ConnectionHandle handle = connector.createConnection(address);
        CipherSuite cs;
        try {
            // 获取远程主机支持的密码套件
            List<CipherSuite> suites = connector.getAvailableCipherSuites(handle);

            if (suites.size() > 3) {
                cs = suites.get(3);
            } else if (suites.size() > 2) {
                cs = suites.get(2);
            } else if (suites.size() > 1) {
                cs = suites.get(1);
            } else {
                cs = suites.get(0);
            }
            // 选择密码套件并请求会话特权级别
            connector.getChannelAuthenticationCapabilities(handle, cs, privilegeLevel);
            // 打开会话并验证
            connector.openSession(handle, username, password, bmcKey.getBytes());
        } catch (Exception e) {
            connector.closeConnection(handle);
            throw e;
        }
        return handle;
    }

    /**
     * 获取传感器数据
     *
     * @param connector     连接器
     * @param handle        连接句柄
     * @param reservationId 预留id
     * @return
     * @throws Exception
     */
    public SensorRecord getSensorData(IpmiConnector connector, ConnectionHandle handle, int reservationId)
            throws Exception {
        try {
            // BMC功能是有限的,这意味着有时记录大小超过消息的最大大小。因为我们不知道这个记录的大小,所以我们先把整个记录放在第一位。
            GetSdrResponseData data = (GetSdrResponseData) connector.sendMessage(handle, new GetSdr(IpmiVersion.V20,
                    handle.getCipherSuite(), AuthenticationType.RMCPPlus, reservationId, nextRecId));
            // 如果获得完整的记录,我们从接收到的数据创建传感记录
            SensorRecord sensorDataToPopulate = SensorRecord.populateSensorRecord(data.getSensorRecordData());
            // 更新下一个记录的ID
            nextRecId = data.getNextRecordId();
            return sensorDataToPopulate;
        } catch (IPMIException e) {
            // 下面的错误代码意味着记录太大,无法在一个块中发送。这意味着我们需要把数据分割成更小的部分。
            if (e.getCompletionCode() == CompletionCode.CannotRespond
                    || e.getCompletionCode() == CompletionCode.UnspecifiedError) {
                System.out.println("Getting chunks");
                // 首先,我们得到记录的头来找出它的大小。
                GetSdrResponseData data = (GetSdrResponseData) connector.sendMessage(handle, new GetSdr(
                        IpmiVersion.V20, handle.getCipherSuite(), AuthenticationType.RMCPPlus, reservationId,
                        nextRecId, 0, INITIAL_CHUNK_SIZE));
                // 记录的大小是记录的第五字节。它没有考虑页眉的大小,所以我们需要添加它。
                int recSize = TypeConverter.byteToInt(data.getSensorRecordData()[4]) + HEADER_SIZE;
                int read = INITIAL_CHUNK_SIZE;

                byte[] result = new byte[recSize];

                System.arraycopy(data.getSensorRecordData(), 0, result, 0, data.getSensorRecordData().length);

                // 我们得到了剩余的记录块(注意超过记录大小),因为这将导致BMC的错误。
                while (read < recSize) {
                    int bytesToRead = CHUNK_SIZE;
                    if (recSize - read < bytesToRead) {
                        bytesToRead = recSize - read;
                    }
                    GetSdrResponseData part = (GetSdrResponseData) connector.sendMessage(handle, new GetSdr(
                            IpmiVersion.V20, handle.getCipherSuite(), AuthenticationType.RMCPPlus, reservationId,
                            nextRecId, read, bytesToRead));

                    System.arraycopy(part.getSensorRecordData(), 0, result, read, bytesToRead);
                    System.out.println("Received part");
                    read += bytesToRead;
                }

                // 最后,用收集的数据填充传感器记录。
                SensorRecord sensorDataToPopulate = SensorRecord.populateSensorRecord(result);
                // 更新下一个记录的ID
                nextRecId = data.getNextRecordId();
                return sensorDataToPopulate;
            } else {
                throw e;
            }
        } catch (Exception e) {
            throw e;
        }
    }
}


打印出来的信息:

传感器名称:Ambient Temp
解析传感器读取的记录信息:23.0 DegreesC
传感器名称:Altitude
解析传感器读取的记录信息:1080.0 Feet
传感器名称:Avg Power
解析传感器读取的记录信息:0.0 Watts
传感器名称:Planar 3.3V
解析传感器读取的记录信息:3.3086 Volts
传感器名称:Planar 5V
解析传感器读取的记录信息:4.9268 Volts
传感器名称:Planar 12V
解析传感器读取的记录信息:12.042 Volts
传感器名称:Planar VBAT
解析传感器读取的记录信息:2.8829000000000002 Volts
传感器名称:Fan 1A Tach
解析传感器读取的记录信息:4770.0 Rpm
传感器名称:Fan 1B Tach
解析传感器读取的记录信息:3600.0 Rpm
传感器名称:Fan 2A Tach
解析传感器读取的记录信息:5035.0 Rpm
传感器名称:Fan 2B Tach
解析传感器读取的记录信息:3600.0 Rpm
传感器名称:Fan 3A Tach
解析传感器读取的记录信息:5936.0 Rpm
传感器名称:Fan 3B Tach
解析传感器读取的记录信息:4464.0 Rpm
传感器名称:Fan 4A Tach
解析传感器读取的记录信息:6095.0 Rpm
传感器名称:Fan 4B Tach
解析传感器读取的记录信息:4560.0 Rpm
传感器名称:Fan 5A Tach
解析传感器读取的记录信息:6042.0 Rpm
传感器名称:Fan 5B Tach
解析传感器读取的记录信息:4608.0 Rpm
传感器名称:Fan 6A Tach
解析传感器读取的记录信息:6254.0 Rpm
传感器名称:Fan 6B Tach
解析传感器读取的记录信息:4608.0 Rpm
传感器名称:Fan 1
传感器状态:EntityPresent, 
传感器名称:Fan 2
传感器状态:EntityPresent, 
传感器名称:Fan 3
传感器状态:EntityPresent, 
传感器名称:Fan 4
传感器状态:EntityPresent, 
传感器名称:Fan 5
传感器状态:EntityPresent, 
传感器名称:Fan 6
传感器状态:EntityPresent, 
传感器名称:Front Panel
传感器状态:EntityPresent, 
传感器名称:Video USB
传感器状态:CableInterconnectConnected, 
传感器名称:DASD Backplane
传感器状态:EntityPresent, 
传感器名称:SAS Riser
传感器状态:EntityPresent, 
传感器名称:PCI Riser 1
传感器状态:EntityPresent, 
传感器名称:PCI Riser 2
传感器状态:EntityPresent, 
传感器名称:CPU 1
传感器状态:ProcessorPresenceDetected, 
传感器名称:CPU 2
传感器状态:ProcessorPresenceDetected, 
传感器名称:All CPUs
传感器状态:
传感器名称:One of the CPUs
传感器状态:
传感器名称:IOH Temp Status
传感器状态:TransitionToOK, 
传感器名称:CPU 1 OverTemp
传感器状态:TransitionToOK, 
传感器名称:CPU 2 OverTemp
传感器状态:TransitionToOK, 
传感器名称:CPU Fault Reboot
传感器状态:
传感器名称:Aux Log
传感器状态:
传感器名称:NMI State
传感器状态:
传感器名称:ABR Status
传感器状态:
传感器名称:Progress
传感器状态:
传感器名称:Firmware Error
传感器状态:
传感器名称:PCIs
传感器状态:
传感器名称:CPUs
传感器状态:
传感器名称:DIMMs
传感器状态:
传感器名称:Sys Board Fault
传感器状态:
传感器名称:Power Supply 1
传感器状态:PowerSupplyPresenceDetected, 
传感器名称:Power Supply 2
传感器状态:PowerSupplyPresenceDetected, PowerSupplyInputLost, 
传感器名称:PS 1 Fan Fault
传感器状态:TransitionToOK, 
传感器名称:PS 2 Fan Fault
传感器状态:TransitionToOK, 
传感器名称:VT Fault
传感器状态:
传感器名称:Pwr Rail A Fault
传感器状态:TransitionToOK, 
传感器名称:Pwr Rail B Fault
传感器状态:TransitionToOK, 
传感器名称:Pwr Rail C Fault
传感器状态:TransitionToOK, 
传感器名称:Pwr Rail D Fault
传感器状态:TransitionToOK, 
传感器名称:Pwr Rail E Fault
传感器状态:TransitionToOK, 
传感器名称:PS 1 Therm Fault
传感器状态:TransitionToOK, 
传感器名称:PS 2 Therm Fault
传感器状态:TransitionToOK, 
传感器名称:PS1 12V OV Fault
传感器状态:TransitionToOK, 
传感器名称:PS2 12V OV Fault
传感器状态:TransitionToOK, 
传感器名称:PS1 12V UV Fault
传感器状态:TransitionToOK, 
传感器名称:PS2 12V UV Fault
传感器状态:TransitionToOK, 
传感器名称:PS1 12V OC Fault
传感器状态:TransitionToOK, 
传感器名称:PS2 12V OC Fault
传感器状态:TransitionToOK, 
传感器名称:PS 1 VCO Fault
传感器状态:TransitionToOK, 
传感器名称:PS 2 VCO Fault
传感器状态:TransitionToOK, 
传感器名称:Power Unit
传感器状态:RedundancyLost, 
传感器名称:Cooling Zone 1
传感器状态:FullyRedundant, 
传感器名称:Cooling Zone 2
传感器状态:FullyRedundant, 
传感器名称:Cooling Zone 3
传感器状态:FullyRedundant, 
传感器名称:Drive 0
传感器状态:DrivePresence, 
传感器名称:Drive 1
传感器状态:DrivePresence, 
传感器名称:Drive 2
传感器状态:DrivePresence, 
传感器名称:Drive 3
传感器状态:DrivePresence, 
传感器名称:Drive 4
传感器状态:DrivePresence, 
传感器名称:Drive 5
传感器状态:DrivePresence, 
传感器名称:All DIMMS
传感器状态:
传感器名称:One of the DIMMs
传感器状态:
传感器名称:DIMM 1
传感器状态:
传感器名称:DIMM 2
传感器状态:
传感器名称:DIMM 3
传感器状态:MemoryPresenceDetected, 
传感器名称:DIMM 4
传感器状态:
传感器名称:DIMM 5
传感器状态:
传感器名称:DIMM 6
传感器状态:
传感器名称:DIMM 7
传感器状态:
传感器名称:DIMM 8
传感器状态:
传感器名称:DIMM 9
传感器状态:
传感器名称:DIMM 10
传感器状态:
传感器名称:DIMM 11
传感器状态:MemoryPresenceDetected, 
传感器名称:DIMM 12
传感器状态:
传感器名称:DIMM 13
传感器状态:
传感器名称:DIMM 14
传感器状态:
传感器名称:DIMM 15
传感器状态:MemoryPresenceDetected, 
传感器名称:DIMM 16
传感器状态:MemoryPresenceDetected, 
传感器名称:DIMM 1 Temp
传感器状态:
传感器名称:DIMM 2 Temp
传感器状态:
传感器名称:DIMM 3 Temp
传感器状态:TransitionToOK, 
传感器名称:DIMM 4 Temp
传感器状态:
传感器名称:DIMM 5 Temp
传感器状态:
传感器名称:DIMM 6 Temp
传感器状态:
传感器名称:DIMM 7 Temp
传感器状态:
传感器名称:DIMM 8 Temp
传感器状态:
传感器名称:DIMM 9 Temp
传感器状态:
传感器名称:DIMM 10 Temp
传感器状态:
传感器名称:DIMM 11 Temp
传感器状态:TransitionToOK, 
传感器名称:DIMM 12 Temp
传感器状态:
传感器名称:DIMM 13 Temp
传感器状态:
传感器名称:DIMM 14 Temp
传感器状态:
传感器名称:DIMM 15 Temp
传感器状态:TransitionToOK, 
传感器名称:DIMM 16 Temp
传感器状态:TransitionToOK, 
传感器名称:All PCI Error
传感器状态:
传感器名称:One of PCI Error
传感器状态:
传感器名称:PCI 1
传感器状态:
传感器名称:Watchdog
传感器状态:
传感器名称:Host Power
传感器状态:
传感器名称:Backup Memory
传感器状态:
传感器名称:Planar Fault
传感器状态:TransitionToOK, 
传感器名称:SEL Fullness
传感器状态:SelAlmostFull, 
传感器名称:PCI 5
传感器状态:
传感器名称:OS RealTime Mod
传感器状态:
传感器名称:PCI 2
传感器状态:

 

  • 1
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值