Browse Source

Added remove RAID function

aroz 1 year ago
parent
commit
cc2e9df05d

+ 12 - 7
disk.go

@@ -157,20 +157,25 @@ func DiskServiceInit() {
 				/* RAID storage pool function */
 				adminRouter.HandleFunc("/system/disk/raid/list", raidManager.HandleListRaidDevices)
 				adminRouter.HandleFunc("/system/disk/raid/new", raidManager.HandleCreateRAIDDevice)
-				adminRouter.HandleFunc("/system/disk/raid/remove", raidManager.HandleRemoveRaideDevice)
+				adminRouter.HandleFunc("/system/disk/raid/remove", func(w http.ResponseWriter, r *http.Request) {
+					if !AuthValidateSecureRequest(w, r) {
+						return
+					}
+					raidManager.HandleRemoveRaideDevice(w, r)
+				})
 				adminRouter.HandleFunc("/system/disk/raid/format", raidManager.HandleFormatRaidDevice)
 				adminRouter.HandleFunc("/system/disk/raid/detail", raidManager.HandleLoadArrayDetail)
 				adminRouter.HandleFunc("/system/disk/raid/devinfo", raidManager.HandlListChildrenDeviceInfo)
 				adminRouter.HandleFunc("/system/disk/raid/addMemeber", func(w http.ResponseWriter, r *http.Request) {
-					if !AuthValidateSecureRequest(w, r) {
-						return
-					}
+					//if !AuthValidateSecureRequest(w, r) {
+					//	return
+					//}
 					raidManager.HandleAddDiskToRAIDVol(w, r)
 				})
 				adminRouter.HandleFunc("/system/disk/raid/removeMemeber", func(w http.ResponseWriter, r *http.Request) {
-					if !AuthValidateSecureRequest(w, r) {
-						return
-					}
+					//if !AuthValidateSecureRequest(w, r) {
+					//	return
+					//}
 					raidManager.HandleRemoveDiskFromRAIDVol(w, r)
 				})
 

+ 10 - 3
mod/disk/diskfs/diskfs.go

@@ -5,8 +5,10 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
+	"log"
 	"os"
 	"os/exec"
+	"path/filepath"
 	"regexp"
 	"strings"
 
@@ -186,12 +188,16 @@ func DeviceIsMounted(devicePath string) (bool, error) {
 	}
 	defer file.Close()
 
+	if !strings.HasPrefix(devicePath, "/dev/") {
+		devicePath = filepath.Join("/dev/", devicePath)
+	}
 	// 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 {
+		fmt.Println(strings.TrimSpace(fields[0]), devicePath, strings.EqualFold(strings.TrimSpace(fields[0]), devicePath))
+		if strings.EqualFold(strings.TrimSpace(fields[0]), devicePath) {
 			// Device is mounted
 			return true, nil
 		}
@@ -205,11 +211,12 @@ func DeviceIsMounted(devicePath string) (bool, error) {
 // 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))
+	cmd := exec.Command("sudo", "bash", "-c", fmt.Sprintf("umount -l %s", devicePath))
 
 	// Run the command
-	err := cmd.Run()
+	output, err := cmd.CombinedOutput()
 	if err != nil {
+		log.Println("[RAID] Unable to unmount device: " + string(output))
 		return fmt.Errorf("error unmounting device: %v", err)
 	}
 

+ 1 - 9
mod/disk/diskmg/diskmg.go

@@ -12,7 +12,6 @@ import (
 	"strings"
 	"time"
 
-	db "imuslab.com/arozos/mod/database"
 	fs "imuslab.com/arozos/mod/filesystem"
 	"imuslab.com/arozos/mod/utils"
 )
@@ -359,13 +358,7 @@ func Mount(devID string, mountpt string, mountingTool string, fsHandlers []*fs.F
 	//Loop each fsHandler. If exists one that fits and Closed, reopen it
 	for _, fsh := range fsHandlers {
 		if strings.Contains(filepath.ToSlash(fsh.Path), filepath.ToSlash(mountpt)) {
-			//Re-open the file system database and set its flag to Open
-			fsdbPath := filepath.ToSlash(filepath.Clean(fsh.Path)) + "/aofs.db"
-			dbObject, err := db.NewDatabase(fsdbPath, false)
-			if err != nil {
-				continue
-			}
-			fsh.FilesystemDatabase = dbObject
+			//Re-open the file system and set its flag to Open
 			fsh.Closed = false
 		}
 	}
@@ -385,7 +378,6 @@ func Unmount(mountpt string, fsHandlers []*fs.FileSystemHandler) (string, error)
 	for _, fsh := range fsHandlers {
 		if strings.Contains(filepath.ToSlash(fsh.Path), filepath.ToSlash(mountpt)) {
 			//Close this file system handler
-			fsh.FilesystemDatabase.Close()
 			fsh.Closed = true
 		}
 	}

+ 30 - 3
mod/disk/raid/handler.go

@@ -2,6 +2,7 @@ package raid
 
 import (
 	"encoding/json"
+	"fmt"
 	"log"
 	"net/http"
 	"path/filepath"
@@ -417,7 +418,7 @@ func (m *Manager) HandleRaidDevicesAssemble(w http.ResponseWriter, r *http.Reque
 // 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")
+	targetDevice, err := utils.PostPara(r, "raidDev")
 	if err != nil {
 		utils.SendErrorResponse(w, "target device not given")
 		return
@@ -437,7 +438,7 @@ func (m *Manager) HandleRemoveRaideDevice(w http.ResponseWriter, r *http.Request
 	}
 
 	//Check if it is mounted. If yes, unmount it
-	if !strings.HasPrefix("/dev/", targetDevice) {
+	if !strings.HasPrefix(targetDevice, "/dev/") {
 		targetDevice = filepath.Join("/dev/", targetDevice)
 	}
 
@@ -448,15 +449,42 @@ func (m *Manager) HandleRemoveRaideDevice(w http.ResponseWriter, r *http.Request
 		return
 	}
 
+	fmt.Println(mounted)
+
 	if mounted {
+		log.Println("[RAID] " + targetDevice + " is mounted. Trying to unmount...")
 		err = diskfs.UnmountDevice(targetDevice)
 		if err != nil {
 			log.Println("[RAID] Unmount failed: " + err.Error())
 			utils.SendErrorResponse(w, err.Error())
 			return
 		}
+
+		//Wait for 3 seconds to check if it is still mounted
+		counter := 0
+		for counter < 3 {
+			mounted, _ := diskfs.DeviceIsMounted(targetDevice)
+			if mounted {
+				//Still not unmounted. Wait for it
+				log.Println("[RAID] Device still mounted. Retrying in 1 second")
+				counter++
+				time.Sleep(1 * time.Second)
+			} else {
+				break
+			}
+		}
+
+		//Check if it is still mounted
+		mounted, _ = diskfs.DeviceIsMounted(targetDevice)
+		if mounted {
+			utils.SendErrorResponse(w, "unmount RAID partition failed: device is busy")
+			return
+		}
 	}
 
+	//Give it some time for the raid device to finish umount
+	time.Sleep(300 * time.Millisecond)
+
 	//Stop & Remove RAID service on the target device
 	err = m.StopRAIDDevice(targetDevice)
 	if err != nil {
@@ -481,7 +509,6 @@ func (m *Manager) HandleRemoveRaideDevice(w http.ResponseWriter, r *http.Request
 	}
 
 	//Update the mdadm config
-	//TODO: Validate this actually works
 	err = m.UpdateMDADMConfig()
 	if err != nil {
 		utils.SendErrorResponse(w, err.Error())

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

@@ -64,6 +64,7 @@ func (m *Manager) FlushReload() error {
 
 // Updates the mdadm configuration file with the details of RAID arrays
 // so the RAID drive will still be seen after a reboot (hopefully)
+// this will automatically add / remove config base on current runtime setup
 func (m *Manager) UpdateMDADMConfig() error {
 	cmdMdadm := exec.Command("sudo", "mdadm", "--detail", "--scan", "--verbose")
 

+ 0 - 72
mod/filesystem/filesystem.go

@@ -25,7 +25,6 @@ import (
 	"time"
 
 	uuid "github.com/satori/go.uuid"
-	db "imuslab.com/arozos/mod/database"
 	"imuslab.com/arozos/mod/filesystem/abstractions/ftpfs"
 	"imuslab.com/arozos/mod/filesystem/abstractions/localfs"
 	sftpfs "imuslab.com/arozos/mod/filesystem/abstractions/sftpfs"
@@ -107,7 +106,6 @@ type FileSystemHandler struct {
 	RequireBuffer            bool //Set this to true if the fsh do not provide file header functions like Open() or Create(), require WriteStream() and ReadStream()
 	Parentuid                string
 	InitiationTime           int64
-	FilesystemDatabase       *db.Database
 	FileSystemAbstraction    FileSystemAbstraction
 	Filesystem               string
 	StartOptions             FileSystemOption
@@ -160,17 +158,6 @@ func NewFileSystemHandler(option FileSystemOption, RuntimePersistenceConfig Runt
 			os.MkdirAll(filepath.ToSlash(filepath.Clean(option.Path))+"/users", 0755)
 		}
 
-		//Create the fsdb for this handler
-		var fsdb *db.Database = nil
-		dbp, err := db.NewDatabase(filepath.ToSlash(filepath.Join(filepath.Clean(option.Path), "aofs.db")), false)
-		if err != nil {
-			if option.Access != arozfs.FsReadOnly {
-				log.Println("[File System] Invalid config: Trying to mount a read only path as read-write mount point. Changing " + option.Name + " mount point to READONLY.")
-				option.Access = arozfs.FsReadOnly
-			}
-		} else {
-			fsdb = dbp
-		}
 		rootpath := filepath.ToSlash(filepath.Clean(option.Path)) + "/"
 		return &FileSystemHandler{
 			Name:                     option.Name,
@@ -181,7 +168,6 @@ func NewFileSystemHandler(option FileSystemOption, RuntimePersistenceConfig Runt
 			Hierarchy:                option.Hierarchy,
 			HierarchyConfig:          DefaultEmptyHierarchySpecificConfig,
 			InitiationTime:           time.Now().Unix(),
-			FilesystemDatabase:       fsdb,
 			FileSystemAbstraction:    localfs.NewLocalFileSystemAbstraction(option.Uuid, rootpath, option.Hierarchy, option.Access == arozfs.FsReadOnly),
 			Filesystem:               fstype,
 			StartOptions:             option,
@@ -208,7 +194,6 @@ func NewFileSystemHandler(option FileSystemOption, RuntimePersistenceConfig Runt
 			Hierarchy:             option.Hierarchy,
 			HierarchyConfig:       nil,
 			InitiationTime:        time.Now().Unix(),
-			FilesystemDatabase:    nil,
 			FileSystemAbstraction: webdavfs,
 			Filesystem:            fstype,
 			StartOptions:          option,
@@ -248,7 +233,6 @@ func NewFileSystemHandler(option FileSystemOption, RuntimePersistenceConfig Runt
 			Hierarchy:             option.Hierarchy,
 			HierarchyConfig:       nil,
 			InitiationTime:        time.Now().Unix(),
-			FilesystemDatabase:    nil,
 			FileSystemAbstraction: smbfs,
 			Filesystem:            fstype,
 			StartOptions:          option,
@@ -296,7 +280,6 @@ func NewFileSystemHandler(option FileSystemOption, RuntimePersistenceConfig Runt
 			Hierarchy:             option.Hierarchy,
 			HierarchyConfig:       nil,
 			InitiationTime:        time.Now().Unix(),
-			FilesystemDatabase:    nil,
 			FileSystemAbstraction: sftpfs,
 			Filesystem:            fstype,
 			StartOptions:          option,
@@ -319,7 +302,6 @@ func NewFileSystemHandler(option FileSystemOption, RuntimePersistenceConfig Runt
 			Hierarchy:             option.Hierarchy,
 			HierarchyConfig:       nil,
 			InitiationTime:        time.Now().Unix(),
-			FilesystemDatabase:    nil,
 			FileSystemAbstraction: ftpfs,
 			Filesystem:            fstype,
 			StartOptions:          option,
@@ -457,54 +439,6 @@ func (fsh *FileSystemHandler) GetDirctorySizeFromVpath(vpath string, username st
 	return fsh.GetDirctorySizeFromRealPath(realpath, includeHidden)
 }
 
-/*
-	File Record Related Functions
-	fsh database that keep track of which files is owned by whom
-*/
-
-// Create a file ownership record
-func (fsh *FileSystemHandler) CreateFileRecord(rpath string, owner string) error {
-	if fsh.FilesystemDatabase == nil {
-		//Not supported file system type
-		return errors.New("Not supported filesystem type")
-	}
-	fsh.FilesystemDatabase.NewTable("owner")
-	fsh.FilesystemDatabase.Write("owner", "owner/"+rpath, owner)
-	return nil
-}
-
-// Read the owner of a file
-func (fsh *FileSystemHandler) GetFileRecord(rpath string) (string, error) {
-	if fsh.FilesystemDatabase == nil {
-		//Not supported file system type
-		return "", errors.New("Not supported filesystem type")
-	}
-
-	fsh.FilesystemDatabase.NewTable("owner")
-	if fsh.FilesystemDatabase.KeyExists("owner", "owner/"+rpath) {
-		owner := ""
-		fsh.FilesystemDatabase.Read("owner", "owner/"+rpath, &owner)
-		return owner, nil
-	} else {
-		return "", errors.New("Owner not exists")
-	}
-}
-
-// Delete a file ownership record
-func (fsh *FileSystemHandler) DeleteFileRecord(rpath string) error {
-	if fsh.FilesystemDatabase == nil {
-		//Not supported file system type
-		return errors.New("Not supported filesystem type")
-	}
-
-	fsh.FilesystemDatabase.NewTable("owner")
-	if fsh.FilesystemDatabase.KeyExists("owner", "owner/"+rpath) {
-		fsh.FilesystemDatabase.Delete("owner", "owner/"+rpath)
-	}
-
-	return nil
-}
-
 // Reload the target file system abstraction
 func (fsh *FileSystemHandler) ReloadFileSystelAbstraction() error {
 	log.Println("[File System] Reloading File System Abstraction for " + fsh.Name)
@@ -525,7 +459,6 @@ func (fsh *FileSystemHandler) ReloadFileSystelAbstraction() error {
 
 	//Overwrite the pointers to target fsa
 	fsh.FileSystemAbstraction = reloadedFsh.FileSystemAbstraction
-	fsh.FilesystemDatabase = reloadedFsh.FilesystemDatabase
 	fsh.Closed = false
 	return nil
 }
@@ -535,11 +468,6 @@ func (fsh *FileSystemHandler) Close() {
 	//Set the close flag to true so others function wont access it
 	fsh.Closed = true
 
-	//Close the fsh database
-	if fsh.FilesystemDatabase != nil {
-		fsh.FilesystemDatabase.Close()
-	}
-
 	//Close the file system object
 	err := fsh.FileSystemAbstraction.Close()
 	if err != nil {

+ 1 - 16
mod/user/quota.go

@@ -39,8 +39,6 @@ func (u *User) SetOwnerOfFile(fsh *fs.FileSystemHandler, vpath string) error {
 		u.StorageQuota.AllocateSpace(fsh.FileSystemAbstraction.GetFileSize(rpath))
 	}
 
-	//Add to the fshandler database of this file owner
-	err = fsh.CreateFileRecord(rpath, u.Username)
 	return err
 }
 
@@ -55,8 +53,6 @@ func (u *User) RemoveOwnershipFromFile(fsh *fs.FileSystemHandler, vpath string)
 		//log.Println("Removing user ownership on: " + realpath)
 		u.StorageQuota.ReclaimSpace(fsh.FileSystemAbstraction.GetFileSize(realpath))
 	}
-
-	err = fsh.DeleteFileRecord(realpath)
 	return err
 }
 
@@ -71,21 +67,10 @@ func (u *User) IsOwnerOfFile(fsh *fs.FileSystemHandler, vpath string) bool {
 }
 
 func (u *User) GetFileOwner(fsh *fs.FileSystemHandler, vpath string) string {
-	realpath, err := fsh.FileSystemAbstraction.VirtualPathToRealPath(vpath, u.Username)
-	if err != nil {
-		return ""
-	}
-
 	if fsh.UUID == "user" {
 		//This file is inside user's root. It must be this user's file
 		return u.Username
 	}
 
-	owner, err := fsh.GetFileRecord(realpath)
-	if err != nil {
-		//Error occured. Either this file is not tracked or this file has no owner
-		return ""
-	}
-
-	return owner
+	return ""
 }

+ 1 - 4
storage.go

@@ -360,10 +360,7 @@ func RegisterStorageSettings() {
 
 // CloseAllStorages Close all storage database
 func CloseAllStorages() {
-	allFsh := GetAllLoadedFsh()
-	for _, fsh := range allFsh {
-		fsh.FilesystemDatabase.Close()
-	}
+
 }
 
 func closeAllStoragePools() {

+ 0 - 17
storage.pool.go

@@ -10,7 +10,6 @@ import (
 	"strings"
 	"time"
 
-	"imuslab.com/arozos/mod/database"
 	"imuslab.com/arozos/mod/permission"
 	"imuslab.com/arozos/mod/storage/bridge"
 	"imuslab.com/arozos/mod/utils"
@@ -322,22 +321,6 @@ func HandleFSHToggle(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	if targetFSH.Closed {
-		//Reopen the fsh database and set this to false
-		aofsPath := filepath.ToSlash(filepath.Clean(targetFSH.Path)) + "/aofs.db"
-		conn, err := database.NewDatabase(aofsPath, false)
-		if err == nil {
-			targetFSH.FilesystemDatabase = conn
-		}
-		targetFSH.Closed = false
-	} else {
-		//Close the fsh database and set this to true
-		if targetFSH.FilesystemDatabase != nil {
-			targetFSH.FilesystemDatabase.Close()
-		}
-		targetFSH.Closed = true
-	}
-
 	//Give it some time to finish unloading
 	time.Sleep(1 * time.Second)
 

+ 135 - 67
web/SystemAO/disk/raid/index.html

@@ -64,6 +64,13 @@
                 margin-right: 0 !important;
             }
 
+            /* RAID Option Button */
+            .raidOptionBtn{
+                position: absolute;
+                top: 1em;
+                right: 1em;
+            }
+
             /* Statistics of Device Status */
             .deviceOverview{
                 background-color: #f3f3f3 !important;
@@ -171,9 +178,14 @@
                                 <i id="RAIDOverviewStateIcon" class="ui green check circle icon"></i>
                                 <div class="content">
                                     <span id="RAIDOverviewDiskpath">Loading device details</span>
-                                    <div class="sub header" id="RAIDOverviewDetails"></div>
+                                    <div class="sub header">
+                                        <span id="RAIDOverviewDetails"></span><br>
+                                        <small style="font-weight: 300;" id="RAIDUUID"></small>
+                                    </div>
+                                    
                                 </div>
                             </h3>
+                           
                             <div class="ui divider"></div>
                             <div class="ui basic segment deviceOverview">
                                 <div class="ui tiny four statistics">
@@ -215,8 +227,19 @@
                                     </div>
                                 </div>
                             </div>
+                            <div class="raidOptionBtn">
+                                <button onclick="reloadRAIDVolDetail();" class="ui basic circular icon button"><i class="ui green refresh icon"></i></button>
+                            </div>
+                            <div>
+                                <button onclick="addDiskToArray();" title="Add new disk to this volume" class="circular small basic ui button">
+                                    <i class="green add icon"></i> Add Disk
+                                </button>
+                                <button onclick="" title="Expand volume to fit disks capacity" class="circular small basic ui button">
+                                    <i class="purple expand icon"></i> Expand Volume
+                                </button>
+                            </div>
                         </div>
-                        <br>
+                        <div class="ui divider"></div>
                         <div id="raidDiskList">
                             
                         </div>
@@ -224,66 +247,20 @@
                             <i class="yellow exclamation triangle icon"></i> Not enough redundant disks. Further removal / failure of disk will result in data loss.<br>
                         </div>
                         <div class="ui divider"></div>
-                        <table class="ui very basic compact celled table" style="padding-left: 1em; padding-right: 1em;">
-                            <tbody>
-                                <tr>
-                                    <td>
-                                        <h4><i class="green add icon"></i> Add New Disk</h4>
-                                        <p>Add a new disk to the array. If your array have an empty slot (removed disk), the disk will be added as working disk, otherwise, it will be added as a spare disk.</p>
-                                    </td>
-                                    <td>
-                                        <button onclick="addDiskToArray();" class="circular small basic ui button">
-                                            <i class="green add icon"></i> Add Disk
-                                        </button>
-                                    </td>
-                                </tr>
-                                <tr>
-                                    <td>
-                                        <h4><i class="purple expand icon"></i> Expand RAID Volume</h4>
-                                        <p>If you have upgraded all disks in this RAID storage pool, you can grow the RAID volume and its file system to match the new size of your disks. </p>
-                                    </td>
-                                    <td>
-                                        <button onclick="" class="circular small basic ui button">
-                                            <i class="purple expand icon"></i> Expand Volume
-                                        </button>
-                                    </td>
-                                </tr>
-                            </tbody>
-                        </table> 
-
-                        <div class="dangerzone">
-                            <div class="header">
-                                <h4>Danger Zone</h4>
-                            </div>
-                            <table class="ui very basic compact celled table" style="padding-left: 1em; padding-right: 1em;">
-                                <tbody>
-                                    <tr>
-                                        <td>
-                                            <h4>Stop RAID Volume</h4>
-                                            <p>This will unmount the volume (if mounted) and stop the RAID volume with <code>mdadm --stop /dev/mdX</code>. You will not be able to mount it again until mdadm reloads.<br>
-                                            If you only want to unmount the RAID volume, use the Disk Management Tool instead.</p>
-                                        </td>
-                                        <td>
-                                            <button onclick="" class="circular basic red ui button">
-                                                <i class="red trash icon"></i> Stop RAID Volume
-                                            </button>
-                                        </td>
-                                    </tr>
-                                    <tr>
-                                        <td>
-                                            <h4>Remove RAID Volume</h4>
-                                            <p>Remove the RAID volume from runtime AND the mdadm config file. This should only be done when you are trying to rebuild the RAID volume on a new machine. <br>
-                                                Data in the disks will not be wiped but a full backup is recommended before removing the RAID volume from this system.</p>
-                                        </td>
-                                        <td>
-                                            <button onclick="" class="circular red ui button">
-                                                <i class="trash icon"></i> Remove Volume
-                                            </button>
-                                        </td>
-                                    </tr>
-                                </tbody>
-                            </table> 
+                        <div style="width: 100%; text-align:  center; margin-bottom: 1em;">
+                            <p><i class="yellow exclamation triangle icon"></i> Danger Zone <i class="yellow exclamation triangle icon"></i></p>
                         </div>
+                        
+                        <button onclick="" class="circular basic red ui button">
+                            <i class="red stop icon"></i> Stop RAID
+                        </button>
+                        <button onclick="RAIDRemove();" class="circular red ui button">
+                            <i class="trash icon"></i> Remove RAID
+                        </button>
+                        
+                       
+                       
+                        <br><br><br><br>
                     </div>
                 </div>
             </div>
@@ -295,7 +272,7 @@
                   Confirm Disk Remove
                 </div>
                 <div class="image content">
-                  <div class="ui medium image">
+                  <div class="ui small image">
                     <img src="../disk/raid/img/remove-warning.svg">
                   </div>
                   <div class="description">
@@ -312,6 +289,32 @@
                     REMOVE
                   </div>
                 </div>
+            </div>
+
+            <!-- RAID Remove Confirmation -->
+            <div id="confirmRAIDRemove" class="ui small modal">
+                <i class="close icon"></i>
+                <div class="header">
+                  Confirm RAID Volume Remove
+                </div>
+                <div class="image content">
+                  <div class="ui small image">
+                    <img src="../disk/raid/img/remove-warning.svg">
+                  </div>
+                  <div class="description">
+                    <h4 style="color: rgb(206, 31, 31);"><span id="removingRAIDName"></span></h4>
+                    <p><b>This will clear all stored data in this volume. Please make sure you have backup all important data.</b> Confirm Remove?<br></p>
+                  </div>
+                </div>
+                <div class="actions">
+                  <div class="ui black deny button">
+                    Cancel
+                  </div>
+                  <div class="ui negative left labeled icon button" onclick="confirmRAIDRemove();">
+                    <i class="trash icon"></i>
+                    REMOVE
+                  </div>
+                </div>
               </div>
 
         <script>
@@ -322,6 +325,56 @@
                 removePendingSourceVol: ""
             };
 
+            /* RAID Remove Function */
+            function RAIDRemove(){
+                if (raidManager.editingArray == ""){
+                    console.log("RAID manager have no editing array set")
+                    return;
+                }
+                $("#removingRAIDName").text(raidManager.editingArray);
+                $("#confirmRAIDRemove").modal("show");          
+            }
+
+            function confirmRAIDRemove(){
+                var apiObject = {
+                    api: "../system/disk/raid/remove",
+                    data: {
+                        "raidDev":  raidManager.editingArray,
+                    },
+                    title: `<i class='yellow exclamation triangle icon'></i> REMOVE RAID VOLUME <i class='yellow exclamation triangle icon'></i>`,
+                    desc: `Confirm format and remove RAID: ${raidManager.editingArray}`,
+                    thisuser: true, //This username as default, set to false for entering other user
+                    method: "POST",
+                    success: undefined
+                }
+                apiObject = encodeURIComponent(JSON.stringify(apiObject));
+                
+               
+                parent.newFloatWindow({
+                    url: "SystemAO/security/authreq.html#" + apiObject,
+                    width: 480,
+                    height: 300,
+                    appicon: "SystemAO/security/img/lock.svg",
+                    title: `Confirm Disk Remove`,
+                    parent: ao_module_windowID,
+                    callback: "handleRAIDRemoveCallback"
+                });
+            }
+
+            window.handleRAIDRemoveCallback = function(data){
+                if (data.error != undefined){
+                    //Something went wrong
+                    alert(data.error);
+                }else{
+                    setTimeout(function(){
+                        //RAID volume not exist anymore. Reset everything
+                        raidManager = {};
+                        initRAIDVolList();
+                    }, 300);
+                }
+                
+            }
+
             /* New Disk Function */
             function addDiskToArray(arrayName=raidManager.editingArray){
                 let payload = {
@@ -358,6 +411,7 @@
             
 
             function confirmRemoveDisk(){
+                /*
                 let raidName = raidManager.removePendingSourceVol.split("/").pop();
                 var apiObject = {
                     api: "../system/disk/raid/removeMemeber",
@@ -365,7 +419,7 @@
                         raidDev:  raidManager.removePendingSourceVol,
                         memDev: raidManager.removePendingDisk
                     },
-                    title: `<i class='yellow exclamation triangle icon'></i> REMOVE DISK FROM RAID VOLUME <i class='yellow exclamation triangle icon'></i>`,
+                    title: `<i class='yellow exclamation triangle icon'></i> Remove Disk From Volume <i class='yellow exclamation triangle icon'></i>`,
                     desc: `Confirm remove ${raidManager.removePendingDisk} from ${raidManager.removePendingSourceVol}`,
                     thisuser: true, //This username as default, set to false for entering other user
                     method: "POST",
@@ -383,11 +437,26 @@
                     parent: ao_module_windowID,
                     callback: "handleRemoveDiskCallback"
                 });
+                */
+
+                $.ajax({
+                    url: "../../system/disk/raid/removeMemeber",
+                    data: {
+                        raidDev:  raidManager.removePendingSourceVol,
+                        memDev: raidManager.removePendingDisk
+                    },
+                    method: "POST",
+                    success: function(data){
+                        handleRemoveDiskCallback(data);
+                    }
+                })
             }
 
             //Remove disk completed
             window.handleRemoveDiskCallback = function(succ){
                 console.log(data);
+                raidManager.removePendingDisk = "";
+                raidManager.removePendingSourceVol = "";
                 setTimeout(function(){
                     reloadRAIDVolDetail();
                 }, 300);
@@ -489,7 +558,8 @@
 
                         //Update the active disks info
                         $("#RAIDOverviewDiskpath").html(data.DevicePath + ` <span class="mdevice">(${data.RaidLevel.toUpperCase()})</span>`);
-                        $("#RAIDOverviewDetails").text(data.UUID + " | State: " + capitalize(data.State));
+                        $("#RAIDOverviewDetails").text("State: " + capitalize(data.State));
+                        $("#RAIDUUID").text(data.UUID);
                         $("#RAIDActiveDevices").text(data.ActiveDevices);
                         $("#RAIDWorkingDevices").text(data.WorkingDevices);
                         $("#RAIDFailedDevices").text(data.FailedDevices);
@@ -561,11 +631,9 @@
                                 </div>
                                 <div class="raidDeviceOptions">
                                     <div class="content">
-                                        <button class="ui tiny basic button"><i class="ui info circle grey icon"></i> SMART</button>
-                                        <button class="ui tiny basic button removeDiskBtn ${diskIsFailed?"faulty":"normal"}" onclick="removeDisk('${deviceName}','${driveName}');"><i class="ui red trash icon"></i> Remove Disk from Volume</button>
+                                        <button class="ui tiny basic button removeDiskBtn ${diskIsFailed?"faulty":"normal"}" onclick="removeDisk('${deviceName}','${driveName}');"><i class="ui red trash icon"></i> Remove Disk</button>
                                     </div>
                                 </div>
-                                <div class="ui divider"></div>
                             </div>`);
 
                             if (driveName != "" && drivePath != ""){

+ 16 - 1
web/SystemAO/disk/raid/newdisk.html

@@ -69,7 +69,7 @@
               Confirm Disk Choice
             </div>
             <div class="image content">
-              <div class="ui medium image">
+              <div class="ui small image">
                 <img src="./img/drive-format.svg">
               </div>
               <div class="description">
@@ -135,6 +135,8 @@
             }
 
             function confirmAddDisk(){
+                /*
+                //Authreq is bypassed as add disk seems don't need that much security
                 var apiObject = {
                     api: "../system/disk/raid/addMemeber",
                     data: {
@@ -158,6 +160,19 @@
                     parent: ao_module_windowID,
                     callback: "handleDiskAddCallback"
                 });
+                */
+
+                $.ajax({
+                    url: "../../../system/disk/raid/addMemeber",
+                    data:{
+                        raidDev:  editingMD.md,
+                        memDev: selectedDiskID
+                    },
+                    method: "POST",
+                    success: function(data){
+                        handleDiskAddCallback(data);
+                    } 
+                })
             }
 
             window.handleDiskAddCallback = function(data){