182 lines
5.2 KiB
Go
182 lines
5.2 KiB
Go
package raid
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"os/exec"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"git.lxtend.com/qqbot/constants"
|
|
"git.lxtend.com/qqbot/handler"
|
|
"git.lxtend.com/qqbot/model"
|
|
)
|
|
|
|
func init() {
|
|
handler.RegisterHandler("!raid", RaidHandler, constants.LEVEL_USER)
|
|
}
|
|
|
|
func RaidHandler(msg model.Message) (reply *model.Reply) {
|
|
diskInfoList := GetDiskInfo()
|
|
|
|
if len(diskInfoList) == 0 {
|
|
return &model.Reply{
|
|
FromMsg: msg,
|
|
ReplyMsg: "未获取到阵列信息",
|
|
ReferOriginMsg: false,
|
|
}
|
|
}
|
|
|
|
sb := strings.Builder{}
|
|
sb.WriteString("阵列信息:\n")
|
|
for _, diskInfo := range diskInfoList {
|
|
sb.WriteString(diskInfo.String())
|
|
}
|
|
|
|
return &model.Reply{
|
|
FromMsg: msg,
|
|
ReplyMsg: sb.String(),
|
|
ReferOriginMsg: false,
|
|
}
|
|
}
|
|
|
|
// MegaCli64 -PDList -aALL | grep -E "Slot Number|Drive Temperature|Inquiry Data|Firmware state|S.M.A.R.T alert" | cat
|
|
// Slot Number: 0
|
|
// Firmware state: Online, Spun Up
|
|
// Inquiry Data: TOSHIBA MG04SCA60EE 010356A0A001FWWB
|
|
// Drive Temperature :56C (132.80 F)
|
|
// Drive has flagged a S.M.A.R.T alert : No
|
|
// Slot Number: 1
|
|
// Firmware state: Online, Spun Up
|
|
// Inquiry Data: TOSHIBA MG04SCA60EE 0103X6S0A0LRFWWB
|
|
// Drive Temperature :54C (129.20 F)
|
|
// Drive has flagged a S.M.A.R.T alert : No
|
|
// Slot Number: 2
|
|
// Firmware state: Online, Spun Up
|
|
// Inquiry Data: TOSHIBA MG04SCA60EE 010356F0A00AFWWB
|
|
// Drive Temperature :51C (123.80 F)
|
|
// Drive has flagged a S.M.A.R.T alert : No
|
|
// Slot Number: 3
|
|
// Firmware state: Online, Spun Up
|
|
// Inquiry Data: TOSHIBA MG04SCA60EE 0103X6Q0A0RZFWWB
|
|
// Drive Temperature :46C (114.80 F)
|
|
// Drive has flagged a S.M.A.R.T alert : No
|
|
// Slot Number: 4
|
|
// Firmware state: Unconfigured(bad)
|
|
// Inquiry Data: TOSHIBA MG04SCA60EE 0103X6R0A09VFWWB
|
|
// Drive Temperature :49C (120.20 F)
|
|
// Drive has flagged a S.M.A.R.T alert : No
|
|
// Slot Number: 5
|
|
// Firmware state: Online, Spun Up
|
|
// Inquiry Data: TOSHIBA MG04SCA60EE 0103X6R0A0JZFWWB
|
|
// Drive Temperature :53C (127.40 F)
|
|
// Drive has flagged a S.M.A.R.T alert : No
|
|
// Slot Number: 6
|
|
// Firmware state: Online, Spun Up
|
|
// Inquiry Data: TOSHIBA MG04SCA60EE 010356F0A004FWWB
|
|
// Drive Temperature :56C (132.80 F)
|
|
// Drive has flagged a S.M.A.R.T alert : No
|
|
// Slot Number: 7
|
|
// Firmware state: Online, Spun Up
|
|
// Inquiry Data: TOSHIBA MG04SCA60EE 01034680A01WFWWB
|
|
// Drive Temperature :58C (136.40 F)
|
|
// Drive has flagged a S.M.A.R.T alert : No
|
|
|
|
type DiskInfo struct {
|
|
SlotNumber int
|
|
DriveTemperature string
|
|
Type string
|
|
Sn string
|
|
FirmwareState string
|
|
SmartAlert bool
|
|
}
|
|
|
|
func (d *DiskInfo) String() string {
|
|
sb := strings.Builder{}
|
|
sb.WriteString(fmt.Sprintf("槽位: %d\n", d.SlotNumber))
|
|
sb.WriteString(fmt.Sprintf("温度: %s\n", d.DriveTemperature))
|
|
sb.WriteString(fmt.Sprintf("型号: %s\n", d.Type))
|
|
sb.WriteString(fmt.Sprintf("SN: %s\n", d.Sn))
|
|
sb.WriteString(fmt.Sprintf("状态: %s\n", d.FirmwareState))
|
|
sb.WriteString(fmt.Sprintf("S.M.A.R.T报警: %t\n", d.SmartAlert))
|
|
return sb.String()
|
|
}
|
|
|
|
func ParseDiskInfoList(lines []string) []*DiskInfo {
|
|
var diskInfoList []*DiskInfo
|
|
var currentDisk *DiskInfo
|
|
|
|
for _, line := range lines {
|
|
line = strings.TrimSpace(line)
|
|
|
|
if strings.HasPrefix(line, "Slot Number:") {
|
|
// 新的磁盘信息开始
|
|
if currentDisk != nil {
|
|
diskInfoList = append(diskInfoList, currentDisk)
|
|
}
|
|
|
|
slotStr := strings.TrimSpace(strings.TrimPrefix(line, "Slot Number:"))
|
|
slotNum, err := strconv.Atoi(slotStr)
|
|
if err != nil {
|
|
log.Printf("解析槽位号失败: %v", err)
|
|
slotNum = -1
|
|
}
|
|
|
|
currentDisk = &DiskInfo{
|
|
SlotNumber: slotNum,
|
|
}
|
|
} else if currentDisk != nil {
|
|
// 处理当前磁盘的其他信息
|
|
if strings.HasPrefix(line, "Firmware state:") {
|
|
currentDisk.FirmwareState = strings.TrimSpace(strings.TrimPrefix(line, "Firmware state:"))
|
|
} else if strings.HasPrefix(line, "Inquiry Data:") {
|
|
inquiryData := strings.TrimSpace(strings.TrimPrefix(line, "Inquiry Data:"))
|
|
parts := strings.Fields(inquiryData)
|
|
if len(parts) >= 2 {
|
|
currentDisk.Type = strings.Join(parts[:len(parts)-1], " ")
|
|
currentDisk.Sn = parts[len(parts)-1]
|
|
}
|
|
} else if strings.HasPrefix(line, "Drive Temperature") {
|
|
tempParts := strings.Split(line, ":")
|
|
if len(tempParts) >= 2 {
|
|
currentDisk.DriveTemperature = strings.TrimSpace(tempParts[1])
|
|
}
|
|
} else if strings.HasPrefix(line, "Drive has flagged a S.M.A.R.T alert") {
|
|
smartParts := strings.Split(line, ":")
|
|
if len(smartParts) >= 2 {
|
|
currentDisk.SmartAlert = strings.TrimSpace(smartParts[1]) != "No"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 添加最后一个磁盘
|
|
if currentDisk != nil {
|
|
diskInfoList = append(diskInfoList, currentDisk)
|
|
}
|
|
|
|
return diskInfoList
|
|
}
|
|
|
|
func GetDiskInfo() []*DiskInfo {
|
|
// 首先尝试运行MegaCli64命令
|
|
cmd := exec.Command("MegaCli64", "-PDList", "-aALL")
|
|
outputBytes, err := cmd.Output()
|
|
if err != nil {
|
|
log.Printf("运行MegaCli64失败: %v", err)
|
|
|
|
// 尝试运行grep命令模拟示例输出
|
|
grepCmd := exec.Command("grep", "-E", "Slot Number|Drive Temperature|Inquiry Data|Firmware state|S.M.A.R.T alert")
|
|
outputBytes, err = grepCmd.Output()
|
|
if err != nil {
|
|
log.Printf("获取磁盘信息失败: %v", err)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
output := string(outputBytes)
|
|
lines := strings.Split(output, "\n")
|
|
|
|
return ParseDiskInfoList(lines)
|
|
}
|