# Redfish

> Redfish 驱动参考：到 BMC 的 HTTPS 连接、资源路径加 JSON 指针的寻址、读取、PATCH 写入和类型。

Redfish 驱动读写 **DMTF Redfish** 管理服务，也就是服务器 BMC（基板管理控制器）、机箱和其他数据中心硬件为带外管理暴露出来的那套 REST API。这是一个普通的客户端模式驱动，**由 Ganter Lab 连到仪器上**，而传输永远是 **HTTPS**：加固过的 BMC 只暴露这一种，驱动也绝不会自己降级到普通 HTTP。

这样读到的典型的点有：电源状态、安全启动状态、机箱和管理器的健康状况、固件版本，以及热管理资源里的温度和风扇读数。

## 连接字段 {#connection-fields}

| 字段 | 它是什么 | 格式 | 默认值 |
|---|---|---|---|
| 主机 | Redfish 服务的主机名或 IP 地址。 | 主机名或 IP | 空 |
| 端口 | 服务应答所在的端口。管理控制器通常在 443 上应答，发布在别处的服务在这里说明。框留空时 443 以灰色显示，服务就通过这个端口连上；以 0 保存的设备也是这样显示的。 | 1 到 65535 | 443 |
| 用户名 | 用于 **HTTP Basic** 认证的那个 BMC 账户。留空会让请求以匿名身份发出，而受保护的服务会用一个授权错误来回答它。 | 自由文本 | 空 |
| 密码 | 和用户名配对的密码。在静态存储时按 Windows 用户保护，所以配置数据库从不保存明文值；在别的 Windows 账户下输入的密码会显示为读不出来，必须重新输入一次。 | 自由文本 | 空 |

连上时，驱动通过读服务根（`/redfish/v1/`）来核实这个服务。BMC 的 TLS 证书在 Windows 信任它，或你在本驱动页面的[现场设备访问](#equipment-access)里批准了这份证书本身时被接受：BMC 出厂自带的自签名证书不需要在 Windows 里安装任何东西。连接失败时，事件页面和当天的日志文件会说明原因，并把底层错误附在后面，这样密码被驳回和证书在等待批准才分得开。

轮询间隔可以配置：设备的默认值（1000 毫秒）适用于每一个没有自己另作规定的点位。

## 点位寻址 {#tag-addressing}

Redfish 的点位靠一条**资源路径**，加上一个可选的、指向那个资源返回的文档里的 **JSON 指针**来寻址：

| 字段 | 作用 | 取值 | 默认值 |
|---|---|---|---|
| 资源路径 | 要 GET 的那个 Redfish 资源相对服务根的路径，例如 `redfish/v1/Chassis/1/Thermal`。 | 自由文本（必填） | 空 |
| JSON 指针（留空 = 整份文档） | 一个 RFC 6901 指针，选中返回的 JSON 里的某一个字段，例如 `/Temperatures/0/ReadingCelsius`。数组元素按下标寻址；字段名里的 `/` 用 `~1` 转义，`~` 用 `~0` 转义。开头少了 `/` 会替你补上。留空则把整份文档作为文本返回。 | JSON 指针或留空 | 留空 |

拼好的地址的几个例子（作为总线来源预览以只读方式显示）：

- `redfish/v1/Systems/1#/PowerState`：系统的电源状态，一个字符串。
- `redfish/v1/Chassis/1/Thermal#/Temperatures/0/ReadingCelsius`：第一个热传感器，一个数字。
- `redfish/v1/Systems/1/SecureBoot#/SecureBootEnable`：安全启动，一个布尔量。

读取时，驱动 GET 这个资源、解析 JSON、顺着指针走下去，再把结果转换成点位声明的数据类型。一个在文档里什么都没点到的指针，以及一个文档里存的是 JSON `null` 的字段，两者都读作没有值：点位转为质量不可用，由它的读取失败策略决定呈现什么，而不是让 `null` 这个词作为一次好的读数进来。不是 JSON 的响应会被直接按声明的类型解析。服务返回一个在成功范围之外的状态，那是服务在拒绝这次读取：点位同样转为质量不可用，它的原因会点名那个状态，以及服务随它发来的错误文档里的一小段摘录（`HTTP 404 Not Found: …`）。其他没有值的读取也会说出原因：没有资源路径的点位、在文档里什么都没点到的指针、存为 `null` 的字段（各自点名资源和指针），以及读不成声明类型的响应。一个完全不答的服务是设备的连接失败：设备会报告它并重新连接，它的点位会指向这台设备。点位红色那一行用工作站的语言说出这样的状态，401、403 和 404 还附上含义；设备红色那一行在每次尝试时说明它的连接为什么失败，是端口拒绝还是 401 这样的状态；服务自己的原话留在事件页面。

## 写入 {#writes}

读写方式可写的点位会对被寻址的那个字段发 PATCH：驱动构造出覆盖指针那条路径的最小 JSON 文档（对 `/Parent/Child` 来说就是 `{"Parent":{"Child":<value>}}` 这个请求体），并把它发到那个资源上。由此有两条约束：

- 写入**必须有 JSON 指针**。整份文档的点位（指针留空）没法被写：你还在编辑的时候，点位面板就拒绝这种组合，说这个字段缺了；而一次绕过去、真发到服务的尝试会失败，原因写进诊断日志。
- 什么可写由 BMC 说了算；服务驳回的 PATCH 会得到一个答复，里面有状态，以及服务随它发来的错误文档里的一小段摘录（`HTTP 400 Bad Request: …`），写入这个值的一方读得到原因。

和别处一样，你在点位写入框里打的是工程值，原始值上总线之前会先把这个点位的转换环节反过来走一遍，见 [Connector](connector) 页面。

## 支持的数据类型 {#supported-data-types}

Boolean、Int32、Int64、Float、Double 和 String。请挑和那个 JSON 字段对得上的类型：像 `SecureBootEnable` 这样的标志用布尔，读数用数字，像 `PowerState` 或 `Health` 这样的状态用字符串。

## 命令 {#commands}

一个 Redfish 服务会为它能被要求做的每一件事发布一个 action，各自挂在它所作用的那个资源下面的路径上。工作站不去猜它们，因为只有硬件自己的文档才说得清哪些存在：你在设备上声明它们，位置是它页面上的**命令**卡片。每一条命令带一个名称、一条 action 路径（`redfish/v1/Systems/1/Actions/ComputerSystem.Reset`），以及可选的、它所接收的那一个值的名字（`ResetType`）；行上的“运行”把它发出去，服务答了什么会报告回来。一条命令同时也成为这台设备在本工作站自己的 OPC UA 地址空间里的一个方法，所以任何能调用方法的东西都能下发它。

值作为请求体发出去。已经是 JSON 的值原样发出；其余一切都按 `{"<声明的名称>": "<值>"}` 发出，那正是 Redfish 自己的 reset action 所要求的形状。

服务驳回的 action 会得到一个答复，里面有状态，以及服务随它发来的错误文档里的一小段摘录（`HTTP 400 Bad Request: …`），用的是和被驳回的写入一样的说法，这台设备上别的什么都不受它打扰。

## 设备发现 {#discovery}

**发现设备**按钮读的是一个服务：把它的地址填进驱动页面的“扫描范围”卡片（`https://bmc-host`，或者厂商文档给的那个地址），扫描就走一遍那个服务的第一个 system、manager 和 chassis，把设备连同那些点一起提供出来，可以直接添加。扫描是走 HTTPS 且不带凭据去读的，因为它跑的时候那台该拿着凭据的设备还不存在，所以一个对每次请求都要求认证的服务什么都不会回答，那就改为手工添加。Redfish 自己的 SSDP 发现需要 UDP 组播，而进程内的驱动不做这个，所以广播找不到任何东西：扫描读的就是你给它的那个地址。

已经有的 Redfish 设备可以在自己的页面上找出它的点：“点位”卡片标题栏里的**发现点位**用设备的用户名和密码登录，走一遍同样的资源，所以对每次请求都要求认证的服务也会回答；它只列出设备还没有点位的点（见[发现一台设备的点位](connector-discovery#discovering-a-devices-tags)）。

## 现场设备访问 {#equipment-access}

BMC 通常用它自己的证书应答，这份证书是自签名的或由厂商颁发，Windows 中已安装的任何根证书都不为它担保。无需在这台计算机上安装那个根证书。第一次连接会被拒绝，设备在树里和它的页面上显示**正在等待证书批准**，页面上的**查看证书**按钮会在那份证书上打开这张卡片；证书则在 Redfish 驱动页面末尾的**现场设备访问**里等你决定。这张卡片和 OPC UA 驱动页面上的是同一张。

| 分组 | 列出什么 | 你能做什么 |
|---|---|---|
| 等待批准 | 每一份被拒绝的证书，按它自称的名字列出：它的 SHA-256 指纹、遇到它的地址、最后一次尝试的时间和次数，以及详情（主体、颁发者、域名、有效期）。设备的**查看证书**打开的那一份会标为“已选中待审核”。 | **批准**从下一次连接尝试起接受这份证书。**阻止**继续拒绝它，且不再在这里列出。**丢弃所有待处理的证书**清空列表，什么也不批准、不阻止。 |
| 已批准的现场设备 | 你批准或导入的证书，连同谁在何时做的决定，以及每份证书最后一次被遇到的地址。 | **撤回批准**关闭连接，并把证书放回列表。**导入证书**在第一次连接之前批准一份你手头已有的公开证书文件（.der、.cer、.crt 或 .pem）。 |
| 被阻止的现场设备 | 你阻止的证书。被阻止的证书即使受 Windows 信任也会被拒绝。 | **解除阻止**把证书放回列表，但不批准它。 |

批准之前，请与管理该服务器的人核对指纹。批准只接受这一份证书，而且只在它的有效期内；它代替 Windows 缺少的根证书和证书上写的名字，所以按 IP 地址连接的 BMC，即使证书上写的是别的名字也能连上，而证书的其他方面一概不放宽。如果现场设备在你批准过证书的地址上换出另一份证书（证书续期、更换控制器等），读取就会停止，新证书在这里等待，工作站会带着**审核**按钮提示“证书已更换：`<名称>`”。Windows 已经信任的证书照旧被接受，永远不会出现在这里；没有任何东西会被自动批准。

驱动自己的失败会说明原因，而不是一个没有名字的 TLS 错误：“这台现场设备的证书（指纹的前 16 个字符）正在 Redfish 驱动页面的‘现场设备访问’里等待你的批准。批准之后就开始读取。”被阻止的则显示“……在本工作站已被阻止。请在 Redfish 驱动页面的‘现场设备访问’里审核它。”超出有效期、已吊销或签名损坏的证书会以这个原因被拒绝，且永远不会被列出，因为批准也不能让它变得可靠。无论从“扫描范围”卡片还是从设备页面上的**发现点位**扫描这个 BMC，都遵循同样的决定：陌生的证书会以这句话结束扫描，并在这里等待。

这些决定保存在工作站数据文件夹的 `ua\pki\redfish` 下，重启后依然有效。操作按钮只对能配置 Connector 的角色显示，而且只在工作站自己的窗口里生效：其他设备上的浏览器只能查看卡片、不能修改，也没有任何代理工具能批准证书（`connector_browse` 用 `awaitingCertificate` 标出正在等待的设备）。列表最多保留 100 份等待批准的证书；列表满了以后，新的证书仍会被拒绝但不会列出，卡片会说明这一点。
