Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【功能增强】改善Web界面的数据显示,加上IPMI风扇信息 #67

Open
lurenJBD opened this issue Jan 6, 2023 · 1 comment

Comments

@lurenJBD
Copy link

lurenJBD commented Jan 6, 2023

非常抱歉没有按格式汇报,但这并非bug,只是我个人折腾后发一下,看看大家是否也有这样类似的需求。

一、改进CPU温度&频率 在Web端的显示效果

参考:Proxmox VE 顯示 CPU 當下的溫度 | BUBU 知識庫 & 秉迅資訊.Studio (freedomstu.com)

温度数据是通过lm-sensors获取,pvetools脚本会创建/usr/bin/s.sh 把获取的数据json化,然后再由PVE 的Node.js进行处理。

但Node.js也能用正则表达式来处理lm-sensors的数据。这也是我在看完上面那篇参考后才知道,所以就提及一下

使用的PVE版本:7.3-4

如果没使用过脚本进行配置显示频率温度的,先看这个部分,如果有用脚本配过,可以直接跳到第4步

第1步:安装 lm-sensors

apt install -y lm-sensors

第2步:加载相关的传感器模块

sensors-etect --auto

第3步:查看当前传感器的信息

sensors

正常情况下会有温度信息显示
image

第4步:创建显示频率的脚本,这里是直接用了pvetools里的脚本内容,非原创,感谢!

nano /usr/bin/GetCpuFrequency.sh

将以下内容复制进去

#!/usr/bin/bash
echo '{'$(lscpu|grep MHz|sed 's/CPU\ /CPU-/g'|sed 's/\ MHz/-MHz/g'|sed 's/\ //g'|sed 's/^/"/g'|sed 's/$/"\,/g'|sed 's/\:/\"\:\"/g'|awk 'BEGIN{ORS=""}{print $0}'|sed 's/\,$//g')'}'

其实我尝试过使用脚本的方式,直接把命令写到Nodes.pm之中,结果就是 Web界面会一直卡在加载中

第5步:编辑 /usr/share/perl5/PVE/API2/Nodes.pm

 nano /usr/share/perl5/PVE/API2/Nodes.pm 

在 第404行 后面添加内容,如果查找麻烦可以先把文件下载到本地用VSCode等文本编辑软件查找 PVE::pvecfg::version_text();

	$res->{pveversion} = PVE::pvecfg::package() . "/" .
	    PVE::pvecfg::version_text();

	$res->{thermalstate} = `sensors`; # 添加这一行
        $res->{cpufrequency} = `/usr/bin/GetCpuFrequency.sh`; # 添加这一行

	my $dinfo = df('/', 1);     # output is bytes

	$res->{rootfs} = {
	    total => $dinfo->{blocks},
	    avail => $dinfo->{bavail},
	    used => $dinfo->{used},
	    free => $dinfo->{blocks} - $dinfo->{used},
	};

第6步:编辑/usr/share/pve-manager/js/pvemanagerlib.js

nano /usr/share/pve-manager/js/pvemanagerlib.js

在 第38526行 修改内容,可以通过查找alias: 'widget.pveNodeStatus' 快速定位。【记得清理注释内容,会报错】

修改这个内容是为了让状态框架能宽一点,显示更多的信息

Ext.define('PVE.node.StatusView', {
    extend: 'PVE.panel.StatusView',
    alias: 'widget.pveNodeStatus',

    height: 320, # 将这个预设的 300 改为 320
    bodyPadding: '20 15 20 15',

    layout: {
	type: 'table',
	columns: 2,
	tableAttrs: {
	    style: {
		width: '100%'
	    }
	}

在 第38637行 修改内容 可以通过查找textField: 'pveversion' 快速定位。【记得清理注释内容,会报错】

  {
	    itemId: 'version',
	    colspan: 2,
	    printBar: false,
	    title: gettext('PVE Manager Version'),
	    textField: 'pveversion',
	    value: ''
  }, # 这里需要补充一个 , 号不然会出问题
# 增加以下内容
    {
		itemId: 'frequency',
		colspan: 2,
		printBar: false,
		title: gettext('CPU 频率'),
		textField: 'cpufrequency',
		renderer:function(value){
			var d = JSON.parse(value);
			f0 = d['CPU-MHz'];
			f1 = d['CPU-min-MHz'];
			f2 = d['CPU-max-MHz'];
			return  `实时(Cur): ${f0} MHz | 最小(min): ${f1} MHz | 最大(max): ${f2} MHz `;
		}
 	},
	{
		itemId: 'thermal',
		colspan: 2,
		printBar: false,
		title: gettext('CPU 温度'),
		textField: 'thermalstate',
		renderer:function(value){
			const p0 = value.match(/Package id 0.*?\+([\d\.]+)Â/)[1];
			const c0 = value.match(/Core 0.*?\+([\d\.]+)Â/)[1];
			const c1 = value.match(/Core 1.*?\+([\d\.]+)Â/)[1];
			const c2 = value.match(/Core 2.*?\+([\d\.]+)Â/)[1];
			const c3 = value.match(/Core 3.*?\+([\d\.]+)Â/)[1];
			return `Package: ${p0} ℃ | Core 0: ${c0} ℃ | Core 1: ${c1} ℃ | Core 2: ${c2} ℃ | Core 3: ${c3} ℃`
		}
	}

第7步:重启 pveproxy 服务

systemctl restart pveproxy

实际效果一览:

如果没生效,记得先清除网页缓存,或者使用Edge的InPrivate模式。

image
将宽度设置320可以把存储库状态给挡住,并且不像之前那样会有一大块的留白。

二、通过IPMI获取风扇转速 并 添加到Web界面上

首先需要主板支持IPMI才能实现这一功能,如果没有,那可以直接跳过。

第1步:安装 ipmitool

apt install -y ipmitool

验证一下能否获取风扇信息

ipmitool sdr type Fan

image

第2步:创建脚本,参考了前面的脚本,实现了输出json格式的数据

nano /usr/bin/GetFanSpeed.sh

粘贴以下内容到脚本中,记得要去修改为自己的BMC信息!!!【注意!此操作存在一定的安全风险,请熟知!!!】

#!/usr/bin/bash
echo '{'$(ipmitool -H <BMC IP地址> -U <BMC 用户名> -P <BMC 用户密码> sdr type Fan | grep RPM | awk -F"|" '{gsub(/ /,"",$1); gsub(/ /,"",$5); gsub(/RPM/,"",$5); print "\""$1"\":\""$5"\","}' | tr -d '\n' | sed '$ s/.$//')'}'

这里必须说一下,为什么需要使用参数去指定BMC信息。
因发现面板 www-date 账号权限不够,不能通过本地来访问IPMI,所以必须要指定BMC信息的才能实现正常的访问

原本在Shell里以root账户执行以下命令是没问题的

echo '{'$(ipmitool sdr type Fan | grep RPM | awk -F"|" '{gsub(/ /,"",$1); gsub(/ /,"",$5); gsub(/RPM/,"",$5); print "\""$1"\":\""$5"\","}' | tr -d '\n' | sed '$ s/.$//')'}'

可以获得正确的信息反馈
image
但实际的界面是无内容显示
image

虽然这样做解决了问题,但存在一定的安全隐患,毕竟明文记录了 IPMI 的管理员信息!【超微的IPMI非管理员账户获取不了风扇信息】

接着我考虑去使用加密shell,避免密码泄露。

参考:Shell脚本加密与解密 - 腾讯云开发者社区-腾讯云 (tencent.com)

直接说结论吧。 结果就是

使用gzexe 能加密成功并且脚本可以正常运行,但这样会导致PVE的web页面刷新变得非常慢!
而且gzexe的加密很弱,几步操作就能解密【本质就是压缩】

使用shc 加密后的文件无法运行

后面想到,如果有人都拿到PVE的root权限了,那这个IPMI密码似乎也阻挡不了什么,毕竟在root账号下,ipmitool直接就能免密码进行操作了。

虽然尚不清楚PVE的Web页面中是否会有bug能让攻击者获取到这个脚本的内容,但我也没打算把PVE的Web页面开放到公网上去。毕竟是最底层的系统,想要远程访问还是有很多安全办法的。

接着的操作就很简单了,基本上就是照搬上面。

第3步:编辑 /usr/share/perl5/PVE/API2/Nodes.pm

在 第404行 后面添加内容,如果查找麻烦可以先把文件下载到本地用VSCode等文本编辑软件查找 PVE::pvecfg::version_text(); 【记得清理注释内容,会报错】

	$res->{pveversion} = PVE::pvecfg::package() . "/" .
	    PVE::pvecfg::version_text();

	$res->{thermalstate} = `sensors`; # 获取CPU温度信息
        $res->{cpufrequency} = `/usr/bin/GetCpuFrequency.sh`; # 获取CPU频率信息
        $res->{getfanspeed} = `/usr/bin/GetFanSpeed.sh`; # 新添加一行,获取风扇信息

	my $dinfo = df('/', 1);     # output is bytes

	$res->{rootfs} = {
	    total => $dinfo->{blocks},
	    avail => $dinfo->{bavail},
	    used => $dinfo->{used},
	    free => $dinfo->{blocks} - $dinfo->{used},
	};

第4步:编辑 /usr/share/pve-manager/js/pvemanagerlib.js
在 第38637行 修改内容 可以通过查找textField: 'pveversion' 快速定位。【记得清理注释内容,会报错!】

  {
	    itemId: 'version',
	    colspan: 2,
	    printBar: false,
	    title: gettext('PVE Manager Version'),
	    textField: 'pveversion',
	    value: ''
  }, 
    {
		itemId: 'frequency',
		colspan: 2,
		printBar: false,
		title: gettext('CPU 频率'),
		textField: 'cpufrequency',
		renderer:function(value){
			var d = JSON.parse(value);
			f0 = d['CPU-MHz'];
			f1 = d['CPU-min-MHz'];
			f2 = d['CPU-max-MHz'];
			return  `实时(Cur): ${f0} MHz | 最小(min): ${f1} MHz | 最大(max): ${f2} MHz `;
		}
 	},
	{
		itemId: 'thermal',
		colspan: 2,
		printBar: false,
		title: gettext('CPU 温度'),
		textField: 'thermalstate',
		renderer:function(value){
			const p0 = value.match(/Package id 0.*?\+([\d\.]+)Â/)[1];
			const c0 = value.match(/Core 0.*?\+([\d\.]+)Â/)[1];
			const c1 = value.match(/Core 1.*?\+([\d\.]+)Â/)[1];
			const c2 = value.match(/Core 2.*?\+([\d\.]+)Â/)[1];
			const c3 = value.match(/Core 3.*?\+([\d\.]+)Â/)[1];
			return `Package: ${p0} ℃ | Core 0: ${c0} ℃ | Core 1: ${c1} ℃ | Core 2: ${c2} ℃ | Core 3: ${c3} ℃`
		}
	},# 这里需要补充一个 , 号不然会出问题
# 增加以下内容
	{
		itemId: 'speed',
		colspan: 2,
		printBar: false,
		title: gettext('FAN 转速'),
		textField: 'getfanspeed',
		renderer:function(value){
			var d = JSON.parse(value);
			f0 = d['FAN1'];
			f1 = d['FAN2'];
			f2 = d['FAN3'];
			return  `FAN1: ${f0} RPM | FAN2: ${f1} RPM | FAN3: ${f2} RPM `;
		}
 	}

第5步:重启 pveproxy 服务

systemctl restart pveproxy

实际效果一览:

如果没生效,记得先清除网页缓存,或者使用Edge的InPrivate模式。

image

当然如果你不想有留白的区域,想关掉一些信息显示,可以将/usr/share/pve-manager/js/pvemanagerlib.js里的这些内容删掉
image
image

最终效果

image

处理器信息我手动改了,因为是ES版,没法正确识别。

@suli3
Copy link

suli3 commented Jan 29, 2023

Nice job, 效果正是我需要的效果,不过我的是台R730xd有20个核的那种,核温显示的地方得改改

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants