Pārlūkot izejas kodu

Added list raid detail api

aroz 1 gadu atpakaļ
vecāks
revīzija
5875d08325

+ 3 - 0
disk.go

@@ -159,6 +159,9 @@ func DiskServiceInit() {
 				adminRouter.HandleFunc("/system/disk/raid/new", raidManager.HandleCreateRAIDDevice)
 				adminRouter.HandleFunc("/system/disk/raid/remove", raidManager.HandleRemoveRaideDevice)
 				adminRouter.HandleFunc("/system/disk/raid/format", raidManager.HandleFormatRaidDevice)
+				adminRouter.HandleFunc("/system/disk/raid/detail", raidManager.HandleLoadArrayDetail)
+
+				//adminRouter.HandleFunc("/system/disk/physical/list", raidManager.HandleListRaidDevices)
 
 				/* Advance functions*/
 				adminRouter.HandleFunc("/system/disk/raid/assemble", raidManager.HandleRaidDevicesAssemble)

+ 61 - 0
mod/disk/diskfs/diskfs.go

@@ -1,8 +1,10 @@
 package diskfs
 
 import (
+	"bufio"
 	"errors"
 	"fmt"
+	"os"
 	"os/exec"
 	"strconv"
 	"strings"
@@ -121,3 +123,62 @@ func ListAllStorageDevices(minSize int64) ([]*StorageDeviceMeta, error) {
 
 	return devices, nil
 }
+
+// Check if a device is mounted given the path name, like /dev/sdc
+func DeviceIsMounted(devicePath string) (bool, error) {
+	// Open the mountinfo file
+	file, err := os.Open("/proc/mounts")
+	if err != nil {
+		return false, fmt.Errorf("error opening /proc/mounts: %v", err)
+	}
+	defer file.Close()
+
+	// Scan the mountinfo file line by line
+	scanner := bufio.NewScanner(file)
+	for scanner.Scan() {
+		line := scanner.Text()
+		fields := strings.Fields(line)
+		if len(fields) >= 2 && fields[0] == devicePath {
+			// Device is mounted
+			return true, nil
+		}
+	}
+
+	// Device is not mounted
+	return false, nil
+}
+
+// UnmountDevice unmounts the specified device.
+// Remember to use full path (e.g. /dev/md0) in the devicePath
+func UnmountDevice(devicePath string) error {
+	// Construct the bash command to unmount the device
+	cmd := exec.Command("sudo", "bash", "-c", fmt.Sprintf("umount %s", devicePath))
+
+	// Run the command
+	err := cmd.Run()
+	if err != nil {
+		return fmt.Errorf("error unmounting device: %v", err)
+	}
+
+	return nil
+}
+
+// DANGER: Wipe the whole disk given the disk path
+func WipeDisk(diskPath string) error {
+	// Unmount the disk
+	isMounted, _ := DeviceIsMounted(diskPath)
+	if isMounted {
+		umountCmd := exec.Command("sudo", "umount", diskPath)
+		if err := umountCmd.Run(); err != nil {
+			return fmt.Errorf("error unmounting disk %s: %v", diskPath, err)
+		}
+	}
+
+	// Wipe all filesystem signatures on the entire disk
+	wipeCmd := exec.Command("sudo", "wipefs", "--all", "--force", diskPath)
+	if err := wipeCmd.Run(); err != nil {
+		return fmt.Errorf("error wiping filesystem signatures on %s: %v", diskPath, err)
+	}
+
+	return nil
+}

+ 38 - 6
mod/disk/raid/handler.go

@@ -25,10 +25,38 @@ func (m *Manager) HandleMdadmFlushReload(w http.ResponseWriter, r *http.Request)
 		utils.SendErrorResponse(w, "reload failed: "+err.Error())
 		return
 	}
-
 	utils.SendOK(w)
 }
 
+// Handle loading the detail of a given RAID array
+func (m *Manager) HandleLoadArrayDetail(w http.ResponseWriter, r *http.Request) {
+	devName, err := utils.GetPara(r, "devName")
+	if err != nil {
+		utils.SendErrorResponse(w, "invalid device name given")
+		return
+	}
+
+	if !strings.HasPrefix(devName, "/dev/") {
+		devName = "/dev/" + devName
+	}
+
+	//Check if it exists
+	if !m.RAIDDeviceExists(devName) {
+		utils.SendErrorResponse(w, "RAID device not exists")
+		return
+	}
+
+	//Get status of the array
+	targetRAIDInfo, err := m.GetRAIDInfo(devName)
+	if err != nil {
+		utils.SendErrorResponse(w, err.Error())
+		return
+	}
+
+	js, _ := json.Marshal(targetRAIDInfo)
+	utils.SendJSONResponse(w, string(js))
+}
+
 // Handle formating a device
 func (m *Manager) HandleFormatRaidDevice(w http.ResponseWriter, r *http.Request) {
 	devName, err := utils.GetPara(r, "devName")
@@ -79,9 +107,13 @@ func (m *Manager) HandleListRaidDevices(w http.ResponseWriter, r *http.Request)
 func (m *Manager) HandleCreateRAIDDevice(w http.ResponseWriter, r *http.Request) {
 	//TODO: Change GetPara to Post
 	devName, err := utils.GetPara(r, "devName")
-	if err != nil {
-		utils.SendErrorResponse(w, "invalid device name given")
-		return
+	if err != nil || devName == "" {
+		//Use auto generated one
+		devName, err = GetNextAvailableMDDevice()
+		if err != nil {
+			utils.SendErrorResponse(w, err.Error())
+			return
+		}
 	}
 	raidName, err := utils.GetPara(r, "raidName")
 	if err != nil {
@@ -190,7 +222,7 @@ func (m *Manager) HandleRemoveRaideDevice(w http.ResponseWriter, r *http.Request
 		targetDevice = filepath.Join("/dev/", targetDevice)
 	}
 
-	mounted, err := DeviceIsMounted(targetDevice)
+	mounted, err := diskfs.DeviceIsMounted(targetDevice)
 	if err != nil {
 		log.Println("[RAID] Unmount failed: " + err.Error())
 		utils.SendErrorResponse(w, err.Error())
@@ -198,7 +230,7 @@ func (m *Manager) HandleRemoveRaideDevice(w http.ResponseWriter, r *http.Request
 	}
 
 	if mounted {
-		err = UnmountDevice(targetDevice)
+		err = diskfs.UnmountDevice(targetDevice)
 		if err != nil {
 			log.Println("[RAID] Unmount failed: " + err.Error())
 			utils.SendErrorResponse(w, err.Error())

+ 2 - 1
mod/disk/raid/mdadmConf.go

@@ -8,6 +8,7 @@ import (
 	"strings"
 	"time"
 
+	"imuslab.com/arozos/mod/disk/diskfs"
 	"imuslab.com/arozos/mod/utils"
 )
 
@@ -33,7 +34,7 @@ func (m *Manager) FlushReload() error {
 	for _, rd := range raidDevices {
 
 		//Check if it is mounted. If yes, skip this
-		devMounted, err := DeviceIsMounted("/dev/" + rd.Name)
+		devMounted, err := diskfs.DeviceIsMounted("/dev/" + rd.Name)
 		if devMounted || err != nil {
 			log.Println("[RAID] " + "/dev/" + rd.Name + " is in use. Skipping.")
 			continue

+ 4 - 4
mod/disk/raid/raiddetails.go

@@ -38,7 +38,7 @@ type DeviceInfo struct {
 }
 
 // GetRAIDInfo retrieves information about a RAID array using the mdadm command.
-func GetRAIDInfo(arrayName string) (*RAIDInfo, error) {
+func (m *Manager) GetRAIDInfo(arrayName string) (*RAIDInfo, error) {
 	cmd := exec.Command("sudo", "mdadm", "--detail", arrayName)
 
 	output, err := cmd.Output()
@@ -63,7 +63,7 @@ func parseRAIDInfo(output string) *RAIDInfo {
 				raidInfo.Version = fields[2]
 			case "Creation":
 				creationTimeStr := strings.Join(fields[3:], " ")
-				creationTime, _ := time.Parse("Mon Jan 02 15:04:05 2006", creationTimeStr)
+				creationTime, _ := time.Parse(time.ANSIC, creationTimeStr)
 				raidInfo.CreationTime = creationTime
 			case "Raid":
 				if fields[1] == "Level" {
@@ -79,10 +79,10 @@ func parseRAIDInfo(output string) *RAIDInfo {
 			case "Total":
 				raidInfo.TotalDevices, _ = strconv.Atoi(fields[3])
 			case "Persistence":
-				raidInfo.Persistence = strings.Join(fields[3:], " ")
+				raidInfo.Persistence = strings.Join(fields[2:], " ")
 			case "Update":
 				updateTimeStr := strings.Join(fields[3:], " ")
-				updateTime, _ := time.Parse("Mon Jan 02 15:04:05 2006", updateTimeStr)
+				updateTime, _ := time.Parse(time.ANSIC, updateTimeStr)
 				raidInfo.UpdateTime = updateTime
 			case "State":
 				raidInfo.State = fields[2]

+ 3 - 61
mod/disk/raid/raidutils.go

@@ -1,13 +1,14 @@
 package raid
 
 import (
-	"bufio"
 	"errors"
 	"fmt"
 	"os"
 	"os/exec"
 	"path/filepath"
 	"strings"
+
+	"imuslab.com/arozos/mod/disk/diskfs"
 )
 
 // Get the next avaible RAID array name
@@ -22,29 +23,9 @@ func GetNextAvailableMDDevice() (string, error) {
 	return "", fmt.Errorf("no available /dev/mdX devices found")
 }
 
-// DANGER: Wipe the whole disk given the disk path
-func (m *Manager) WipeDisk(diskPath string) error {
-	// Unmount the disk
-	isMounted, _ := DeviceIsMounted(diskPath)
-	if isMounted {
-		umountCmd := exec.Command("sudo", "umount", diskPath)
-		if err := umountCmd.Run(); err != nil {
-			return fmt.Errorf("error unmounting disk %s: %v", diskPath, err)
-		}
-	}
-
-	// Wipe all filesystem signatures on the entire disk
-	wipeCmd := exec.Command("sudo", "wipefs", "--all", "--force", diskPath)
-	if err := wipeCmd.Run(); err != nil {
-		return fmt.Errorf("error wiping filesystem signatures on %s: %v", diskPath, err)
-	}
-
-	return nil
-}
-
 // ClearSuperblock clears the superblock of the specified disk so it can be used safely
 func (m *Manager) ClearSuperblock(devicePath string) error {
-	isMounted, err := DeviceIsMounted(devicePath)
+	isMounted, err := diskfs.DeviceIsMounted(devicePath)
 	if err != nil {
 		return errors.New("unable to validate if the device is unmounted: " + err.Error())
 	}
@@ -61,30 +42,6 @@ func (m *Manager) ClearSuperblock(devicePath string) error {
 	return nil
 }
 
-// Check if a device is mounted given the path name, like /dev/sdc
-func DeviceIsMounted(devicePath string) (bool, error) {
-	// Open the mountinfo file
-	file, err := os.Open("/proc/mounts")
-	if err != nil {
-		return false, fmt.Errorf("error opening /proc/mounts: %v", err)
-	}
-	defer file.Close()
-
-	// Scan the mountinfo file line by line
-	scanner := bufio.NewScanner(file)
-	for scanner.Scan() {
-		line := scanner.Text()
-		fields := strings.Fields(line)
-		if len(fields) >= 2 && fields[0] == devicePath {
-			// Device is mounted
-			return true, nil
-		}
-	}
-
-	// Device is not mounted
-	return false, nil
-}
-
 // Use to restart any not-removed RAID device
 func (m *Manager) RestartRAIDService() error {
 	cmd := exec.Command("sudo", "mdadm", "--assemble", "--scan")
@@ -130,21 +87,6 @@ func (m *Manager) RemoveRAIDMember(devicePath string) error {
 	return nil
 }
 
-// UnmountDevice unmounts the specified device.
-// Remember to use full path (e.g. /dev/md0) in the devicePath
-func UnmountDevice(devicePath string) error {
-	// Construct the bash command to unmount the device
-	cmd := exec.Command("sudo", "bash", "-c", fmt.Sprintf("umount %s", devicePath))
-
-	// Run the command
-	err := cmd.Run()
-	if err != nil {
-		return fmt.Errorf("error unmounting device: %v", err)
-	}
-
-	return nil
-}
-
 // IsValidRAIDLevel checks if the given RAID level is valid.
 func IsValidRAIDLevel(level string) bool {
 	// List of valid RAID levels