BMC二次开发 监控数据获取 所有监控数据都存储到主板的 Prometheus 数据库里,可以使用其命令工具 promtool 去获取监控数据。 监控数据是透过 node_exporter 去获取的。 网页的仪表盘定义 json 文件存放在 /var/lib/grafana/dashboards/ 里。 获取所有子板的即时在线状态 $ 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: 子板处于上述状态之外。 获取主机温度 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] ... B. 获取主机内环境温度(仅R2) 通过读取主机内的 ds18b20 温度传感器的数据来获取主机内的环境温度(单位: 摄氏度): $ promtool query instant http://127.0.0.1:9090 'node_cluster_env_temp_celsius' 获取风扇的转速(仅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 块能监控转速的风扇。 获取接入硬盘状态 获取硬盘设备名称和型号: $ 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] 获取所有设备的 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。 硬件控制 重置子板电源 功能: 重置子板电源 描述: 通过操控子板的 RESET 脚来重置子板电源,达到强制重启子板的目的。 如果子板没有 RESET 脚,则通过关闭、打开电源来实现。 调用: 命令行可运行: /usr/bin/bmc <子板SUB编号> reset Web API:GET http://localhost:7070/api/reset/<子板SUB编号> 重启子板操作系统 功能: 重启子板操作系统 描述: 首先通过 adb reboot 命令来重启系统,如果 10 秒内没有反应,则通过 复位电源的方式强行重启子板。 调用: 命令行可运行: /usr/bin/bmc <子板SUB编号> reboot Web API:GET http://localhost:7070/api/reboot/<子板SUB编号> 打开子板电源(仅R2) 功能:打开子板电源 描述:通过操控子板的 POWER 脚来打开子板电源。集群服务器开机默认打开所 有子板电源。 调用: 命令行可运行: /usr/bin/bmc <子板SUB编号> poweron Web API:GET http://localhost:7070/api/poweron/<子板SUB编号> 关闭子板电源(仅R2) 功能:关闭子板电源 描述:通过操控子板的 POWER 脚来关闭子板电源。 调用: 命令行可运行: /usr/bin/bmc <子板SUB编号> poweroff Web API: GET http://localhost:7070/api/poweroff/<子板SUB编号> 固件升级 使用脚本添加固件升级任务: 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] 子板上传下载文件,运行命令 以下命令使用 bmc_adb,此脚本是对 adb 命令的包装,使用户可以方便地使用 子板编号去操作对应子板,而不用理会实际的子板 adb 序列号。当然,adb 命 令也可以使用。 从主板上传文件到子板 在主板上运行: $ bmc_adb -s sub01 push home.json /data/local/tmp 从子板下载文件到主板 在主板上运行: $ bmc_adb -s sub01 pull home.json /data/local/tmp 在子板运行特定命令 在主板上运行: $ bmc_adb -s sub01 shell ifconfig bmc 命令行工具 bmc 命令行工具必须在主板(即结点名称为 main 的设备)的 Shell 终端窗口下 运行,当然,远程通过 ssh 连接到主板也可使用。 获取命令帮助: $ bmc --help Usage: bmc list [--offline] [] List all the active nodes usable with adb, optionally matched by pattern bmc serials List all the active nodes with coresponding adb serial. bmc {reset|poweron|poweroff} Invoke reset, poweron or power off on bmc state Show node state bmc shell [...] Invoke shell with command. bmc forall %{node} 显示 adb 设备列表 列出所有在线(adb 成功连接)设备: $ bmc list sub03 sub04 sub05 sub06 sub07 sub08 sub09 sub10 列出所有 adb 状态为 offline 的设备: $ bmc list --offline 列出子板编号和 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 重置子板的电源 $ bmc sub03 reset okay 打开、关闭子板电源(仅R2) 关闭子板电源: $ bmc sub1-01 poweroff okay 打开子板电源: $ bmc sub1-01 poweron okay 查看子板状态 查看子板的明细状态: # 单个子板 $ 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 进入子板 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 批量执行命令 "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 查询监控数据 "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] 写入序列号,以太网 MAC 地址等(v1.3 新增) 命令格式: bmc {main|sub??} vendor [] : sn: 对应 VENDOR_SN_ID,用来修改 Android 系统的 ro.serialno 属 性。 lan: 对应 VENDOR_LAN_MAC_ID, eth0 网卡的 MAC 地址,设置后重启生 效。 更多类型请在主控板运行:/usr/share/bmc/vendor_storage_linux -h。 : 该参数可选,若提供则写入,否则是读取。 例如,要对 "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 系统) 的包装,更高级 的用法可以直接调用原始命令。 列出主子板的软硬件版本号(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 ...