package raid import ( "encoding/json" "log" "net/http" "path/filepath" "strconv" "strings" "imuslab.com/arozos/mod/utils" ) /* Handler.go This module handle api call to the raid module */ // List all the raid device in this system func (m *Manager) HandleListRaidDevices(w http.ResponseWriter, r *http.Request) { rdev, err := m.GetRAIDDevicesFromProcMDStat() if err != nil { utils.SendErrorResponse(w, err.Error()) return } js, _ := json.Marshal(rdev) utils.SendJSONResponse(w, string(js)) } // Create a RAID storage pool func (m *Manager) HandleCreateRAIDDevice(w http.ResponseWriter, r *http.Request) { devName, err := utils.GetPara(r, "devName") if err != nil { utils.SendErrorResponse(w, "invalid device name given") return } raidName, err := utils.GetPara(r, "raidName") if err != nil { utils.SendErrorResponse(w, "invalid raid storage name given") return } raidLevelStr, err := utils.GetPara(r, "level") if err != nil { utils.SendErrorResponse(w, "invalid raid level given") return } raidDevicesJSON, err := utils.GetPara(r, "raidDev") if err != nil { utils.SendErrorResponse(w, "invalid raid device array given") return } spareDevicesJSON, err := utils.GetPara(r, "spareDev") if err != nil { utils.SendErrorResponse(w, "invalid spare device array given") return } //Convert raidDevices and spareDevices ID into string slice raidDevices := []string{} spareDevices := []string{} err = json.Unmarshal([]byte(raidDevicesJSON), &raidDevices) if err != nil { utils.SendErrorResponse(w, "unable to parse raid device into array") return } err = json.Unmarshal([]byte(spareDevicesJSON), &spareDevices) if err != nil { utils.SendErrorResponse(w, "unable to parse spare devices into array") return } //Make sure RAID Name do not contain spaces or werid charcters if strings.Contains(raidName, " ") { utils.SendErrorResponse(w, "raid name cannot contain space") return } //Convert raidLevel to int raidLevel, err := strconv.Atoi(raidLevelStr) if err != nil { utils.SendErrorResponse(w, "invalid raid level given") return } //Create the RAID device err = m.CreateRAIDDevice(devName, raidName, raidLevel, raidDevices, spareDevices) if err != nil { utils.SendErrorResponse(w, err.Error()) return } //Update the mdadm config err = m.UpdateMDADMConfig() if err != nil { utils.SendErrorResponse(w, err.Error()) return } utils.SendOK(w) } // Request to reload the RAID manager and scan new / fix missing raid pools func (m *Manager) HandleRaidDevicesAssemble(w http.ResponseWriter, r *http.Request) { err := m.RestartRAIDService() if err != nil { utils.SendErrorResponse(w, err.Error()) return } utils.SendOK(w) } // Remove a given raid device with its name, USE WITH CAUTION func (m *Manager) HandleRemoveRaideDevice(w http.ResponseWriter, r *http.Request) { //TODO: Add protection and switch to POST targetDevice, err := utils.GetPara(r, "dev") if err != nil { utils.SendErrorResponse(w, "target device not given") return } //Check if the raid device exists if !m.RAIDDeviceExists(targetDevice) { utils.SendErrorResponse(w, "target device not exists") return } //Get the RAID device memeber disks targetRAIDDevice, err := m.GetRAIDDeviceByDevicePath(targetDevice) if err != nil { utils.SendErrorResponse(w, "error occured when trying to load target RAID device info") return } //Check if it is mounted. If yes, unmount it if !strings.HasPrefix("/dev/", targetDevice) { targetDevice = filepath.Join("/dev/", targetDevice) } mounted, err := DeviceIsMounted(targetDevice) if err != nil { log.Println("[RAID] Unmount failed: " + err.Error()) utils.SendErrorResponse(w, err.Error()) return } if mounted { err = UnmountDevice(targetDevice) if err != nil { log.Println("[RAID] Unmount failed: " + err.Error()) utils.SendErrorResponse(w, err.Error()) return } } //Stop & Remove RAID service on the target device err = m.StopRAIDDevice(targetDevice) if err != nil { log.Println("[RAID] Stop RAID partition failed: " + err.Error()) utils.SendErrorResponse(w, err.Error()) return } //Zeroblock the RAID device member disks for _, memberDisk := range targetRAIDDevice.Members { //Member disk name do not contain full path name := memberDisk.Name if !strings.HasPrefix(name, "/dev/") { name = filepath.Join("/dev/", name) } err = m.ClearSuperblock(name) if err != nil { log.Println("[RAID] Unable to clear superblock on device " + name) continue } } //Update the mdadm config //TODO: Validate this actually works err = m.UpdateMDADMConfig() if err != nil { utils.SendErrorResponse(w, err.Error()) return } //Done utils.SendOK(w) }