1. BMC二次开发¶
1.1. 监控数据获取¶
所有监控数据都存储到主板的 Prometheus 数据库里,可以使用其命令工具 promtool 去获取监控数据。
监控数据是透过 node_exporter 去获取的。
网页的仪表盘定义 json 文件存放在 /var/lib/grafana/dashboards/ 里。
1.1.1. 获取所有子板的即时在线状态¶
$ promtool query instant http://127.0.0.1:9090 node_cluster_up
node_cluster_up{instance="127.0.0.1:9100", job="node", nodename="main", state="android", subnode="sub1-01"} => 1 @[1608772515.659]
node_cluster_up{instance="127.0.0.1:9100", job="node", nodename="main", state="android", subnode="sub1-02"} => 1 @[1608772515.659]
node_cluster_up{instance="127.0.0.1:9100", job="node", nodename="main", state="android", subnode="sub1-03"} => 1 @[1608772515.659]
node_cluster_up{instance="127.0.0.1:9100", job="node", nodename="main", state="android", subnode="sub1-04"} => 1 @[1608772515.659]
...
subnode: 子板编号
state:子板状态
android:子板运行的操作系统为 Android。
linux:子板运行操作系统为 Linux。
netrecovery:子板处于辅助升级系统 netrecovery 状态。
offline:子板离线,无法通过 USB 连接检测到。
online:子板能通过 USB 连接检测到,但无法解析进一步的状态。
loader:子板处于 Loader 状态。
fastboot: 子板处于 Fastboot 状态。
adb:子板被识别为 adb 设备,但暂未识别到其操作系统。
adb_offline: 子板被识别为处于 offline 状态的 adb 设备,无法进行正常 adb 操作。
android_recovery: 子板进入了 Android 的 recovery 系统。
metric:
1.0: 子板处于 android 或 linux 状态。
0.0: 子板处于 offline 状态。
0.5: 子板处于上述状态之外。
1.1.2. 获取主机温度¶
1.1.2.1. A. 获取主板温度(仅R2)¶
通过读取底板上的热敏电阻来获取其温度(单位:摄氏度):
$ promtool query instant http://127.0.0.1:9090 'node_hwmon_temp_celsius{chip=~"platform_ntc.*"}'
node_hwmon_temp_celsius{chip="platform_ntc", instance="127.0.0.1:60101", job="node", nodename="sub1-01", sensor="temp1"} => 34.779 @[1608773513.849]
node_hwmon_temp_celsius{chip="platform_ntc", instance="127.0.0.1:60102", job="node", nodename="sub1-02", sensor="temp1"} => 42.81 @[1608773513.849]
node_hwmon_temp_celsius{chip="platform_ntc", instance="127.0.0.1:60103", job="node", nodename="sub1-03", sensor="temp1"} => 43.305 @[1608773513.849]
...
1.1.2.2. B. 获取主机内环境温度(仅R2)¶
通过读取主机内的 ds18b20 温度传感器的数据来获取主机内的环境温度(单位:摄氏度):
$ promtool query instant http://127.0.0.1:9090 'node_cluster_env_temp_celsius'
1.1.3. 获取风扇的转速(仅R2)¶
单位:RPM (转/分钟)
$ promtool query instant http://127.0.0.1:9090 node_cluster_fan_speed
node_cluster_fan_speed{fan="fan1", instance="127.0.0.1:9100", job="node", nodename="main"} => 7812 @[1607501007.839]
node_cluster_fan_speed{fan="fan2", instance="127.0.0.1:9100", job="node", nodename="main"} => 7936 @[1607501007.839]
...
R2v2 有 10 块能监控转速的风扇。
1.1.4. 获取接入硬盘状态¶
获取硬盘设备名称和型号:
$ promtool query instant http://127.0.0.1:9090 node_cluster_disk_up
node_cluster_disk_up{device="sda", instance="127.0.0.1:9100", job="node", model="ST1000DM010-2EP1", nodename="main"} => 1 @[1609228221.442]
获取硬盘总容量(单位:字节):
$ promtool query instant http://127.0.0.1:9090 node_cluster_disk_bytes_total
node_cluster_disk_bytes_total{device="sda", instance="127.0.0.1:9100", job="node", nodename="main"} => 1000204886016 @[1609228289.651]
获取硬盘已使用空间(单位:字节):
$ promtool query instant http://127.0.0.1:9090 node_cluster_disk_bytes__used
node_cluster_disk_bytes_used{device="sda", instance="127.0.0.1:9100", job="node", nodename="main"} => 121475072 @[1609228366.843]
1.1.5. 获取所有设备的 IP 地址¶
$ promtool query instant http://127.0.0.1:9090 node_network_ipaddr
node_network_ipaddr{device="eth0", instance="127.0.0.1:60101", ipaddr="168.168.101.198", job="node", nodename="sub1-01"} => 1 @[1609396443.993]
node_network_ipaddr{device="eth0", instance="127.0.0.1:60102", ipaddr="168.168.100.180", job="node", nodename="sub1-02"} => 1 @[1609396443.993]
node_network_ipaddr{device="eth0", instance="127.0.0.1:60103", ipaddr="168.168.101.145", job="node", nodename="sub1-03"} => 1 @[1609396443.993]
...
device: 网络接口名称,各个子板仅有一个以太网接口 eth0, 主板有多个。每个网络接口对应一个 IP 地址。
ipaddr:IP 地址,如果尚没有取得 IP 地址,则为 “0.0.0.0”。
nodename:子板 sub 编号,或主板 main。
1.2. 硬件控制¶
1.2.1. 重置子板电源¶
功能: 重置子板电源
描述: 通过操控子板的 RESET 脚来重置子板电源,达到强制重启子板的目的。如果子板没有 RESET 脚,则通过关闭、打开电源来实现。
调用:
命令行可运行: /usr/bin/bmc <子板SUB编号> reset
Web API:
GET http://localhost:7070/api/reset/<子板SUB编号>
1.2.2. 重启子板操作系统¶
功能: 重启子板操作系统
描述: 首先通过 adb reboot 命令来重启系统,如果 10 秒内没有反应,则通过复位电源的方式强行重启子板。
调用:
命令行可运行: /usr/bin/bmc <子板SUB编号> reboot
Web API:
GET http://localhost:7070/api/reboot/<子板SUB编号>
1.2.3. 打开子板电源(仅R2)¶
功能:打开子板电源
描述:通过操控子板的 POWER 脚来打开子板电源。集群服务器开机默认打开所有子板电源。
调用:
命令行可运行: /usr/bin/bmc <子板SUB编号> poweron
Web API:
GET http://localhost:7070/api/poweron/<子板SUB编号>
1.2.4. 关闭子板电源(仅R2)¶
功能:关闭子板电源
描述:通过操控子板的 POWER 脚来关闭子板电源。
调用:
命令行可运行: /usr/bin/bmc <子板SUB编号> poweroff
Web API:
GET http://localhost:7070/api/poweroff/<子板SUB编号>
1.3. 固件升级¶
使用脚本添加固件升级任务:
sudo netrecovery-master queue <固件文件绝对路径> <子板SUB编号> [<子板SUB编号> ...]
例如:
sudo netrecovery-master queue /home/firefly/Firmware/xxx.img sub1-01 sub1-02
查看固件升级进度:
$ promtool query instant http://127.0.0.1:9090 node_cluster_firmware_upgrade_stat
node_cluster_firmware_upgrade_stat{firmware="SR-C11G-3399JD4_Android10_HDMI_201202.img", instance="127.0.0.1:9100", job="node", node="sub02", nodename="main", state="done"} => 100 @[1608795873.055]
node_cluster_firmware_upgrade_stat{firmware="SR-C11G-3399JD4_Android10_HDMI_201202.img", instance="127.0.0.1:9100", job="node", node="sub03", nodename="main", state="done"} => 100 @[1608795873.055]
node: 升级固件的子板编号。
state: preparing: 正在准备;flashing: 正在烧写;done: 已完成;error:出错。
metric: 烧写进度百分比,例如 100 表示已全部完成(100%)。
注意:有可能出现同一块子板有两种不同的 state,这时如果存在 state=”flashing” 则表示子板尚在烧写中,因此更稳妥的办法是,先查 flashing 进度,如果有则在升级中,如果没有则再查是完成还是出错:
$ promtool query instant http://127.0.0.1:9090 'node_cluster_firmware_upgrade_stat{node="sub02",state="flashing"}'
$ promtool query instant http://127.0.0.1:9090 'node_cluster_firmware_upgrade_stat{node="sub02",state=~"done|error"}'
node_cluster_firmware_upgrade_stat{firmware="SR-C11G-3399JD4_Android10_HDMI_201202.img", instance="127.0.0.1:9100", job="node", node="sub02", nodename="main", state="done"} => 100 @[1608796078.37]
1.4. 子板上传下载文件,运行命令¶
以下命令使用 bmc_adb,此脚本是对 adb 命令的包装,使用户可以方便地使用子板编号去操作对应子板,而不用理会实际的子板 adb 序列号。当然,adb 命令也可以使用。
1.5. bmc 命令行工具¶
bmc 命令行工具必须在主板(即结点名称为 main 的设备)的 Shell 终端窗口下运行,当然,远程通过 ssh 连接到主板也可使用。
获取命令帮助:
$ bmc --help
Usage:
bmc list [--offline] [<pattern>]
List all the active nodes usable with adb, optionally matched by pattern
bmc serials
List all the active nodes with coresponding adb serial.
bmc <node> {reset|poweron|poweroff}
Invoke reset, poweron or power off on <node>
bmc <node> state
Show node state
bmc <node> shell [<command>...]
Invoke shell with command.
bmc forall <command> %{node}
1.5.1. 显示 adb 设备列表¶
列出所有在线(adb 成功连接)设备:
$ bmc list
sub03
sub04
sub05
sub06
sub07
sub08
sub09
sub10
列出所有 adb 状态为 offline 的设备:
$ bmc list --offline
1.5.2. 列出子板编号和 adb 序列号的对应关系¶
$ bmc serials
sub02 B09CCSUB02 usb:2-1.2.3
sub03 A8232SUB03 usb:2-1.2.4
sub06 4DE1ESUB06 usb:2-1.2.7
sub07 505C3SUB07 usb:2-1.1.2
sub08 FFBCCSUB08 usb:2-1.4
sub09 710AFSUB09 usb:2-1.1.1
1.5.3. 重置子板的电源¶
$ bmc sub03 reset
okay
1.5.5. 查看子板状态¶
查看子板的明细状态:
# 单个子板
$ bmc sub1-01 state
android
# 所有子板
$ bmc state
main: linux
sub1-01: android
sub1-02: android
...
# 所有状态为 offline 的子板
$ bmc state | grep offline
sub7-01: offline
sub7-02: offline
sub7-03: offline
...
列出 sub3-01 的 adb 状态和 ifconfig 结果:
$ bmc sub3-01
node: sub3-01
state: android
adb_state: device
ifconfig:
eth0 Link encap:Ethernet HWaddr ae:bb:8b:e7:b4:38 Driver rk_gmac-dwmac
inet addr:168.168.100.171 Bcast:168.168.255.255 Mask:255.255.0.0
inet6 addr: fe80::7298:5297:6ab9:7fd0/64 Scope: Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:66181 errors:0 dropped:0 overruns:0 frame:0
TX packets:190 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:4414382 TX bytes:22295
Interrupt:27
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope: Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:715 errors:0 dropped:0 overruns:0 frame:0
TX packets:715 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:885911 TX bytes:885911
1.5.6. 进入子板 shell 或在子板执行命令¶
进入 sub03 的 adb shell:
$ bmc sub03 shell
rk3399_firefly_sr_c11g_jd4:/ $
在 sub03 上运行命令:
$ bmc sub03 shell id
uid=2000(shell) gid=2000(shell) groups=2000(shell),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats),3009(readproc) context=u:r:shell:s0
1.5.7. 批量执行命令¶
bmc
提供了可以批量执行命令的快捷方式 bmc forall
,此命令从标准输入读入子板编号,替换命令行上的 %{node}
参数再执行命令。例如:
批量获取子板 adb 状态,%{node}
会被替换为实际的设备结点:
$ echo sub03 sub04 | bmc forall adb -s %{node} get-state
>>> adb -s sub03 get-state
device
>>> adb -s sub04 get-state
device
为了简化操作,bmc forall
对 reset
, poweron
和 poweroff
命令提供了快捷支持。
批量重置子板电源:
$ echo sub03 sub04 | bmc forall reset
>>> bmc sub03 reset
okay
>>> bmc sub04 reset
okay
# 等价于
$ echo sub03 sub04 | bmc forall bmc %{node} reset
另外,bmc forall
也对 shell
命令还提供了简化。
例如,批量获取子板 Android 序列号:
$ echo sub03 sub04 | bmc forall shell getprop ro.serialno
>>> bmc sub03 shell getprop ro.serialno
A82328MDDT
>>> bmc sub04 shell getprop ro.serialno
2E8178MDDT
# 等价于
$ echo sub03 sub04 | bmc forall bmc %{node} shell getprop ro.serialno
1.5.8. 查询监控数据¶
promtool
是 Prometheus
提供的命令行工具,可用于查询数据库等功能。
bmc query
是 promtool
的快捷查询方式,不加参数默认返回 node_cluster_up
的值:
$ bmc query
node_cluster_up{instance="127.0.0.1:9100", job="node", nodename="main", state="android", subnode="sub1-01"} => 1 @[1609227870.112]
...
也可以直接指定需要查询的参数,参数请参阅 node_exporter
文档和 BMC 的 API 说明。
以下是插入硬盘后查询其状态:
$ bmc query node_cluster_disk_up
node_cluster_disk_up{device="sda", instance="127.0.0.1:9100", job="node", model="ST1000DM010-2EP1", nodename="main"} => 1 @[1609228042.393]
1.5.9. 写入序列号,以太网 MAC 地址等(v1.3 新增)¶
命令格式:
bmc {main|sub??} vendor <type> [<data>]
<type>
:sn: 对应 VENDOR_SN_ID,用来修改 Android 系统的 ro.serialno 属性。
lan: 对应 VENDOR_LAN_MAC_ID, eth0 网卡的 MAC 地址,设置后重启生效。
更多类型请在主控板运行:
/usr/share/bmc/vendor_storage_linux -h
。
<data>
: 该参数可选,若提供则写入,否则是读取。
例如,要对 sub8-09
写入 MAC 地址 ae:0e:fb:84:0f:c2
:
# 写入
$ bmc sub8-09 vendor lan ae0efb840fc2
# 读取
$ bmc sub8-09 vendor lan
该命令实际是对 /usr/share/bmc/vendor_storage_linux
(Linux 系统) 和 /usr/share/bmc/vendor_storage_android
(Android 系统) 的包装,更高级的用法可以直接调用原始命令。
1.5.10. 列出主子板的软硬件版本号(v1.3 新增)¶
列出主板和所有子板的软硬件版本号:
$ bmc versions
main linux OS:Ubuntu18.04.4 HW:v1.0
sub1-01 android OS:CLUSTER-SERVER-R2_20210118 HW:v1.0
sub1-02 android OS:CLUSTER-SERVER-R2_20210118 HW:v1.0
sub1-03 android OS:CLUSTER-SERVER-R2_20210118 HW:v1.0
...