Kaynağa Gözat

Added ui support for versioning backup restore points

TC pushbot 5 4 yıl önce
ebeveyn
işleme
2ba30fcc22

+ 13 - 6
backup.go

@@ -143,14 +143,21 @@ func backup_listRestorable(w http.ResponseWriter, r *http.Request) {
 	if paretnfsh.Hierarchy == "user" {
 		//The file system is user based. Filter out those file that is not belong to this user
 		for _, restorableFile := range restorableReport.RestorableFiles {
-			fileAbsPath := filepath.Join(fsh.Path, restorableFile.RelpathOnDisk)
-			_, err := userinfo.RealPathToVirtualPath(fileAbsPath)
-			if err != nil {
-				//Cannot translate this file. That means the file is not owned by this user
-			} else {
-				//Can translate the path.
+			if restorableFile.IsSnapshot {
+				//Is snapshot. Always allow access
 				result.RestorableFiles = append(result.RestorableFiles, restorableFile)
+			} else {
+				//Is file
+				fileAbsPath := filepath.Join(fsh.Path, restorableFile.RelpathOnDisk)
+				_, err := userinfo.RealPathToVirtualPath(fileAbsPath)
+				if err != nil {
+					//Cannot translate this file. That means the file is not owned by this user
+				} else {
+					//Can translate the path.
+					result.RestorableFiles = append(result.RestorableFiles, restorableFile)
+				}
 			}
+
 		}
 	} else {
 		result = restorableReport

+ 1 - 0
mod/disk/hybridBackup/compareRoots.go

@@ -47,6 +47,7 @@ func (t *BackupTask) compareRootPaths() ([]*RestorableFile, error) {
 				BackupDiskUID: t.DiskUID,
 				RemainingTime: 86400 - (time.Now().Unix() - value),
 				DeleteTime:    value,
+				IsSnapshot:    false,
 			}
 			results = append(results, &thisFile)
 		}

+ 9 - 0
mod/disk/hybridBackup/hybridBackup.go

@@ -63,6 +63,7 @@ type RestorableFile struct {
 	BackupDiskUID string //The UID of disk that is hold the backup of this file
 	RemainingTime int64  //Remaining time till auto remove
 	DeleteTime    int64  //Delete time
+	IsSnapshot    bool   //Define is this restorable file point to a snapshot instead
 }
 
 //The restorable report
@@ -287,6 +288,14 @@ func (m *Manager) ListRestorable(parentDiskID string) (RestorableReport, error)
 				diffFiles = append(diffFiles, restorable)
 			}
 		} else if task.Mode == "version" {
+			restorableFiles, err := listVersionRestorables(task)
+			if err != nil {
+				//Something went wrong. Skip this
+				continue
+			}
+			for _, restorable := range restorableFiles {
+				diffFiles = append(diffFiles, restorable)
+			}
 
 		} else {
 			//Unknown mode. Skip it

+ 46 - 0
mod/disk/hybridBackup/versionBackup.go

@@ -334,3 +334,49 @@ func fileHashIdentical(srcFile string, matchingFile string) (bool, error) {
 		return true, nil
 	}
 }
+
+//List all restorable for version backup
+func listVersionRestorables(task *BackupTask) ([]*RestorableFile, error) {
+	//Check if mode is set correctly
+	restorableFiles := []*RestorableFile{}
+	if task.Mode != "version" {
+		return restorableFiles, errors.New("This task mode is not supported by this list function")
+	}
+
+	//List directories of the restorable snapshots
+	snapshotPath := filepath.ToSlash(filepath.Clean(filepath.Join(task.DiskPath, "/version/")))
+	filesInSnapshotFolder, err := filepath.Glob(snapshotPath + "/*")
+	if err != nil {
+		return restorableFiles, err
+	}
+
+	//Check if the foler is actually a snapshot
+	avaibleSnapshot := []string{}
+	for _, fileObject := range filesInSnapshotFolder {
+		possibleSnapshotDatalinkFile := filepath.Join(fileObject, "snapshot.datalink")
+		if fileExists(possibleSnapshotDatalinkFile) {
+			//This is a snapshot
+			avaibleSnapshot = append(avaibleSnapshot, fileObject)
+		}
+	}
+
+	//Build restorabe file struct for returning
+	for _, snapshot := range avaibleSnapshot {
+		thisFile := RestorableFile{
+			Filename:      filepath.Base(snapshot),
+			IsHidden:      false,
+			Filesize:      0,
+			RelpathOnDisk: filepath.ToSlash(snapshot),
+			RestorePoint:  task.ParentUID,
+			BackupDiskUID: task.DiskUID,
+			RemainingTime: -1,
+			DeleteTime:    -1,
+			IsSnapshot:    true,
+		}
+
+		restorableFiles = append(restorableFiles, &thisFile)
+	}
+
+	return restorableFiles, nil
+
+}

+ 76 - 13
web/SystemAO/disk/disk_restore.html

@@ -59,6 +59,12 @@
             overflow-y: scroll;
             padding-right: 4px;
         }
+
+        #snapshotList{
+            max-height: 300px;
+            overflow-y: scroll;
+            padding-right: 4px;
+        }
         
         .timeleft{
             width: 30px;
@@ -120,14 +126,22 @@
             <i class="icon remove"></i>
         </button>
        </div>
+       <div id="snapshotList" class="ui middle aligned divided list">
+            <div class="item">
+                <img class="ui mini image nointeract" src="../../img/system/drive-backup.svg">
+                <div class="content">
+                No Restorable Snapshot(s) for this virtual disk.
+                </div>
+            </div>
+        </div>
         <div id="restorableList" class="ui middle aligned divided list">
             <div class="item">
-              <img class="ui mini image nointeract" src="../../img/system/file-notfound.svg">
-              <div class="content">
+                <img class="ui mini image nointeract" src="../../img/system/file-notfound.svg">
+                <div class="content">
                 No Restorable File(s) for this virtual disk.
-              </div>
+                </div>
             </div>
-          </div>
+        </div>
         <div class="ui checkbox">
             <input type="checkbox" name="showhidden" autocomplete="false" onchange="toggleHiddenFiles(this.checked);">
             <label>Show hidden / cache files</label>
@@ -164,7 +178,12 @@
             filedata = JSON.parse(decodeURIComponent(filedata));
             console.log(filedata);
             //Show information on page
-            $("#fileinfo").find(".filename").text(filedata.Filename + ` (${ao_module_utils.formatBytes(filedata.Filesize, 2)})`);
+            if (filedata.IsSnapshot){
+                $("#fileinfo").find(".filename").text("Snapshot " + filedata.Filename);
+            }else{
+                $("#fileinfo").find(".filename").text(filedata.Filename + ` (${ao_module_utils.formatBytes(filedata.Filesize, 2)})`);
+            }
+            
             
             //Hide the filename in relpath
             var shortenRelpath = filedata.RelpathOnDisk.split("/");
@@ -176,6 +195,14 @@
             $("#fileinfo").find(".restorePoint").html('<i class="ui refresh icon"></i> Restore to ' + (filedata.RestorePoint));
             $("#fileinfo").find(".deleteRemainingTime").html('<i class="ui red remove icon"></i> Auto delete in '+ secondsToHms(filedata.RemainingTime));
 
+            if (filedata.IsSnapshot){
+                $("#fileinfo").find(".deleteRemainingTime").hide();
+                $("#fileinfo").find(".deleteTime").hide();
+            }else{
+                $("#fileinfo").find(".deleteRemainingTime").show();
+                $("#fileinfo").find(".deleteTime").show();
+            }
+
             $("#fileinfo").slideDown('fast');
         }
 
@@ -265,15 +292,49 @@
                     if (data.error !== undefined){
                         $("#error").find(".reason").texxt(data.error);
                     }else{
-                      
-                        //Sort the result by latest first
-                        data.RestorableFiles.sort(function(a, b) {
+
+                        //Filter out the restorable snapshot and files
+                        let restorableFiles = [];
+                        let restorableSnapshots = [];
+
+                        data.RestorableFiles.forEach(file => {
+                            if (file.IsSnapshot){
+                                restorableSnapshots.push(file);
+                            }else{
+                                restorableFiles.push(file);
+                                
+                            }
+                        });
+
+                        //Sort the result by latest first (file only)
+                        restorableFiles.sort(function(a, b) {
                             return b.DeleteTime - a.DeleteTime;
                         });
+                        restorableSnapshots.sort(function(a, b) {
+                            return b.Filename > a.Filename;
+                        });
 
-                        //Display the result
+                        //Display the reuslt for restorableSnapshot
+                        $("#snapshotList").html("");
+                        restorableSnapshots.forEach(snapshot => {
+                            let snapshotData = encodeURIComponent(JSON.stringify(snapshot));
+                            $("#snapshotList").append(`<div class="item restorableFile" filedata="${snapshotData}">
+                                <div class="right floated content">
+                                    <div class="ui tiny button" onclick="showFileInfo(this.parentNode.parentNode)">Info</div>
+                                    <div class="ui tiny green button" onclick="restoreThisFile($(this).parent().parent());">Restore</div>
+                                </div>
+                                
+                                <div class="content">
+                                    <p style="word-break: break-all; font-size: 97%"><img class="ui mini spaced image nointeract" src="../../img/system/drive-backup.svg">
+                                        Snapshot ${snapshot.Filename}
+                                    </p>
+                                </div>
+                            </div>`);
+                        })
+
+                        //Display the result for restorableFile
                         $("#restorableList").html("");
-                        data.RestorableFiles.forEach(fileObject => {
+                        restorableFiles.forEach(fileObject => {
                             let thisFileData = encodeURIComponent(JSON.stringify(fileObject));
 
                             var timerIcon = "100.svg";
@@ -321,7 +382,7 @@
                             </div>`);
                         });
 
-                        if (data.RestorableFiles.length == 0){
+                        if (restorableFiles.length == 0){
                             $("#restorableList").html(`<div class="item">
                             <img class="ui mini image nointeract" src="../../img/system/file-notfound.svg">
                             <div class="content">
@@ -330,10 +391,12 @@
                             </div>`);
 
                         }
-
-                        $(".hiddenfile").hide();
                     }
+                    
+
+                    $(".hiddenfile").hide();
                 }
+                
             })
         }