backup.go 5.7 KB

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