backup.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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. router.HandleFunc("/system/backup/snapshotSummary", backup_renderSnapshotSummary)
  22. }
  23. //Generate a snapshot summary for vroot
  24. func backup_renderSnapshotSummary(w http.ResponseWriter, r *http.Request) {
  25. //Get user accessiable storage pools
  26. userinfo, err := userHandler.GetUserInfoFromRequest(w, r)
  27. if err != nil {
  28. sendErrorResponse(w, "User not logged in")
  29. return
  30. }
  31. //Get Backup disk ID from request
  32. bdid, err := mv(r, "bdid", true)
  33. if err != nil {
  34. sendErrorResponse(w, "Invalid backup disk ID given")
  35. return
  36. }
  37. //Get target snapshot name from request
  38. snapshot, err := mv(r, "snapshot", true)
  39. if err != nil {
  40. sendErrorResponse(w, "Invalid snapshot name given")
  41. return
  42. }
  43. //Get fsh from the id
  44. fsh, err := GetFsHandlerByUUID(bdid)
  45. if err != nil {
  46. sendErrorResponse(w, err.Error())
  47. return
  48. }
  49. //Get parent disk hierarcy
  50. parentDiskID, err := userinfo.HomeDirectories.HyperBackupManager.GetParentDiskIDByRestoreDiskID(fsh.UUID)
  51. if err != nil {
  52. sendErrorResponse(w, err.Error())
  53. return
  54. }
  55. parentFsh, err := GetFsHandlerByUUID(parentDiskID)
  56. if err != nil {
  57. sendErrorResponse(w, err.Error())
  58. return
  59. }
  60. //Get task by the backup disk id
  61. task, err := userinfo.HomeDirectories.HyperBackupManager.GetTaskByBackupDiskID(fsh.UUID)
  62. if err != nil {
  63. sendErrorResponse(w, err.Error())
  64. return
  65. }
  66. if task.Mode == "version" {
  67. //Generate snapshot summary
  68. var summary *hybridBackup.SnapshotSummary
  69. if parentFsh.Hierarchy == "user" {
  70. s, err := task.GenerateSnapshotSummary(snapshot, &userinfo.Username)
  71. if err != nil {
  72. sendErrorResponse(w, err.Error())
  73. return
  74. }
  75. summary = s
  76. } else {
  77. s, err := task.GenerateSnapshotSummary(snapshot, nil)
  78. if err != nil {
  79. sendErrorResponse(w, err.Error())
  80. return
  81. }
  82. summary = s
  83. }
  84. js, _ := json.Marshal(summary)
  85. sendJSONResponse(w, string(js))
  86. } else {
  87. sendErrorResponse(w, "Unable to genreate snapshot summary: Backup mode is not snapshot")
  88. return
  89. }
  90. }
  91. //Restore a given file
  92. func backup_restoreSelected(w http.ResponseWriter, r *http.Request) {
  93. //Get user accessiable storage pools
  94. userinfo, err := userHandler.GetUserInfoFromRequest(w, r)
  95. if err != nil {
  96. sendErrorResponse(w, "User not logged in")
  97. return
  98. }
  99. //Get Backup disk ID from request
  100. bdid, err := mv(r, "bdid", true)
  101. if err != nil {
  102. sendErrorResponse(w, "Invalid backup disk ID given")
  103. return
  104. }
  105. //Get fsh from the id
  106. fsh, err := GetFsHandlerByUUID(bdid)
  107. if err != nil {
  108. sendErrorResponse(w, err.Error())
  109. return
  110. }
  111. //Get the relative path for the restorable file
  112. relpath, err := mv(r, "relpath", true)
  113. if err != nil {
  114. sendErrorResponse(w, "Invalid relative path given")
  115. return
  116. }
  117. //Handle restore of the file
  118. err = userinfo.HomeDirectories.HyperBackupManager.HandleRestore(fsh.UUID, relpath, &userinfo.Username)
  119. if err != nil {
  120. sendErrorResponse(w, err.Error())
  121. return
  122. }
  123. type RestoreResult struct {
  124. RestoreDiskID string
  125. TargetDiskID string
  126. RestoredVirtualPath string
  127. }
  128. result := RestoreResult{
  129. RestoreDiskID: fsh.UUID,
  130. }
  131. //Get access path for this file
  132. parentDiskId, err := userinfo.HomeDirectories.HyperBackupManager.GetParentDiskIDByRestoreDiskID(fsh.UUID)
  133. if err != nil {
  134. //Unable to get parent disk ID???
  135. } else {
  136. //Get the path of the parent disk
  137. parentDiskHandler, err := GetFsHandlerByUUID(parentDiskId)
  138. if err == nil {
  139. //Join the result to create a virtual path
  140. assumedRestoreRealPath := filepath.ToSlash(filepath.Join(parentDiskHandler.Path, relpath))
  141. restoreVpath, err := userinfo.RealPathToVirtualPath(assumedRestoreRealPath)
  142. if err == nil {
  143. result.RestoredVirtualPath = restoreVpath
  144. }
  145. result.TargetDiskID = parentDiskId
  146. }
  147. }
  148. js, _ := json.Marshal(result)
  149. sendJSONResponse(w, string(js))
  150. }
  151. //Generate and return a restorable report
  152. func backup_listRestorable(w http.ResponseWriter, r *http.Request) {
  153. //Get user accessiable storage pools
  154. userinfo, err := userHandler.GetUserInfoFromRequest(w, r)
  155. if err != nil {
  156. sendErrorResponse(w, "User not logged in")
  157. return
  158. }
  159. //Get Vroot ID from request
  160. vroot, err := mv(r, "vroot", true)
  161. if err != nil {
  162. sendErrorResponse(w, "Invalid vroot given")
  163. return
  164. }
  165. //Get fsh from the id
  166. fsh, err := GetFsHandlerByUUID(vroot)
  167. if err != nil {
  168. sendErrorResponse(w, err.Error())
  169. return
  170. }
  171. userBackupManager := userinfo.HomeDirectories.HyperBackupManager
  172. //Get the user's storage pool and list restorable by the user's storage pool access
  173. restorableReport, err := userBackupManager.ListRestorable(fsh.UUID)
  174. if err != nil {
  175. sendErrorResponse(w, err.Error())
  176. return
  177. }
  178. //Get and check if the parent disk has a user Hierarcy
  179. paretnfsh, err := GetFsHandlerByUUID(restorableReport.ParentUID)
  180. if err != nil {
  181. sendErrorResponse(w, err.Error())
  182. return
  183. }
  184. result := hybridBackup.RestorableReport{
  185. ParentUID: restorableReport.ParentUID,
  186. RestorableFiles: []*hybridBackup.RestorableFile{},
  187. }
  188. if paretnfsh.Hierarchy == "user" {
  189. //The file system is user based. Filter out those file that is not belong to this user
  190. for _, restorableFile := range restorableReport.RestorableFiles {
  191. if restorableFile.IsSnapshot {
  192. //Is snapshot. Always allow access
  193. result.RestorableFiles = append(result.RestorableFiles, restorableFile)
  194. } else {
  195. //Is file
  196. fileAbsPath := filepath.Join(fsh.Path, restorableFile.RelpathOnDisk)
  197. _, err := userinfo.RealPathToVirtualPath(fileAbsPath)
  198. if err != nil {
  199. //Cannot translate this file. That means the file is not owned by this user
  200. } else {
  201. //Can translate the path.
  202. result.RestorableFiles = append(result.RestorableFiles, restorableFile)
  203. }
  204. }
  205. }
  206. } else {
  207. result = restorableReport
  208. }
  209. js, _ := json.Marshal(result)
  210. sendJSONResponse(w, string(js))
  211. }