|
@@ -2,7 +2,11 @@ package main
|
|
|
|
|
|
import (
|
|
|
"encoding/json"
|
|
|
+ "log"
|
|
|
"net/http"
|
|
|
+ "path/filepath"
|
|
|
+
|
|
|
+ "imuslab.com/arozos/mod/disk/hybridBackup"
|
|
|
|
|
|
prout "imuslab.com/arozos/mod/prouter"
|
|
|
)
|
|
@@ -17,9 +21,89 @@ func backup_init() {
|
|
|
},
|
|
|
})
|
|
|
|
|
|
+ //Register API endpoints
|
|
|
router.HandleFunc("/system/backup/listRestorable", backup_listRestorable)
|
|
|
+ router.HandleFunc("/system/backup/restoreFile", backup_restoreSelected)
|
|
|
}
|
|
|
|
|
|
+//Restore a given file
|
|
|
+func backup_restoreSelected(w http.ResponseWriter, r *http.Request) {
|
|
|
+ //Get user accessiable storage pools
|
|
|
+ userinfo, err := userHandler.GetUserInfoFromRequest(w, r)
|
|
|
+ if err != nil {
|
|
|
+ sendErrorResponse(w, "User not logged in")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ //Get Backup disk ID from request
|
|
|
+ bdid, err := mv(r, "bdid", true)
|
|
|
+ if err != nil {
|
|
|
+ sendErrorResponse(w, "Invalid backup disk ID given")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ //Get fsh from the id
|
|
|
+ fsh, err := GetFsHandlerByUUID(bdid)
|
|
|
+ if err != nil {
|
|
|
+ sendErrorResponse(w, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ //Get the relative path for the restorable file
|
|
|
+ relpath, err := mv(r, "relpath", true)
|
|
|
+ if err != nil {
|
|
|
+ sendErrorResponse(w, "Invalid relative path given")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ //Check if the path exists in the backup disk
|
|
|
+ if !fileExists(filepath.Join(fsh.Path, relpath)) {
|
|
|
+ sendErrorResponse(w, "Restore source file not exists")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ //Handle restore of the file
|
|
|
+ err = userinfo.HomeDirectories.HyperBackupManager.HandleRestore(fsh.UUID, relpath)
|
|
|
+ if err != nil {
|
|
|
+ sendErrorResponse(w, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ type RestoreResult struct {
|
|
|
+ RestoreDiskID string
|
|
|
+ TargetDiskID string
|
|
|
+ RestoredVirtualPath string
|
|
|
+ }
|
|
|
+
|
|
|
+ result := RestoreResult{
|
|
|
+ RestoreDiskID: fsh.UUID,
|
|
|
+ }
|
|
|
+
|
|
|
+ //Get access path for this file
|
|
|
+ parentDiskId, err := userinfo.HomeDirectories.HyperBackupManager.GetParentDiskIDByRestoreDiskID(fsh.UUID)
|
|
|
+ if err != nil {
|
|
|
+ //Unable to get parent disk ID???
|
|
|
+
|
|
|
+ } else {
|
|
|
+ //Get the path of the parent disk
|
|
|
+ parentDiskHandler, err := GetFsHandlerByUUID(parentDiskId)
|
|
|
+ if err == nil {
|
|
|
+ //Join the result to create a virtual path
|
|
|
+ assumedRestoreRealPath := filepath.ToSlash(filepath.Join(parentDiskHandler.Path, relpath))
|
|
|
+ restoreVpath, err := userinfo.RealPathToVirtualPath(assumedRestoreRealPath)
|
|
|
+ if err == nil {
|
|
|
+ result.RestoredVirtualPath = restoreVpath
|
|
|
+ }
|
|
|
+ result.TargetDiskID = parentDiskId
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ js, _ := json.Marshal(result)
|
|
|
+ sendJSONResponse(w, string(js))
|
|
|
+}
|
|
|
+
|
|
|
+//Generate and return a restorable report
|
|
|
func backup_listRestorable(w http.ResponseWriter, r *http.Request) {
|
|
|
//Get user accessiable storage pools
|
|
|
userinfo, err := userHandler.GetUserInfoFromRequest(w, r)
|
|
@@ -42,13 +126,44 @@ func backup_listRestorable(w http.ResponseWriter, r *http.Request) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
+ userBackupManager := userinfo.HomeDirectories.HyperBackupManager
|
|
|
+
|
|
|
//Get the user's storage pool and list restorable by the user's storage pool access
|
|
|
- restorableReport, err := userinfo.HomeDirectories.HyperBackupManager.ListRestorable(fsh.UUID)
|
|
|
+ restorableReport, err := userBackupManager.ListRestorable(fsh.UUID)
|
|
|
if err != nil {
|
|
|
sendErrorResponse(w, err.Error())
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- js, _ := json.Marshal(restorableReport)
|
|
|
+ //Get and check if the parent disk has a user Hierarcy
|
|
|
+ paretnfsh, err := GetFsHandlerByUUID(restorableReport.ParentUID)
|
|
|
+ if err != nil {
|
|
|
+ sendErrorResponse(w, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ result := hybridBackup.RestorableReport{
|
|
|
+ ParentUID: restorableReport.ParentUID,
|
|
|
+ }
|
|
|
+
|
|
|
+ log.Println(paretnfsh)
|
|
|
+
|
|
|
+ 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.
|
|
|
+ result.RestorableFiles = append(result.RestorableFiles, restorableFile)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ result = restorableReport
|
|
|
+ }
|
|
|
+
|
|
|
+ js, _ := json.Marshal(result)
|
|
|
sendJSONResponse(w, string(js))
|
|
|
}
|