backup.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package main
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "path/filepath"
  6. "imuslab.com/arozos/mod/disk/hybridBackup"
  7. prout "imuslab.com/arozos/mod/prouter"
  8. )
  9. func backup_init() {
  10. //Register HybridBackup storage restore endpoints
  11. router := prout.NewModuleRouter(prout.RouterOption{
  12. AdminOnly: false,
  13. UserHandler: userHandler,
  14. DeniedHandler: func(w http.ResponseWriter, r *http.Request) {
  15. sendErrorResponse(w, "Permission Denied")
  16. },
  17. })
  18. //Register API endpoints
  19. router.HandleFunc("/system/backup/listRestorable", backup_listRestorable)
  20. router.HandleFunc("/system/backup/restoreFile", backup_restoreSelected)
  21. }
  22. //Restore a given file
  23. func backup_restoreSelected(w http.ResponseWriter, r *http.Request) {
  24. //Get user accessiable storage pools
  25. userinfo, err := userHandler.GetUserInfoFromRequest(w, r)
  26. if err != nil {
  27. sendErrorResponse(w, "User not logged in")
  28. return
  29. }
  30. //Get Backup disk ID from request
  31. bdid, err := mv(r, "bdid", true)
  32. if err != nil {
  33. sendErrorResponse(w, "Invalid backup disk ID given")
  34. return
  35. }
  36. //Get fsh from the id
  37. fsh, err := GetFsHandlerByUUID(bdid)
  38. if err != nil {
  39. sendErrorResponse(w, err.Error())
  40. return
  41. }
  42. //Get the relative path for the restorable file
  43. relpath, err := mv(r, "relpath", true)
  44. if err != nil {
  45. sendErrorResponse(w, "Invalid relative path given")
  46. return
  47. }
  48. //Handle restore of the file
  49. err = userinfo.HomeDirectories.HyperBackupManager.HandleRestore(fsh.UUID, relpath)
  50. if err != nil {
  51. sendErrorResponse(w, err.Error())
  52. return
  53. }
  54. type RestoreResult struct {
  55. RestoreDiskID string
  56. TargetDiskID string
  57. RestoredVirtualPath string
  58. }
  59. result := RestoreResult{
  60. RestoreDiskID: fsh.UUID,
  61. }
  62. //Get access path for this file
  63. parentDiskId, err := userinfo.HomeDirectories.HyperBackupManager.GetParentDiskIDByRestoreDiskID(fsh.UUID)
  64. if err != nil {
  65. //Unable to get parent disk ID???
  66. } else {
  67. //Get the path of the parent disk
  68. parentDiskHandler, err := GetFsHandlerByUUID(parentDiskId)
  69. if err == nil {
  70. //Join the result to create a virtual path
  71. assumedRestoreRealPath := filepath.ToSlash(filepath.Join(parentDiskHandler.Path, relpath))
  72. restoreVpath, err := userinfo.RealPathToVirtualPath(assumedRestoreRealPath)
  73. if err == nil {
  74. result.RestoredVirtualPath = restoreVpath
  75. }
  76. result.TargetDiskID = parentDiskId
  77. }
  78. }
  79. js, _ := json.Marshal(result)
  80. sendJSONResponse(w, string(js))
  81. }
  82. //Generate and return a restorable report
  83. func backup_listRestorable(w http.ResponseWriter, r *http.Request) {
  84. //Get user accessiable storage pools
  85. userinfo, err := userHandler.GetUserInfoFromRequest(w, r)
  86. if err != nil {
  87. sendErrorResponse(w, "User not logged in")
  88. return
  89. }
  90. //Get Vroot ID from request
  91. vroot, err := mv(r, "vroot", true)
  92. if err != nil {
  93. sendErrorResponse(w, "Invalid vroot given")
  94. return
  95. }
  96. //Get fsh from the id
  97. fsh, err := GetFsHandlerByUUID(vroot)
  98. if err != nil {
  99. sendErrorResponse(w, err.Error())
  100. return
  101. }
  102. userBackupManager := userinfo.HomeDirectories.HyperBackupManager
  103. //Get the user's storage pool and list restorable by the user's storage pool access
  104. restorableReport, err := userBackupManager.ListRestorable(fsh.UUID)
  105. if err != nil {
  106. sendErrorResponse(w, err.Error())
  107. return
  108. }
  109. //Get and check if the parent disk has a user Hierarcy
  110. paretnfsh, err := GetFsHandlerByUUID(restorableReport.ParentUID)
  111. if err != nil {
  112. sendErrorResponse(w, err.Error())
  113. return
  114. }
  115. result := hybridBackup.RestorableReport{
  116. ParentUID: restorableReport.ParentUID,
  117. RestorableFiles: []*hybridBackup.RestorableFile{},
  118. }
  119. if paretnfsh.Hierarchy == "user" {
  120. //The file system is user based. Filter out those file that is not belong to this user
  121. for _, restorableFile := range restorableReport.RestorableFiles {
  122. if restorableFile.IsSnapshot {
  123. //Is snapshot. Always allow access
  124. result.RestorableFiles = append(result.RestorableFiles, restorableFile)
  125. } else {
  126. //Is file
  127. fileAbsPath := filepath.Join(fsh.Path, restorableFile.RelpathOnDisk)
  128. _, err := userinfo.RealPathToVirtualPath(fileAbsPath)
  129. if err != nil {
  130. //Cannot translate this file. That means the file is not owned by this user
  131. } else {
  132. //Can translate the path.
  133. result.RestorableFiles = append(result.RestorableFiles, restorableFile)
  134. }
  135. }
  136. }
  137. } else {
  138. result = restorableReport
  139. }
  140. js, _ := json.Marshal(result)
  141. sendJSONResponse(w, string(js))
  142. }