Эх сурвалжийг харах

Added list backup drive api

TC pushbot 5 4 жил өмнө
parent
commit
aa875b10a8

+ 66 - 0
backup.go

@@ -24,6 +24,72 @@ func backup_init() {
 	router.HandleFunc("/system/backup/listRestorable", backup_listRestorable)
 	router.HandleFunc("/system/backup/restoreFile", backup_restoreSelected)
 	router.HandleFunc("/system/backup/snapshotSummary", backup_renderSnapshotSummary)
+	router.HandleFunc("/system/backup/listAll", backup_listAllBackupDisk)
+}
+
+//List all backup disk info
+func backup_listAllBackupDisk(w http.ResponseWriter, r *http.Request) {
+	//Get all fsh from the system
+	runningBackupTasks := []*hybridBackup.BackupTask{}
+
+	//Render base storage pool
+	for _, fsh := range baseStoragePool.Storages {
+		if fsh.Hierarchy == "backup" {
+			task, err := baseStoragePool.HyperBackupManager.GetTaskByBackupDiskID(fsh.UUID)
+			if err != nil {
+				continue
+			}
+
+			runningBackupTasks = append(runningBackupTasks, task)
+		}
+	}
+
+	//Render group storage pool
+	for _, pg := range permissionHandler.PermissionGroups {
+		for _, fsh := range pg.StoragePool.Storages {
+			task, err := pg.StoragePool.HyperBackupManager.GetTaskByBackupDiskID(fsh.UUID)
+			if err != nil {
+				continue
+			}
+
+			runningBackupTasks = append(runningBackupTasks, task)
+		}
+	}
+
+	type backupDrive struct {
+		DiskUID             string //The backup disk UUID
+		DiskName            string // The Backup disk name
+		ParentUID           string //Parent disk UID
+		ParentName          string //Parent disk name
+		BackupMode          string //The backup mode of the drive
+		LastBackupCycleTime int64  //Last backup timestamp
+		BackupCycleCount    int64  //How many backup cycle has proceeded since the system startup
+	}
+
+	backupDrives := []*backupDrive{}
+	for _, task := range runningBackupTasks {
+		diskFsh, diskErr := GetFsHandlerByUUID(task.DiskUID)
+		parentFsh, parentErr := GetFsHandlerByUUID(task.ParentUID)
+
+		//Check for error in getting FS Handler
+		if diskErr != nil || parentErr != nil {
+			sendErrorResponse(w, "Unable to get backup task info from backup disk: "+task.DiskUID)
+			return
+		}
+
+		backupDrives = append(backupDrives, &backupDrive{
+			DiskUID:             diskFsh.UUID,
+			DiskName:            diskFsh.Name,
+			ParentUID:           parentFsh.UUID,
+			ParentName:          parentFsh.Name,
+			BackupMode:          task.Mode,
+			LastBackupCycleTime: task.LastCycleTime,
+			BackupCycleCount:    task.CycleCounter,
+		})
+	}
+
+	js, _ := json.Marshal(backupDrives)
+	sendJSONResponse(w, string(js))
 }
 
 //Generate a snapshot summary for vroot

+ 15 - 7
mod/disk/hybridBackup/hybridBackup.go

@@ -161,7 +161,10 @@ func (m *Manager) StopTask(jobname string) {
 
 //Stop all managed handlers
 func (m *Manager) Close() error {
-	m.StopTicker <- true
+	if m != nil {
+		m.StopTicker <- true
+	}
+
 	return nil
 }
 
@@ -193,28 +196,33 @@ func (backupConfig *BackupTask) HandleBackupProcess() (string, error) {
 			backupConfig.LastCycleTime = time.Now().Unix()
 		}
 		log.Println("[HybridBackup] Basic backup executed: " + backupConfig.ParentUID + ":/ -> " + backupConfig.DiskUID + ":/")
-		return executeBackup(backupConfig, deepBackup)
+		//Add one to the cycle counter
+		backupConfig.CycleCounter++
+		executeBackup(backupConfig, deepBackup)
 	} else if backupConfig.Mode == "nightly" {
 		if time.Now().Unix()-backupConfig.LastCycleTime >= 86400 {
 			//24 hours from last backup. Execute deep backup now
 			executeBackup(backupConfig, true)
 			backupConfig.LastCycleTime = time.Now().Unix()
 			log.Println("[HybridBackup] Executing nightly backup: " + backupConfig.ParentUID + ":/ -> " + backupConfig.DiskUID + ":/")
+
+			//Add one to the cycle counter
+			backupConfig.CycleCounter++
 		}
 
 	} else if backupConfig.Mode == "version" {
-		//Do a versioning backup
-		if time.Now().Unix()-backupConfig.LastCycleTime >= 86400 || backupConfig.CycleCounter == 0 {
+		//Do a versioning backup every 6 hours
+		if time.Now().Unix()-backupConfig.LastCycleTime >= 21600 || backupConfig.CycleCounter == 0 {
 			//Scheduled backup or initial backup
 			executeVersionBackup(backupConfig)
 			backupConfig.LastCycleTime = time.Now().Unix()
 			log.Println("[HybridBackup] Executing backup schedule: " + backupConfig.ParentUID + ":/ -> " + backupConfig.DiskUID + ":/")
+
+			//Add one to the cycle counter
+			backupConfig.CycleCounter++
 		}
 	}
 
-	//Add one to the cycle counter
-	backupConfig.CycleCounter++
-
 	//Return the log information
 	return "", nil
 }

+ 23 - 0
mod/filesystem/config.go

@@ -3,6 +3,7 @@ package filesystem
 import (
 	"encoding/json"
 	"errors"
+	"strings"
 )
 
 //FileSystem configuration. Append more lines if required.
@@ -46,21 +47,43 @@ func ValidateOption(options *FileSystemOption) error {
 		return errors.New("Path not exists, given: " + options.Path)
 	}
 
+	//Check if access mode is supported
 	if !inSlice([]string{"readonly", "readwrite"}, options.Access) {
 		return errors.New("Not supported access mode: " + options.Access)
 	}
 
+	//Check if hierarchy is supported
 	if !inSlice([]string{"user", "public", "backup"}, options.Hierarchy) {
 		return errors.New("Not supported hierarchy: " + options.Hierarchy)
 	}
 
+	//Check disk format is supported
 	if !inSlice([]string{"ext4", "ext2", "ext3", "fat", "vfat", "ntfs"}, options.Filesystem) {
 		return errors.New("Not supported file system type: " + options.Filesystem)
 	}
 
+	//Check if mount point exists
 	if options.Mountpt != "" && !fileExists(options.Mountpt) {
 		return errors.New("Mount point not exists: " + options.Mountpt)
 	}
 
+	//This drive is backup drive
+	if options.Hierarchy == "backup" {
+		//Check if parent uid is not empty
+		if strings.TrimSpace(options.Parentuid) == "" {
+			return errors.New("Invalid backup source ID given")
+		}
+
+		//Check if the backup drive source and target are not the same drive
+		if options.Parentuid == options.Uuid {
+			return errors.New("Recursive backup detected. You cannot backup the backup drive itself.")
+		}
+
+		//Check if the backup mode exists
+		if !inSlice([]string{"basic", "nightly", "version"}, options.BackupMode) {
+			return errors.New("Invalid backup mode given")
+		}
+	}
+
 	return nil
 }

+ 1 - 1
mod/storage/storage.go

@@ -63,7 +63,7 @@ func NewStoragePool(fsHandlers []*fs.FileSystemHandler, owner string) (*StorageP
 			if parentExists {
 				backupManager.AddTask(&backupConfig)
 			} else {
-				log.Println("*ERROR* Backup disk " + backupConfig.DiskUID + ":/ source disk not found: " + backupConfig.ParentUID + ":/ not exists!")
+				log.Println("*ERROR* Backup disk " + backupConfig.DiskUID + ":/ source disk not found: " + backupConfig.ParentUID + ":/ not exists or it is from other storage pool!")
 			}
 
 		}

+ 11 - 4
storage.pool.go

@@ -81,7 +81,7 @@ func HandleFSHEdit(w http.ResponseWriter, r *http.Request) {
 	} else if opr == "set" {
 		//Set
 		newFsOption := buildOptionFromRequestForm(r)
-		log.Println(newFsOption)
+		//log.Println(newFsOption)
 
 		//Read and remove the original settings from the config file
 		err := setFSHConfigByGroupAndId(group, uuid, newFsOption)
@@ -115,6 +115,10 @@ func getFSHConfigFromGroupAndUUID(group string, uuid string) (*fs.FileSystemOpti
 		return nil, errors.New("Configuration file not found")
 	}
 
+	if !fileExists(filepath.Dir(targerFile)) {
+		os.MkdirAll(filepath.Dir(targerFile), 0775)
+	}
+
 	//Load and parse the file
 	configContent, err := ioutil.ReadFile(targerFile)
 	if err != nil {
@@ -154,6 +158,10 @@ func setFSHConfigByGroupAndId(group string, uuid string, options fs.FileSystemOp
 		return errors.New("Configuration file not found")
 	}
 
+	if !fileExists(filepath.Dir(targerFile)) {
+		os.MkdirAll(filepath.Dir(targerFile), 0775)
+	}
+
 	//Load and parse the file
 	configContent, err := ioutil.ReadFile(targerFile)
 	if err != nil {
@@ -180,7 +188,7 @@ func setFSHConfigByGroupAndId(group string, uuid string, options fs.FileSystemOp
 
 	//Write config back to file
 	js, _ := json.MarshalIndent(newConfig, "", " ")
-	return ioutil.WriteFile(targerFile, js, 0755)
+	return ioutil.WriteFile(targerFile, js, 777)
 }
 
 //Handle Storage Pool toggle on-off
@@ -397,7 +405,7 @@ func HandleStoragePoolRemove(w http.ResponseWriter, r *http.Request) {
 	if len(newConfigs) > 0 {
 		js, _ := json.Marshal(newConfigs)
 		resultingJson := pretty.Pretty(js)
-		ioutil.WriteFile(targetConfigFile, resultingJson, 755)
+		ioutil.WriteFile(targetConfigFile, resultingJson, 777)
 	} else {
 		os.Remove(targetConfigFile)
 	}
@@ -431,7 +439,6 @@ func buildOptionFromRequestForm(r *http.Request) fs.FileSystemOption {
 }
 
 func HandleStorageNewFsHandler(w http.ResponseWriter, r *http.Request) {
-
 	newFsOption := buildOptionFromRequestForm(r)
 
 	type errorObject struct {

+ 2 - 2
web/SystemAO/storage/fshedit.html

@@ -106,8 +106,8 @@
             <p class="backuponly">Backup Settings</p>
             <div class="field backuponly">
                 <label>Backup Virtual Disk UID</label>
-                <div class="ui selection dropdown">
-                    <input type="hidden" autocomplete="false" name="parentuid" value="">
+                <div class="ui selection dropdown disabled">
+                    <input type="hidden" autocomplete="false" name="parentuid" value="" readonly="true">
                     <i class="dropdown icon"></i>
                     <div class="default text">Storage Hierarchy</div>
                     <div class="menu" id="backupIdList">

+ 1 - 1
web/SystemAO/storage/poolEditor.html

@@ -344,7 +344,7 @@
 
                 //Render the backup id list
                 $("#backupIdList").html(``);
-                $.get("../../system/storage/pool/list", function(data){
+                $.get("../../system/storage/pool/list?filter=" + editingStoragePool, function(data){
                      data.forEach(usergroup => {
                          if (usergroup.Storages != null){
                             usergroup.Storages.forEach(storage => {