虚拟媒体允许用户通过BMC将给定的ISO/IMG驱动器映像远程挂载到服务器主机。远程驱动器在主机中显示为USB存储设备,并以RO模式或RW模式运行(请记住容器限制和写保护开关)。这甚至可以用于在裸机系统上安装操作系统。本文档重点介绍了一些重定向选项,例如基于浏览器的ISO/IMG映像挂载和远程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秒,可能在某些情况下不足以执行挂载和卸载。
异步响应将在适当的部分中描述。
读者可以注意到,图表中的大多数连接都基于网络块设备。根据Sourceforge项目的描述:
在内核中编译了这个之后,Linux可以将远程服务器用作其块设备之一。每次客户端计算机想要读取/dev/nbd0时,它都会通过TCP向服务器发送一个请求,服务器将回复请求的数据。这可以用于具有低磁盘空间的工作站(甚至是无盘 - 如果您使用initrd)从其他计算机借用磁盘空间。与NFS不同,可以在其上放置任何文件系统。但是(与NFS不同),如果有人将NBD挂载为读/写,则必须确保没有其他人会将其挂载。
– https://nbd.sourceforge.io/
在Virtual Media用例中,它被用于从远程客户端拉取数据,并将其呈现到未挂载到BMC的/dev/nbdXX
设备中。然后通过USB Gadget将块设备提供给Host。
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模式使用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终端点公开。以下是一些示例。
集合中的成员将根据下一节中描述的配置文件定义,并且无论是否插入媒体,都将可见。
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"
}
{
"@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 |
虚拟媒体模式适用于传统模式,其中镜像由用户通过 Redfish 操作直接提供,整个连接在服务和 Web 服务器之间进行处理。
对于代理模式,nbd数据由客户端 Web 浏览器提供。为了建立连接,客户端需要有关 Web 服务器创建的 WebSocket 位置的信息。此值作为每个项目的OEM“WebSocketEndpoint”属性公开。
虚拟媒体支持不活动超时,这将在一定时间内的不活动后断开虚拟媒体连接。由于nbdclient具有缓存图像的机制,同时内核还具有块设备的home buffer机制,因此想法是在USBGadget驱动程序上准备一个补丁,该补丁将在/proc/USBGadget/lun.X文件下写入USB gadget统计信息。虚拟媒体应用程序将观察这些统计信息。
虚拟媒体服务是一个独立的应用程序,将与DBus共存。它将从配置json文件初始化,并公开所有可用于提供虚拟媒体对象的功能。虚拟媒体负责:
在进程启动时,虚拟媒体读取其配置文件,其结构如下:
"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
}
},
虚拟媒体将公开以下对象结构。所有对象路径都是上面描述的配置文件的表示形式。
/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错误。
Existing implementation in OpenBMC
Shall not affect usability of current Virtual Media implementation
TBD
https://github.com/openbmc/docs/blob/master/designs/virtual-media.md
数据流如下:
在 OpenBMC Virtual Media 的实现中,NBDKit、NBDServer 和 NBDClient 三者的关系如下:
因此,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包括:
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服务提供的功能。