OpenBMC开发之虚拟媒体virtual-media服务

虚拟媒体(Virtual Media)(又称远程媒体)

问题描述

虚拟媒体允许用户通过BMC将给定的ISO/IMG驱动器映像远程挂载到服务器主机。远程驱动器在主机中显示为USB存储设备,并以RO模式或RW模式运行(请记住容器限制和写保护开关)。这甚至可以用于在裸机系统上安装操作系统。本文档重点介绍了一些重定向选项,例如基于浏览器的ISO/IMG映像挂载和远程CIFS/HTTPS映像挂载。

参考资料

  • 虚拟媒体将使用网络块设备作为主要的磁盘映像转发器。
  • NBDkit被用来从远程存储中提供映像,通过HTTPS/CIFS协议。使用USBGadget将媒体存储设备暴露给主机。

需求

提议的设计

虚拟媒体分为两种操作模式,称之为代理模式和传统模式。

  • 代理模式 - 直接从浏览器中工作,并使用JavaScript/HTML5通过安全的WebSocket直接与BMC上托管的HTTPS端点进行通信。
  • 传统模式 - 从浏览器中使用Redfish定义的VirtualMedia模式启动,然后BMC进程连接到在初始化期间指定的外部CIFS/HTTPS映像。

这两种方法均继承了默认的Redfish/BMCWeb身份验证和特权机制。

以下组件图显示了虚拟媒体的高级概述。

+------------------+           +----------------------------------+     +-----------------------+
|Remote Device|    |           |BMC|              +------------+  |     |HOST|                  |
+-------------/    |           +---/ +--Dbus----->+VirtualMedia|  |     +----/                  |
|                  |           |     v            +------------+  |     |                       |
|  +------------+  |           |   +-+--------+                   |     |                       |
|  |WebBrowser  +<----HTTPS------->+BMCWeb    |      +---------+  |     |  +----------+         |
|  +------------+  |           |   +-+--------+      |USBGadget+<--------->+USB Device|         |
+------------------+           |     ^               +----+----+  |     |  +----------+         |
                               |     |                    ^       |     |                       |
                               |     |    +------+        v       |     |                       |
                               |     +--->+UNIX  |   +----+----+  |     |                       |
                               |          |SOCKET+<->+NBDClient|  |     |                       |
+------------------+           |     +--->+      |   +---------+  |     |                       |
|Remote Storage|   |           |     |    +------+                |     |                       |
+--------------/   |           |     |                            |     |                       |
|                  |           |     v                            |     |                       |
|   +-----------+  |           |   +-+-------+                    |     |                       |
|   |ISO/IMG    +<---CIFS/HTTPS+-->+NBDkit   |                    |     |                       |
|   +-----------+  |           |   +---------+                    |     +-----------------------+
|                  |           |                                  |
+------------------+           +----------------------------------+

Virtual Media功能支持在两种模式下进行多个同时连接。

异步性

挂载和卸载远程设备可能需要一些时间。Virtual Media应在DBus和可选的Redfish API级别支持异步性。

DBus的默认超时时间为25秒,Redfish的默认超时时间为60秒,可能在某些情况下不足以执行挂载和卸载。

异步响应将在适当的部分中描述。

网络块设备(NBD)

读者可以注意到,图表中的大多数连接都基于网络块设备。根据Sourceforge项目的描述:

在内核中编译了这个之后,Linux可以将远程服务器用作其块设备之一。每次客户端计算机想要读取/dev/nbd0时,它都会通过TCP向服务器发送一个请求,服务器将回复请求的数据。这可以用于具有低磁盘空间的工作站(甚至是无盘 - 如果您使用initrd)从其他计算机借用磁盘空间。与NFS不同,可以在其上放置任何文件系统。但是(与NFS不同),如果有人将NBD挂载为读/写,则必须确保没有其他人会将其挂载。

– https://nbd.sourceforge.io/

在Virtual Media用例中,它被用于从远程客户端拉取数据,并将其呈现到未挂载到BMC的/dev/nbdXX设备中。然后通过USB Gadget将块设备提供给Host。

USB Gadget

Linux内核的一部分,通过USB "On-The-Go"使得特定USB设备类别的仿真成为可能,如果适当地连接到Host,则会仿真USB大容量存储器连接到HOST。在Virtual Media的情况下,它模拟连接到HOST的USB大容量存储器。源或重定向是由nbd-client创建的块设备/dev/nbdXX

代理模式

代理模式使用浏览器JavaScript和WebSocket支持,创建JS NBD服务器。浏览器负责创建HTTPS会话,验证用户,并接收给定的权限,然后通过RFC6455中描述的机制将HTTPS会话升级到WSS。自从WSS升级以来,JS应用程序负责处理所有规范要求的NBD服务器命令。

每个URI上打开多个同时连接,在HTTPS服务器中定义可用的同时连接数。下一章节中描述的配置文件定义了可用的同时连接数。

代理的加密是通过HTTPS/WSS通道支持的,并从HTTPS服务器直接继承加密机制,所有数据交易都经过bmcweb。

连接的初始化将如图所示:

┌───────┐                  ┌──────┐       ┌────────────┐          ┌─────────┐   ┌────┐ ┌─────────┐
│Browser│                  │bmcweb│       │VirtualMedia│          │NBDClient│   │uDEV│ │USBGadget│
└───┬───┘                  └──┬───┘       └─────┬──────┘          └────┬────┘   └─┬──┘ └────┬────┘
    │ establish HTTPS session │                 │                      │          │         │
    │─────────────────────────>                 │                      │          │         │
    │                         │                 │                      │          │         │
    │   upgrade to WSS on     │                 │                      │          │         │
    │    /nbd/X endpoint      │  ╔══════════════╧════╗                 │          │         │
    │─────────────────────────>  ║* bmcweb creates  ░║                 │          │         │
    │                         │  ║  /tmp/nbd.X.sock  ║                 │          │         │
    │                         │  ║* bmcweb locks new ║                 │          │         │
    │                         │  ║  connections on   ║                 │          │         │
    │                         │  ║  endpoint /nbd/X  ║                 │          │         │
    │                         │  ╚══════════════╤════╝                 │          │         │
    │                         │    Mount from:  │                      │          │         │
    │                         │ /tmp/nbd.X.sock │                      │          │         │
    │                         │ ────────────────>                      │          │         │
    │                         │                 │                      │          │         │
    │                         │                 │ Spawn NBDClient from │          │         │
    │                         │                 │    /tmp/nbd.x.sock   │          │         │
    │                         │                 │      to /dev/nbdX   ┌┴┐         │         │
    │                         │                 │ ──────────────────> │ │         │         │
    │                         │                 │                     │ │         │         │
    │                         │                 │     Block Device    │ │         │         │
    │                         │                 │  properties changed │ │         │         │
    │                         │                 │ <───────────────────────────────│         │
    │                         │                 │                     │ │         │         │
    │                         │                 │      Configure USB mass         │         │
    │                         │                 │    storage from /dev/nbd/X      │         │
    │                         │                 │ ─────────────────────────────────────────>│
    │                         │                 │                     │ │         │         │
    │                         │    Completion   │                     | |         │         │
    │                         │      signal     │                     | |         │         │
    │                         │ <───────────────│                     │ │         │         │
    │                         │                 │                     │ │         │         │
    │                         │                 │         Data        │ │         │         │
    │<─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─>│
    │                         │                 │                     │ │         │         │

Legacy模式

Legacy模式使用DMTF定义的VirtualMedia schema来挂载外部CIFS/HTTPS映像。目前的实现仅支持流式挂载。在这种情况下,Redfish仅用作Virtual Media初始化的机制,不负责数据传输。对于数据,有一个单独的组件负责处理CIFS/HTTPS流量,称为NBDkit。

多个同时连接通过生成附加的nbkit实例进行支持,可用的CIFS/HTTPS实例数在下一章节中进行配置和详细描述。

加密基于远程存储连接,并遵循英特尔的最佳安全实践,只要远程服务器支持此类加密(例如HTTPS需要SSL,不支持纯HTTP,对于CIFS协议版本3.0允许启用加密,并将提供此功能)。

流程如下所示:

┌───────┐  ┌──────────┐  ┌──────┐  ┌────────────┐           ┌──────┐┌─────────┐┌────┐ ┌─────────┐
│Browser│  │CIFS/HTTPS│  │bmcweb│  │VirtualMedia│           │NBDkit││NBDClient││uDEV│ │USBGadget│
└───┬───┘  └────┬─────┘  └──┬───┘  └─────┬──────┘           └──┬───┘└────┬────┘└─┬──┘ └────┬────┘
    │establish HTTPS session│            │                     │         │       │         │
    │───────────────────────>            │                     │         │       │         │
    │           │           │            │                     │         │       │         │
    │Create new VirtualMedia│            │                     │         │       │         │
    │  mountpoint via POST  │            │                     │         │       │         │
    │───────────────────────>            │                     │         │       │         │
    │           │           │            │                     │         │       │         │
    │           │           │ Mount from │                     │         │       │         │
    │           │           │ CIFS/HTTPS │                     │         │       │         │
    │           │           │  location  │                     │         │       │         │
    │           │           │────────────>                     │         │       │         │
    │           │           │            │                     │         │       │         │
    │           │           │            │Spawn NBDKit mounting│         │       │         │
    │           │           │            │    given location   │         │       │         │
    │           │           │            │     appropriate     │         │       │         │
    │           │           │            │   /tmp/nbd.X.sock  ┌┴┐        │       │         │
    │           │           │            │ ──────────────────>│ │        │       │         │
    │           │           │            │                    │ │        │       │         │
    │           │           │            │      Spawn NBDClient from     │       │         │
    │           │           │            │ /tmp/nbd.X.sock to /dev/nbdX ┌┴┐      │         │
    │           │           │            │ ────────────────────────────>│ │      │         │
    │           │           │            │                    │ │       │ │      │         │
    │           │           │            │    Block Device properties changed    │         │
    │           │           │            │ <──────────────────────────────────────         │
    │           │           │            │                    │ │       │ │      │         │
    │           │           │            │    Configure USB mass storage from /dev/nbd/X   │
    │           │           │            │ ───────────────────────────────────────────────>│
    │           │           │            │                    │ │       │ │      │         │
    │           │           │ Completion │                    │ │       │ │      │         │
    │           │           │   signal   │                    │ │       │ │      │         │
    │           │           |<───────────│                    │ │       │ │      │         │
    │           │           │            │                    │ │       │ │      │         │
    │           │           │            │               Data │ │       │ │      │         │
    │           │ <─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─>│

Redfish support

虚拟媒体服务将作为DMTF定义的Redfish VirtualMedia终端点公开。以下是一些示例。

Virtual Media Collection schema

集合中的成员将根据下一节中描述的配置文件定义,并且无论是否插入媒体,都将可见。

Members in collection will be defined based on configuration file described in next sections. And will be visible despite media is inserted or not.

{
  "@odata.type": "#VirtualMediaCollection.VirtualMediaCollection",
  "Name": "Virtual Media Services",
  "Description": "Redfish-BMC Virtual Media Service Settings",
  "[email protected]": 2,
  "Members": [
    {
      "@odata.id": "/redfish/v1/Managers/BMC/VirtualMedia/ISO0"
    },
    {
      "@odata.id": "/redfish/v1/Managers/BMC/VirtualMedia/1"
    }
  ],
  "@odata.context": "/redfish/v1/$metadata#VirtualMediaCollection.VirtualMediaCollection",
  "@odata.id": "/redfish/v1/Managers/BMC/VirtualMedia"
}
Virtual Media schema
{
  "@odata.type": "#VirtualMedia.v1_1_0.VirtualMedia",
  "Id": "ISO0",
  "Name": "Virtual Removable Media",
  "Actions": {
    "#VirtualMedia.InsertMedia": {
      "target": "/redfish/v1/Managers/bmc/VirtualMedia/ISO0/Actions/VirtualMedia.InsertMedia"
    },
    "#VirtualMedia.EjectMedia": {
      "target": "/redfish/v1/Managers/bmc/VirtualMedia/ISO0/Actions/VirtualMedia.EjectMedia"
    }
  },
  "MediaTypes": ["CD", "USBStick"],
  "Image": "https://192.168.0.1/Images/os.iso",
  "ImageName": "Os",
  "ConnectedVia": "URI",
  "Inserted": true,
  "WriteProtected": false,
  "@odata.context": "/redfish/v1/$metadata#VirtualMedia.VirtualMedia",
  "@odata.id": "/redfish/v1/Managers/BMC/VirtualMedia/ISO0",
  "Oem": {
    "OpenBMC": {
      "@odata.type": "#OemVirtualMedia.v1_0_0.VirtualMedia",
      "WebSocketEndpoint": "/nbd/0"
    }
  }
}

代理模式和传统模式的架构看起来很相似。以下是一些关键区别:

Field Name Proxy Mode Legacy Mode Comment
InsertMedia N/A action as described by DMTF spec Action can return Task object if process is time consumming
Image N/A image location
ImageName N/A image name
ConnectedVia “Applet” as described by DMTF spec applies only for connected media
TransferMethod “Stream” “Stream” “upload” is not supported by design
TransferProtocolType “OEM” as described by DMTF spec
虚拟媒体 OEM 扩展

虚拟媒体模式适用于传统模式,其中镜像由用户通过 Redfish 操作直接提供,整个连接在服务和 Web 服务器之间进行处理。

对于代理模式,nbd数据由客户端 Web 浏览器提供。为了建立连接,客户端需要有关 Web 服务器创建的 WebSocket 位置的信息。此值作为每个项目的OEM“WebSocketEndpoint”属性公开。

不活动超时

虚拟媒体支持不活动超时,这将在一定时间内的不活动后断开虚拟媒体连接。由于nbdclient具有缓存图像的机制,同时内核还具有块设备的home buffer机制,因此想法是在USBGadget驱动程序上准备一个补丁,该补丁将在/proc/USBGadget/lun.X文件下写入USB gadget统计信息。虚拟媒体应用程序将观察这些统计信息。

虚拟媒体服务

虚拟媒体服务是一个独立的应用程序,将与DBus共存。它将从配置json文件初始化,并公开所有可用于提供虚拟媒体对象的功能。虚拟媒体负责:

  • 将当前虚拟媒体配置公开给DBus用户。
  • 为代理连接生成nbdclient,并监视其生命周期。
  • 为CIFS/HTTPS连接生成nbdkit,并监视其生命周期。
  • 监视uDEV以了解所有与NBD相关的块设备更改,并相应地配置/取消配置USB Gadget。
  • 监视NBD设备的不活动时间以支持不活动超时。

配置

在进程启动时,虚拟媒体读取其配置文件,其结构如下:

"InactivityTimeout": 1800,              # Timeout of inactivity on device in seconds, that will lead to automatic disconnection
"MountPoints": {
    "ISO0": {
        "EndpointId": "/nbd/0",         # bmcweb endpoint (URL) configured for this type of connection
        "Mode": 0,                      # 0 - Proxy Mode, 1 - Legacy Mode
        "NBDDevice": "/dev/nbd0",       # nbd endpoint on device usually matches numeric value with EndpointId
        "UnixSocket": "/tmp/nbd.sock",  # defines which Unix socket will be occupied by connection
        "Timeout": 30,                  # timeout in seconds passed to nbdclient
        "BlockSize": 512,               # Block size passed to nbdclient
    }
},

DBus Interface

虚拟媒体将公开以下对象结构。所有对象路径都是上面描述的配置文件的表示形式。

/xyz/openbmc_project/VirtualMedia/Proxy/ISO0
/xyz/openbmc_project/VirtualMedia/Proxy/1
/xyz/openbmc_project/VirtualMedia/Legacy/0
/xyz/openbmc_project/VirtualMedia/Legacy/1

每个对象都将实现xyz.openbmc_project.VirtualMedia.Process接口,该接口将定义如下:

Name type input return description
Active Property - BOOLEAN True, if object is occupied by active process, False otherwise
ExitCode Property - INT32 If process terminates this property will contain returned exit code

每个对象还将在xyz.openbmc_project.VirtualMedia.MountPoint下公开其自身的配置(所有属性均为只读)。

Name type input return description
EndPointId Property - STRING As per configuration
Mode Property - BYTE As per configuration
Device Property - STRING As per configuration
Socket Property - STRING As per configuration
Timeout Property - UINT16 As per configuration
BlockSize Property - UINT16 As per configuration
RemainingInactivityTimeout Property - UINT16 Seconds to drop connection by server, for activated endpoint, 0 otherwise
ImageURL Property - STRING URL to mounted image
WriteProtected Property - BOOLEAN ‘True’, if the image is mounted as read only, ‘False’ otherwise

每个对象还公开了xyz.openbmc_project.VirtualMedia.Stats下的统计数据接口(所有属性均为只读):

Name type input return description
ReadIO Property - UINT64 Number of read IOs since image mounting
WriteIO Property - UINT64 Number of write IOs since image mounting

根据对象路径的不同,对象将公开不同的接口以挂载映像。

挂载可能是一个耗时的任务,因此必须引入事件驱动的机制。挂载和卸载调用将触发异步操作,并立即结束,给出包含任务完成状态的适当信号。

对于代理模式,其接口为xyz.openbmc_project.VirtualMedia.Proxy,定义如下:

Name type input return description
Mount Method - BOOLEAN Perform an asynchronous operation of mounting to HOST on given object.
Unmount Method - BOOLEAN Perform an asynchronous operation of unmount from HOST on given object
Completion Signal - INT32 Returns 0 for success or errno on failure after background operation completes

对于传统模式,其接口为xyz.openbmc_project.VirtualMedia.Legacy,定义如下:

Name type input return description
Mount Method STRING BOOLEAN Perform an asynchronous operation of mounting to HOST on given object, with location given as STRING parameter
Mount Method STRING BOOLEAN VARIANT BOOLEAN Perform an asynchronous operation of mounting to HOST on given object, with parameters: STRING : url to image. It should start with either smb:// or https:// prefix BOOLEAN : RW flag for mounted gadget (should be consistent with remote image capabilities) VARIANT : file descriptor of named pipe used for passing null-delimited secret data (username and password). When there is no data to pass -1 should be passed as INT
Unmount Method - BOOLEAN Perform an asynchronous operation of unmounting from HOST on given object
Completion Signal - INT32 Returns 0 for success or errno on failure after background operation completes

挂载和卸载操作会在异步操作启动时返回true,在预检查遇到错误时返回false。它们还可以指示适当的DBus错误。

Alternatives Considered

Existing implementation in OpenBMC

Impact

Shall not affect usability of current Virtual Media implementation

Testing

TBD

https://github.com/openbmc/docs/blob/master/designs/virtual-media.md

数据流如下:

  1. 用户在客户端浏览器中打开Virtual Media页面,发送HTTP请求到OpenBMC Virtual Media服务。
  2. OpenBMC Virtual Media服务接收HTTP请求,并通过DBus调用Virtual Media进程。
  3. Virtual Media进程收到请求后,创建一个nbd-client实例,并连接到nbd-server。如果需要,还会生成代理地址和Websocket URL,并将它们返回到客户端浏览器中。
  4. 一旦连接建立,客户端浏览器就可以使用NBD协议从OpenBMC设备中读取/写入块设备的内容。
  5. 当用户在客户端浏览器中断开Virtual Media会话时,会发送HTTP请求到OpenBMC Virtual Media服务来结束会话。
  6. OpenBMC Virtual Media服务通过DBus调用Virtual Media进程,并通知它结束nbd-client实例。
  7. Virtual Media进程关闭nbd-client实例,并在必要时还会停止nbd-server实例。

在 OpenBMC Virtual Media 的实现中,NBDKit、NBDServer 和 NBDClient 三者的关系如下:

  1. NBDKit 是一个开源工具,用于创建和管理网络块设备 (Network Block Device,简称 NBD)。在 OpenBMC 中,NBDKit 作为 NBDServer 的依赖,用于创建 NBD 服务端并管理 NBD 块设备。
  2. NBDServer 是一个在 OpenBMC 上运行的服务端应用程序,用于将虚拟媒体映像文件提供给客户端。NBDServer 使用 NBDKit 创建 NBD 服务端,并将客户端请求转发给 NBD 块设备。
  3. NBDClient 是一个客户端应用程序,用于连接到 NBDServer 并将 NBD 块设备映射到本地系统。在 OpenBMC Virtual Media 中,NBDClient 运行在客户端的 Web 浏览器中,用于将虚拟媒体映像文件传输到 OpenBMC 并加载到 NBD 块设备中。

因此,NBDKit 是用于创建和管理 NBD 服务端的工具,NBDServer 是运行在 OpenBMC 上的 NBD 服务端应用程序,NBDClient 则是运行在客户端浏览器中的 NBD 客户端应用程序。这三者协同工作,构成了 OpenBMC Virtual Media 的核心组件。

openbmc Dbus----->VirtualMedia 讲解

OpenBMC Virtual Media是一个基于DBus的服务,旨在提供通过网络连接在BMC(Baseboard Management Controller)上虚拟媒体的功能。DBus是一种进程间通信机制,用于在不同进程之间进行消息传递。OpenBMC Virtual Media服务使用DBus作为通信机制,使得其他进程可以通过DBus API调用Virtual Media服务提供的功能。

Virtual Media服务会在DBus上注册一个Object,其他进程可以通过DBus Object Path来访问Virtual Media服务的API。Virtual Media服务的API包括:

  • 设置Virtual Media的配置
  • 获取当前Virtual Media的配置
  • 连接/断开Virtual Media
  • 获取Virtual Media连接的状态

DBus API调用的格式如下:

pythonCopy codeMethodCall("xyz.openbmc_project.VirtualMedia",
            "/xyz/openbmc_project/virtual_media/1",
            "xyz.openbmc_project.VirtualMedia.Process",
            "Mount",
            "s",
            imagePath)

其中,第一个参数表示DBus Service Name,第二个参数表示DBus Object Path,第三个参数表示DBus Interface Name,第四个参数表示调用的方法名,第五个参数表示方法的参数类型,第六个参数表示方法的参数。

Virtual Media服务是通过DBus与其他进程进行通信的,因此,其他进程只需了解DBus API的调用方式即可使用Virtual Media服务提供的功能。

你可能感兴趣的:(OpenBMC,媒体,linux,服务器,c++)