فهرست منبع

Added raid grow

aroz 1 سال پیش
والد
کامیت
48c3a0af9b

+ 1 - 0
disk.go

@@ -171,6 +171,7 @@ func DiskServiceInit() {
 					}
 					raidManager.HandleForceAssembleReload(w, r)
 				})
+				adminRouter.HandleFunc("/system/disk/raid/grow", raidManager.HandleGrowRAIDArray)
 				adminRouter.HandleFunc("/system/disk/raid/format", raidManager.HandleFormatRaidDevice)
 				adminRouter.HandleFunc("/system/disk/raid/detail", raidManager.HandleLoadArrayDetail)
 				adminRouter.HandleFunc("/system/disk/raid/devinfo", raidManager.HandlListChildrenDeviceInfo)

+ 40 - 0
mod/disk/raid/handler.go

@@ -587,3 +587,43 @@ func (m *Manager) HandleForceAssembleReload(w http.ResponseWriter, r *http.Reque
 
 	utils.SendOK(w)
 }
+
+// Grow the raid array to maxmium possible size of the current disks
+func (m *Manager) HandleGrowRAIDArray(w http.ResponseWriter, r *http.Request) {
+	deviceName, err := utils.PostPara(r, "raidDev")
+	if err != nil {
+		utils.SendErrorResponse(w, "raid device not given")
+		return
+	}
+
+	if !m.RAIDDeviceExists(deviceName) {
+		utils.SendErrorResponse(w, "target raid device not exists")
+		return
+	}
+
+	//Check the raid is healthy and ok for expansion
+	raidNotHealthy, err := m.RAIDArrayContainsFailedDisks(deviceName)
+	if err != nil {
+		utils.SendErrorResponse(w, "unable to check health state before expansion")
+		return
+	}
+	if raidNotHealthy {
+		utils.SendErrorResponse(w, "expand can only be performed on a healthy array")
+		return
+	}
+
+	//Expand the raid array
+	err = m.GrowRAIDDevice(deviceName)
+	if err != nil {
+		utils.SendErrorResponse(w, err.Error())
+		return
+	}
+
+	err = m.RestartRAIDService()
+	if err != nil {
+		utils.SendErrorResponse(w, err.Error())
+		return
+	}
+
+	utils.SendOK(w)
+}

+ 18 - 0
mod/disk/raid/mdadm.go

@@ -298,3 +298,21 @@ func (m *Manager) AddDisk(mdDevice, diskPath string) error {
 	}
 	return nil
 }
+
+// GrowRAIDDevice grows the specified RAID device to its maximum size
+func (m *Manager) GrowRAIDDevice(deviceName string) error {
+	//Prevent anyone passing /dev/md0 into the deviceName field
+	deviceName = strings.TrimPrefix(deviceName, "/dev/")
+
+	// Construct the mdadm command
+	cmd := exec.Command("sudo", "mdadm", "--grow", fmt.Sprintf("/dev/%s", deviceName), "--size=max")
+
+	// Execute the command
+	output, err := cmd.CombinedOutput()
+	if err != nil {
+		return fmt.Errorf("failed to grow RAID device: %v, output: %s", err, string(output))
+	}
+
+	fmt.Printf("[RAID] Successfully grew RAID device %s. Output: %s\n", deviceName, string(output))
+	return nil
+}

+ 9 - 0
mod/disk/raid/raidutils.go

@@ -206,3 +206,12 @@ func (m *Manager) RAIDDeviceExists(devicePath string) bool {
 	_, err := m.GetRAIDDeviceByDevicePath(devicePath)
 	return err == nil
 }
+
+// Check if a RAID contain disk that failed or degraded given the devicePath, e.g. md0 or /dev/md0
+func (m *Manager) RAIDArrayContainsFailedDisks(devicePath string) (bool, error) {
+	raidDeviceInfo, err := m.GetRAIDInfo(devicePath)
+	if err != nil {
+		return false, err
+	}
+	return strings.Contains(raidDeviceInfo.State, "degraded") || strings.Contains(raidDeviceInfo.State, "faulty"), nil
+}

+ 53 - 1
mod/fileservers/servers/samba/handlers.go

@@ -186,7 +186,59 @@ func (s *ShareManager) AddSambaShare(w http.ResponseWriter, r *http.Request) {
 	utils.SendOK(w)
 }
 
-// Remove a samba share by name
+// Delete a user samba share, that share must only contains the current user / owner
+func (s *ShareManager) DelUserSambaShare(w http.ResponseWriter, r *http.Request) {
+	//Get the user info
+	userInfo, err := s.UserHandler.GetUserInfoFromRequest(w, r)
+	if err != nil {
+		utils.SendErrorResponse(w, "permission denied")
+		return
+	}
+
+	shareName, err := utils.PostPara(r, "name")
+	if err != nil {
+		utils.SendErrorResponse(w, "share name not given")
+		return
+	}
+
+	//Check if share exists
+	targetShare, err := s.GetShareByName(shareName)
+	if err != nil {
+		utils.SendErrorResponse(w, err.Error())
+		return
+	}
+
+	//Check if the user can access this share
+	if !s.UserCanAccessShare(targetShare, userInfo.Username) {
+		utils.SendErrorResponse(w, "share access denied")
+		return
+	}
+
+	//Check if the user is the only user in the share access list
+	if len(targetShare.ValidUsers) == 1 && strings.EqualFold(targetShare.ValidUsers[0], userInfo.Username) {
+		//This share is own by this user and this user is the only one who can access it
+		//remove user access will create trash in the smb.conf folder. Remove the whole folder entirely.
+		err = s.RemoveSambaShareConfig(targetShare.Name)
+		if err != nil {
+			utils.SendErrorResponse(w, err.Error())
+			return
+		}
+		utils.SendOK(w)
+		return
+	}
+
+	//Share also contains other users. Only remove user to that share
+	err = s.RemoveUserFromSambaShare(targetShare.Name, userInfo.Username)
+	if err != nil {
+		utils.SendErrorResponse(w, err.Error())
+		return
+	}
+	utils.SendOK(w)
+
+}
+
+// Remove a samba share by name, can remove any share by name, should be for admin only
+// call to DelUserSambaShare for non-admin uses
 func (s *ShareManager) DelSambaShare(w http.ResponseWriter, r *http.Request) {
 	shareName, err := utils.PostPara(r, "name")
 	if err != nil {

+ 1 - 1
network.go

@@ -388,7 +388,7 @@ func FileServerInit() {
 		})
 		adminRouter.HandleFunc("/system/storage/samba/deactivate", SambaShareManager.DeactiveUserAccount)
 		adminRouter.HandleFunc("/system/storage/samba/myshare", SambaShareManager.HandleUserSmbStatusList)
-
+		//adminRouter.HandleFunc("/system/storage/samba/myshare/delete", SambaShareManager.DelUserSambaShare)
 		adminRouter.HandleFunc("/system/storage/samba/status", SambaShareManager.SmbdStates)
 		adminRouter.HandleFunc("/system/storage/samba/list", SambaShareManager.ListSambaShares)
 		adminRouter.HandleFunc("/system/storage/samba/add", SambaShareManager.AddSambaShare)

+ 4 - 4
web/SystemAO/advance/autologin.html

@@ -77,11 +77,11 @@
                         </div>
                     </div>
                 </div>
-                <div id="adminwarning" class="ui yellow segment" style="display:none">
+                <div id="adminwarning" class="ui yellow message" style="display:none">
                     <i class="info circle icon"></i> We do not recommend enabling auto login on Administrator accounts due to security issues. Click <a href="../vendor/public/autoLoginForAdmin.html" target="_blank">HERE</a> to learn more.
                 </div>
-                <button id="ntb" onclick="newToken(event);" class="ui green disabled button" type="submit">New Token</button>
-                <button onclick="refreshTokenList();" class="ui blue button"><i class="refresh icon"></i>Refresh List</button>
+                <button id="ntb" onclick="newToken(event);" class="ui green basic disabled button" type="submit"><i class="ui add circle icon"></i> New Token</button>
+                <button onclick="refreshTokenList();" class="ui basic blue button"><i class="blue refresh icon"></i>Refresh List</button>
                 <div class="ui green segment" style="display:none;">
                     <h4>Token Created: </h4>
                     <p id="newTokenDisplay"></p>
@@ -168,7 +168,7 @@
                     if (data.length == 0){
                         $("#tokenlist").append(`
                         <div class="item">
-                            <i class="question icon"></i>
+                            <i class="ui green check circle icon"></i>
                             <div class="content" style="font-family: monospace;">
                                No Token Found
                             </div>

+ 39 - 11
web/SystemAO/disk/raid/index.html

@@ -234,7 +234,7 @@
                                 <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">
+                                <button onclick="expandRAIDArray();" title="Expand volume to fit disks capacity" class="circular small basic ui button">
                                     <i class="purple expand icon"></i> Expand Volume
                                 </button>
                             </div>
@@ -335,6 +335,7 @@
                 removePendingDisk: "",
                 removePendingSourceVol: ""
             };
+            var raidInfoTicker = undefined;
 
             /* Information Update Ticker */
             function RAIDInfoUpdateTicker(){
@@ -381,16 +382,23 @@
                             }
                         }
 
-                        //Update again in 3s
-                        setTimeout(RAIDInfoUpdateTicker, 5000);
+                        //Update again later
+                        raidInfoTicker = setTimeout(RAIDInfoUpdateTicker, 5000);
                     });
                     
+                }else{
+                    //Release the ticker
+                    console.log("RAID status ticker released");
+                    raidInfoTicker = undefined;
                 }
                 
             }
 
             //Set the ticker
-            setTimeout(RAIDInfoUpdateTicker, 1000);
+            if (raidInfoTicker == undefined){
+                console.log("RAID status ticker started");
+                raidInfoTicker = setTimeout(RAIDInfoUpdateTicker, 1000);
+            }
 
             /* RAID Create Functions */
             function addNewRaidVolume(){
@@ -411,7 +419,7 @@
                 setTimeout(function(){
                     reloadRAIDVolDetail();
                     if (data.error != undefined){
-                        msgbox(data.error, false, 5000);
+                        msgbox(capitalize(data.error), false, 5000);
                     }else{
                         msgbox("New RAID volume created");
                     }
@@ -458,7 +466,7 @@
             window.handleRAIDRemoveCallback = function(data){
                 if (data.error != undefined){
                     //Something went wrong
-                    msgbox(data.error, false, 5000);
+                    msgbox(capitalize(data.error), false, 5000);
                 }else{
                     setTimeout(function(){
                         //RAID volume not exist anymore. Reset everything
@@ -494,6 +502,26 @@
                 }, 300);
             }
 
+            /* RAID Array Expand */
+            function expandRAIDArray(arrayName=raidManager.editingArray){
+                $.ajax({
+                    url: "../../system/disk/raid/grow",
+                    method: "POST",
+                    data: {
+                        "raidDev": arrayName,
+                    },
+                    success: function(data){
+                        if (data.error != undefined){
+                            msgbox(capitalize(data.error), false);
+                        }else{
+                            msgbox("mdadm grow operation started");
+                            reloadRAIDVolDetail();
+                        }
+
+                    }
+                })
+            }
+
             /* Disk Remove Functions */
             function removeDisk(arrayName, diskPath){
                 console.log(arrayName, diskPath);
@@ -576,11 +604,11 @@
                 } 
             }
 
-            function loadRAIDVolDetail(deviceName){
-                function capitalize(string) {
-                    return string.charAt(0).toUpperCase() + string.slice(1);
-                }
+            function capitalize(string) {
+                return string.charAt(0).toUpperCase() + string.slice(1);
+            }
 
+            function loadRAIDVolDetail(deviceName){
                 function bytesToSize(bytes) {
                     var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];
                     if (bytes == 0) return 'n/a';
@@ -846,7 +874,7 @@
             window.handleForceAssembleCallback = function(data){
                 if (data.error != undefined){
                     //Something went wrong
-                    msgbox(data.error, false, 5000);
+                    msgbox(capitalize(data.error), false, 5000);
                 }else{
                     setTimeout(function(){
                         //Reload all RAID volumes