Author: Pawel Rapkiewicz pawel.rapkiewicz@intel.com
Primary assignee: None
Other contributors: None
Created: 6/4/2019
Virtual Media allows users to remotely mount given ISO/IMG drive images through BMC to Server HOST. The Remote drive is visible in HOST as USB storage device, and operates in RO mode, or RW mode (keeping in mind container limitations, and write protection switches). This can even be used to install OS on bare metal system. This document focuses on few redirection options, like in-browser ISO/IMG image mounting, and remote CIFS/HTTPS image mounting.
None
Virtual Media splits into two modes of operation, lets call it Proxy, and Legacy.
Both methods inherit from default Redfish/BMCWeb authentication and privileges mechanisms.
The component diagram below shows Virtual Media high-level overview
+------------------+ +----------------------------------+ +-----------------------+ |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 feature supports multiple, simultaneous connections in both modes.
Reader can notice that most connections on diagram are based on Network Block Device. After Sourceforge project description:
With this compiled into your kernel, Linux can use a remote server as one of its block devices. Every time the client computer wants to read /dev/nbd0, it will send a request to the server via TCP, which will reply with the data requested. This can be used for stations with low disk space (or even diskless - if you use an initrd) to borrow disk space from other computers. Unlike NFS, it is possible to put any file system on it. But (also unlike NFS), if someone has mounted NBD read/write, you must assure that no one else will have it mounted.
In Virtual Media use case, it's being used to pull data from remote client, and present it into non BMC mounted /dev/nbdXX
device. Then the block device is being provided to Host through USB Gadget.
Part of Linux kernel that makes emulation of certain USB device classes possible through USB "On-The-Go", if connect appropriately to Host. In Virtual Media case it emulates USB mass storage connected to HOST. The source or redirection is block device created by nbd-client /dev/nbdXX
Proxy Mode uses browser JavaScript and WebSockets support, to create JS NBD Server. Browser is responsible for create HTTPS session, authenticate user, and receive given privileges, then upgrade HTTPS session to WSS, through mechanisms described by RFC6455. Since WSS upgrade, JS application is responsible for handling all required by specification NBD Server commands.
Multiple, simultaneous connections are supported per opening connections on different URIs in HTTPS server. Number of available simultaneous connections is being defined in configuration file described in next chapter.
Encryption for proxy is supported through HTTPS/WSS channel and inherits encryption mechanisms directly from HTTPS server, all data transactions go through bmcweb.
The initialization of connection will look as on diagram:
┌───────┐ ┌──────┐ ┌────────────┐ ┌─────────┐ ┌────┐ ┌─────────┐ │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 │ │ │ │ │ ─────────────────────────────────────────>│ │ │ │ │ │ │ │ │ │ │ Data │ │ │ │ │<─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─>│ │ │ │ │ │ │ │
Legacy Mode uses VirtualMedia schema, defined by DMTF, for mounting external CIFS/HTTPS images. The current implementation supports only stream mounting as for now. In this case Redfish is only used as mechanism for Virtual Media initialization, and is not responsible for data transmission. For data there is a separate component responsible for handling CIFS/HTTPS traffic called NBDkit.
Multiple, simultaneous connections are supported through spawning additional nbkit instances, the number of available instances for CIFS/HTTPS is configured and described in details in next chapter.
Encryption is based on remote storage connection, and follows Intel's Best security practices, as remote server support such (i.e. HTTPS requires SSL, and pure HTTP is not supported, for CIFS protocol version 3.0 allows enabling encryption and that will be provided).
The flow looks like below:
┌───────┐ ┌──────────┐ ┌──────┐ ┌────────────┐ ┌──────┐┌─────────┐┌────┐ ┌─────────┐ │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 │ │ │ │ │ ───────────────────────────────────────────────>│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ Data │ │ │ │ │ │ │ │ <─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─>│
Virtual Media Service will be exposed as Redfish VirtualMedia endpoint as defined by DMTF. Here are some examples.
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", "Members@odata.count": 2, "Members": [ { "@odata.id": "/redfish/v1/Managers/BMC/VirtualMedia/ISO0" } , { "@odata.id": "/redfish/v1/Managers/BMC/VirtualMedia/1" } ], "Oem": { } , "@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", "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" }
Schema will look similar for both Proxy and Legacy Mode. Some key differences as follows:
Field Name | Proxy Mode | Legacy Mode | Comment |
---|---|---|---|
InsertMedia | N/A | action as described by DMTF spec | |
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 |
Virtual Media supports inactivity timeout, which will break Virtual Media connection after certain number of seconds of inactivity. Because nbdclient has mechanism for caching image, also kernel has home buffer mechanisms for block device, the idea is to prepare a patch on USBGadget driver, that will write USB gadget statistics under /proc/USBGadget/lun.X file. Those statistics will be observed by Virtual Media application.
Virtual Media Service is separate application that will coexist on DBus. It will be initialized from configuration json file, and expose all available for provisioning VirtualMedia objects. Virtual Media is responsible for:
Upon process startup, Virtual Media reads its config file, with the following structure:
"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 } },
Virtual Media will expose the following object structure. All object paths are representation of configuration file described above
/xyz/openbmc_project/VirtualMedia/Proxy/ISO0 /xyz/openbmc_project/VirtualMedia/Proxy/1 /xyz/openbmc_project/VirtualMedia/Legacy/0 /xyz/openbmc_project/VirtualMedia/Legacy/1
Each of object will implement xyz.openbmc_project.VirtualMedia.Process
interface, which will be defined as follow:
Name | type | input | return | description |
---|---|---|---|---|
Active | Property | - | BOOLEAN | True , if object is occupied by active process, False otherwise |
ExitCode | Property | - | BYTE | If process terminates this property will contain returned exit code |
Each object will also expose configuration of its own under xyz.openbmc_project.VirtualMedia.MountPoint
(all properties are RO)
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 |
Another interface exposed by each object are stats under xyz.openbmc_project.VirtualMedia.Stats
(all properties are RO):
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 |
Depends on object path, object will expose different interface for mounting image.
For Proxy its xyz.openbmc_project.VirtualMedia.Proxy
, defined as follow:
Name | type | input | return | description |
---|---|---|---|---|
Mount | Method | - | BOOLEAN | Perform a mount to HOST operation on given object |
Unmount | Method | - | BOOLEAN | Perform an unmount from HOST on given object |
For Legacy its xyz.openbmc_project.VirtualMedia.Legacy
, defined as follow:
Name | type | input | return | description |
---|---|---|---|---|
Mount | Method | STRING | BOOLEAN | Perform a mount to HOST operation on given object, with location given as STRING parameter |
Unmount | Method | - | BOOLEAN | Perform an unmount from HOST on given object |
Existing implementation in OpenBMC
Shall not affect usability of current Virtual Media implementation
TBD