package raid import ( "fmt" "os/exec" "strconv" "strings" "time" ) // RAIDInfo represents information about a RAID array. type RAIDInfo struct { Version string CreationTime time.Time RaidLevel string ArraySize int UsedDevSize int RaidDevices int TotalDevices int Persistence string UpdateTime time.Time State string ActiveDevices int WorkingDevices int FailedDevices int SpareDevices int Consistency string Name string UUID string Events int DeviceInfo []DeviceInfo } // DeviceInfo represents information about a device in a RAID array. type DeviceInfo struct { Number int Major int Minor int RaidDevice int State string DevicePath string } // GetRAIDInfo retrieves information about a RAID array using the mdadm command. func GetRAIDInfo(arrayName string) (*RAIDInfo, error) { cmd := exec.Command("sudo", "mdadm", "--detail", arrayName) output, err := cmd.Output() if err != nil { return nil, fmt.Errorf("error running mdadm command: %v", err) } info := parseRAIDInfo(string(output)) return info, nil } // parseRAIDInfo parses the output of mdadm --detail command and returns the RAIDInfo struct. func parseRAIDInfo(output string) *RAIDInfo { lines := strings.Split(output, "\n") raidInfo := &RAIDInfo{} for _, line := range lines { fields := strings.Fields(line) if len(fields) >= 2 { switch fields[0] { case "Version": raidInfo.Version = fields[2] case "Creation": creationTimeStr := strings.Join(fields[3:], " ") creationTime, _ := time.Parse("Mon Jan 02 15:04:05 2006", creationTimeStr) raidInfo.CreationTime = creationTime case "Raid": if fields[1] == "Level" { //Raid Level raidInfo.RaidLevel = fields[3] } else if fields[1] == "Devices" { raidInfo.RaidDevices, _ = strconv.Atoi(fields[3]) } case "Array": raidInfo.ArraySize, _ = strconv.Atoi(fields[3]) case "Used": raidInfo.UsedDevSize, _ = strconv.Atoi(fields[4]) case "Total": raidInfo.TotalDevices, _ = strconv.Atoi(fields[3]) case "Persistence": raidInfo.Persistence = strings.Join(fields[3:], " ") case "Update": updateTimeStr := strings.Join(fields[3:], " ") updateTime, _ := time.Parse("Mon Jan 02 15:04:05 2006", updateTimeStr) raidInfo.UpdateTime = updateTime case "State": raidInfo.State = fields[2] case "Active": raidInfo.ActiveDevices, _ = strconv.Atoi(fields[3]) case "Working": raidInfo.WorkingDevices, _ = strconv.Atoi(fields[3]) case "Failed": raidInfo.FailedDevices, _ = strconv.Atoi(fields[3]) case "Spare": raidInfo.SpareDevices, _ = strconv.Atoi(fields[3]) case "Consistency": raidInfo.Consistency = strings.Join(fields[3:], " ") case "Name": raidInfo.Name = strings.Join(fields[2:], " ") case "UUID": raidInfo.UUID = fields[2] case "Events": raidInfo.Events, _ = strconv.Atoi(fields[2]) default: if len(fields) == 6 && fields[0] != "Number" { deviceInfo := DeviceInfo{} deviceInfo.Number, _ = strconv.Atoi(fields[0]) deviceInfo.Major, _ = strconv.Atoi(fields[1]) deviceInfo.Minor, _ = strconv.Atoi(fields[2]) deviceInfo.RaidDevice, _ = strconv.Atoi(fields[3]) deviceInfo.State = fields[4] deviceInfo.DevicePath = fields[5] raidInfo.DeviceInfo = append(raidInfo.DeviceInfo, deviceInfo) } } } } return raidInfo } // PrettyPrintRAIDInfo pretty prints the RAIDInfo struct. func (info *RAIDInfo) PrettyPrintRAIDInfo() { fmt.Println("RAID Array Information:") fmt.Printf(" Version: %s\n", info.Version) fmt.Printf(" Creation Time: %s\n", info.CreationTime.Format("Mon Jan 02 15:04:05 2006")) fmt.Printf(" Raid Level: %s\n", info.RaidLevel) fmt.Printf(" Array Size: %s\n", info.ArraySize) fmt.Printf(" Used Dev Size: %s\n", info.UsedDevSize) fmt.Printf(" Raid Devices: %d\n", info.RaidDevices) fmt.Printf(" Total Devices: %d\n", info.TotalDevices) fmt.Printf(" Persistence: %s\n", info.Persistence) fmt.Printf(" Update Time: %s\n", info.UpdateTime.Format("Mon Jan 02 15:04:05 2006")) fmt.Printf(" State: %s\n", info.State) fmt.Printf(" Active Devices: %d\n", info.ActiveDevices) fmt.Printf(" Working Devices: %d\n", info.WorkingDevices) fmt.Printf(" Failed Devices: %d\n", info.FailedDevices) fmt.Printf(" Spare Devices: %d\n", info.SpareDevices) fmt.Printf(" Consistency Policy: %s\n", info.Consistency) fmt.Printf(" Name: %s\n", info.Name) fmt.Printf(" UUID: %s\n", info.UUID) fmt.Printf(" Events: %d\n", info.Events) fmt.Println("\nDevice Information:") fmt.Printf("%-10s %-10s %-10s %-12s %-10s %s\n", "Number", "Major", "Minor", "RaidDevice", "State", "DevicePath") for _, device := range info.DeviceInfo { fmt.Printf("%-10d %-10d %-10d %-12d %-10s %s\n", device.Number, device.Major, device.Minor, device.RaidDevice, device.State, device.DevicePath) } }