KVM客户端开发套件
更新时间:2025/08/12
在Gitcode上查看源码

libirc库对openUBMC社区提供KVM客户端开发套件,赋能用户在工具和系统集成KVM功能,调用libirc库提供的接口使用、操作KVM客户端。

编译环境搭建方法可见libirc库README文件

功能介绍

通过集成libirc库,可以向BMC(作为服务端)发送封装好的WebSocket请求,将建立连接、执行操作、关闭连接以调用接口的方式便捷地集成至用户的系统中。

当前libirc库支持以下功能:

  • 认证

    • 基于boost开源软件和openssl, 发送https POST请求到/UI/Rest/KvmHandler, 用于创建KVM会话并获取token和KVM端口号。
  • 建立WebSocket连接

    • 基于boost开源软件和openssl, 与KVM服务端建立WebSocket连接;
    • 使用认证阶段得到的token, 封装KVM认证报文,发送至服务端认证KVM会话;
    • 认证后启动心跳检测机制,定时发送封装的KVM心跳报文;
    • 接收服务发送的KVM协议报文,解析并分发给其它业务处理;
    • 关闭连接时发送封装的KVM断开连接报文;
  • BIOS启动项控制

    • 连接KVM后会主动获取一次BIOS启动项当前配置;
    • 接收到BIOS启动项配置响应报文后更新BIOS启动项当前配置;
    • 根据用户输入封装BIOS启动项报文发送至KVM服务端;
  • 电源控制

    • 根据用户输入封装电源控制报文发送至KVM服务端;
  • 虚拟光驱控制

    • 根据用户输入封装虚拟光驱控制报文发送至KVM服务端,操作类型包括弹出和挂载虚拟媒体;

客户端调用接口后,根据接口返回码执行自定义后续操作。


关键接口

libirc库对外提供了以下关键接口,通过这些接口,可以实现开启、关闭KVM会话、进行光驱操作等。

关键接口功能

  • void SetErrorHandler(std::function<void(const std::exception&)> handler)

    设置错误处理函数,入参为处理函数,而处理函数的入参为exception异常,用于自定义运行时错误异常的处理;

  • void SetCloseHandler(std::function<void(const uint16_t&)> handler)

    设置关闭处理函数,入参为处理函数,而处理函数的入参为KVM会话关闭状态码,定义参考WebSocket协议关闭状态码,用于自定义对KVM会话关闭的处理;

  • void SetLogHandler(std::function<void(const std::string&)> handler)

    设置日志处理函数,入参为处理函数,而处理函数的入参为日志字符串,用于自定义运行时产生的日志处理;

  • int OpenKvm(const char* host, const char* port, const char* userName, const char* password, const char* kvmMode)

    打开KVM会话函数,入参为主机IP、https端口号、用户名、密码、KVM连接模式(0:共享/1:独占),出参为错误码响应,错误码定义参考响应码

  • int CloseKvm()

    关闭KVM会话函数,出参为错误码响应,错误码定义参考响应码

  • int GetBootOption(BootOption& option)

    获取当前系统启动项函数,获取成功会将结果设置到传入的引用中,BootOption枚举类型定义参考系统启动项定义,出参为错误码响应;

  • int SetBootOption(BootOption option)

    设置系统启动项函数,入参为BootOption枚举类型的系统启动项,出参为错误码响应,错误码定义参考响应码

  • int PowerControl(PowerControlOption option)

    电源控制函数,入参为PowerControlOption枚举类型的电源控制项,PowerControlOption枚举类型定义参考电源控制项定义,出参为错误码响应,错误码定义参考响应码

  • int OpenVmm(const std::string& filePath, MountType type)

    VMM虚拟媒体挂载函数,入参为本地镜像文件路径、挂载类型,当前仅支持挂载镜像文件,出参为错误码响应,错误码定义参考响应码

  • int CloseVmm()

    VMM虚拟媒体卸载函数,出参为错误码响应,错误码定义参考响应码


响应码

libirc库定义了13种返回码,返回码对应表如下:

宏定义常量值说明
E_OK0执行成功
E_ERR1发生错误
E_AUTHORIZATION_FAILED2鉴权失败
E_NO_ACCESS3无法获取
E_INSUFFICIENT_PRIVILEGE4权限不足
E_SESSION_LIMIT_EXCEEDED5会话超限
E_SESSION_MODE_IS_EXCLUSIVE6当前KVM会话模式为独占模式
E_INVALID_PARAM7非法入参
E_ALREADY_CONNECTED8重复连接
E_NOT_CONNECTED9未连接
E_TIMEOUT10超时
E_VMM_DISABLED11VMM使能关闭
E_INVALID_FILE_PATH12非法文件路径
E_VMM_BUSY13VMM被占用

NOTE

客户端获取到响应后,需要根据返回码自定义客户端对应操作。


WebSocket协议关闭状态码

WebSocket断开连接时,会返回一个关闭状态码,并根据SetCloseHandler注册的对不同关闭状态码的处理函数进行自定义处理。关闭状态码对应表如下:

宏定义常量值说明
NORMAL_CLOSURE1000正常断开连接
GOING_AWAY1001服务不存在或服务器断开连接
PROTOCOL_ERROR1002WebSocket协议错误
UNSUPPORTED_CLOSURE1003客户端接收到不允许的数据类型(如接收到二进制数据而不是文本数据)
ABNORMAL_CLOSURE1006用于期望收到状态码时连接非正常关闭(即没有发送关闭帧)
UNSUPPORTED_DATA1007客户端接收到格式不符的无效数据而关闭连接(如文本数据中包含了非UTF-8字符)
TIMEOUT1008客户端接收到不符合约定的数据而断开连接,通用状态码
MESSAGE_TOO_BIG1009传输数据量过大
MANDATORY_EXT1010客户端终止连接
INTERNAL_ERROR1011服务端终止连接
SERVICE_RESTART1012服务端正在重新启动
TRY_AGAIN_LATER1013服务端临时终止
BAD_GATEWAY1014通过网关或代理请求服务端,服务端无法及时响应
TOO_MANY_CONNECTIONS4000WebSocket连接过多
FORCE_TO_KICK_SESSION4001强制踢出会话

NOTE

4xxx格式的关闭状态码为业务自定义状态码。

通过调用SetHandler注册以上关闭状态码的处理函数,可以实现断开WebSocket连接时的自定义处理。如正常断开连接(关闭状态码1000)时退出KVM客户端,服务端重新启动(关闭状态码1012)时等待一段时间,WebSocket连接过多(关闭状态码4000)时弹出提示等。


系统启动项定义

libirc库定义了6种系统启动项,系统启动项对应表如下:

宏定义常量值说明
None0x00无启动介质
Hdd0x01硬盘启动
Cd0x02光驱启动
Floppy0x03软驱启动
Pxe0x04PXE启动
BiosSetup0x05BIOS设置启动

获取系统启动项成功时,枚举类型BootOption的入参会被置为以上启动项中的一项;设置系统启动项时,则需要把预期设置的启动项作为入参传入。


电源控制项定义

libirc库定义了6种电源控制项,电源控制项对应表如下:

宏定义常量值说明
On0x00上电
ForceOff0x01强制下电
GracefulShutdown0x02下电
ForceRestart0x03强制重启
ForcePowerCycle0x04强制下电再上电
GracefulPowerCycle0x05安全下电再上电

控制电源时,则需要把预期进行的电源控制项作为入参传入。

简单示例

libirc代码仓提供了简单demo示例,运行demo可以按照回显执行libirc库提供的所有对外接口。

调用方式以GetBootOption为例:

c++
void handleGetBootOption(KvmClient& kvmClient) {
    BootOption option;  // 初始化BootOption枚举类型
    int result = kvmClient.GetBootOption(option);   // 以入参传入GetBootOption,结果存储在option,返回码用result接收
    // 处理未成功执行的场景
    if (result != 0) {
        std::cerr << "Failed to get boot option, errorCode: " << result << "\n";
        return;
    }

    std::cout << "Current boot option: ";
    // 将BootOption枚举类型取值转换为对应含义输出
    switch (option) {
        case BootOption::None: std::cout << "None\n"; break;
        case BootOption::Hdd: std::cout << "Hdd\n"; break;
        case BootOption::Cd: std::cout << "Cd\n"; break;
        case BootOption::Floppy: std::cout << "Floppy\n"; break;
        case BootOption::Pxe: std::cout << "Pxe\n"; break;
        case BootOption::BiosSetup: std::cout << "BiosSetup\n"; break;
        default: std::cout << "Unknown\n"; break;
    }
}