storage.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. package main
  2. import (
  3. "errors"
  4. "io/ioutil"
  5. "log"
  6. "os"
  7. "path/filepath"
  8. "runtime"
  9. "imuslab.com/arozos/mod/filesystem/hybridBackup"
  10. "imuslab.com/arozos/mod/permission"
  11. fs "imuslab.com/arozos/mod/filesystem"
  12. storage "imuslab.com/arozos/mod/storage"
  13. )
  14. var (
  15. baseStoragePool *storage.StoragePool //base storage pool, all user can access these virtual roots
  16. fsHandlers []*fs.FileSystemHandler //All File system handlers. All opened handles must be registered in here
  17. )
  18. func StorageInit() {
  19. //Load the default handler for the user storage root
  20. if !fileExists(filepath.Clean(*root_directory) + "/") {
  21. os.MkdirAll(filepath.Clean(*root_directory)+"/", 0755)
  22. }
  23. //Start loading the base storage pool
  24. err := LoadBaseStoragePool()
  25. if err != nil {
  26. panic(err)
  27. }
  28. }
  29. func LoadBaseStoragePool() error {
  30. //Use for Debian buster local file system
  31. localFileSystem := "ext4"
  32. if runtime.GOOS == "windows" {
  33. localFileSystem = "ntfs"
  34. }
  35. baseHandler, err := fs.NewFileSystemHandler(fs.FileSystemOption{
  36. Name: "User",
  37. Uuid: "user",
  38. Path: filepath.ToSlash(filepath.Clean(*root_directory)) + "/",
  39. Hierarchy: "user",
  40. Automount: false,
  41. Filesystem: localFileSystem,
  42. })
  43. if err != nil {
  44. log.Println("Failed to initiate user root storage directory: " + *root_directory)
  45. return err
  46. }
  47. fsHandlers = append(fsHandlers, baseHandler)
  48. //Load the tmp folder as storage unit
  49. tmpHandler, err := fs.NewFileSystemHandler(fs.FileSystemOption{
  50. Name: "tmp",
  51. Uuid: "tmp",
  52. Path: filepath.ToSlash(filepath.Clean(*tmp_directory)) + "/",
  53. Hierarchy: "user",
  54. Automount: false,
  55. Filesystem: localFileSystem,
  56. })
  57. if err != nil {
  58. log.Println("Failed to initiate tmp storage directory: " + *tmp_directory)
  59. return err
  60. }
  61. fsHandlers = append(fsHandlers, tmpHandler)
  62. //Load all the storage config from file
  63. rawConfig, err := ioutil.ReadFile(*storage_config_file)
  64. if err != nil {
  65. //File not found. Use internal storage only
  66. log.Println("Storage configuration file not found. Using internal storage only.")
  67. } else {
  68. //Configuration loaded. Initializing handler
  69. externalHandlers, err := fs.NewFileSystemHandlersFromJSON(rawConfig)
  70. if err != nil {
  71. log.Println("Failed to load storage configuration: " + err.Error() + " -- Skipping")
  72. } else {
  73. for _, thisHandler := range externalHandlers {
  74. fsHandlers = append(fsHandlers, thisHandler)
  75. log.Println(thisHandler.Name + " Mounted as " + thisHandler.UUID + ":/")
  76. }
  77. }
  78. }
  79. //Create a base storage pool for all users
  80. sp, err := storage.NewStoragePool(fsHandlers, "system")
  81. if err != nil {
  82. log.Println("Failed to create base Storaeg Pool")
  83. return err
  84. }
  85. //Update the storage pool permission to readwrite
  86. sp.OtherPermission = "readwrite"
  87. baseStoragePool = sp
  88. return nil
  89. }
  90. /*
  91. Initiate the backup handlers for backup drives
  92. This function must be called after the scheduler initiated.
  93. */
  94. func FilesystemDaemonInit() {
  95. for _, thisHandler := range fsHandlers {
  96. if thisHandler.Hierarchy == "backup" {
  97. //This is a backup drive. Generate it handler
  98. backupConfig := thisHandler.HierarchyConfig.(hybridBackup.BackupConfig)
  99. //Get its parent mount point for backup
  100. parentFileSystemHandler, err := GetFsHandlerByUUID(backupConfig.ParentUID)
  101. if err != nil {
  102. log.Println("Virtual Root with UUID: " + backupConfig.ParentUID + " not loaded. Unable to start backup process.")
  103. break
  104. }
  105. backupConfig.JobName = "backup-daemon [" + thisHandler.UUID + "]"
  106. backupConfig.ParentPath = parentFileSystemHandler.Path
  107. backupConfig.CycleCounter = 1
  108. //Debug backup execution
  109. hybridBackup.HandleBackupProcess(&backupConfig)
  110. //Remove the previous job if it exists
  111. if systemScheduler.JobExists(backupConfig.JobName) {
  112. systemScheduler.RemoveJobFromScheduleList(backupConfig.JobName)
  113. }
  114. //Create a scheudler for this disk
  115. systemScheduler.CreateNewScheduledFunctionJob(backupConfig.JobName,
  116. "Backup daemon from "+backupConfig.ParentUID+":/ to "+backupConfig.DiskUID+":/",
  117. 60,
  118. func() (string, error) {
  119. return hybridBackup.HandleBackupProcess(&backupConfig)
  120. },
  121. )
  122. }
  123. //Add other type of handler here
  124. }
  125. }
  126. //Initialize group storage pool
  127. func GroupStoragePoolInit() {
  128. //Mount permission groups
  129. for _, pg := range permissionHandler.PermissionGroups {
  130. //For each group, check does this group has a config file
  131. err := LoadStoragePoolForGroup(pg)
  132. if err != nil {
  133. continue
  134. }
  135. //Do something else, WIP
  136. }
  137. //Start editing interface for Storage Pool Editor
  138. StoragePoolEditorInit()
  139. }
  140. func LoadStoragePoolForGroup(pg *permission.PermissionGroup) error {
  141. expectedConfigPath := "./system/storage/" + pg.Name + ".json"
  142. if fileExists(expectedConfigPath) {
  143. //Read the config file
  144. pgStorageConfig, err := ioutil.ReadFile(expectedConfigPath)
  145. if err != nil {
  146. log.Println("Failed to read config for " + pg.Name + ": " + err.Error())
  147. return errors.New("Failed to read config for " + pg.Name + ": " + err.Error())
  148. }
  149. //Generate fsHandler form json
  150. thisGroupFsHandlers, err := fs.NewFileSystemHandlersFromJSON(pgStorageConfig)
  151. if err != nil {
  152. log.Println("Failed to load storage configuration: " + err.Error())
  153. return errors.New("Failed to load storage configuration: " + err.Error())
  154. }
  155. //Add these to mounted handlers
  156. for _, thisHandler := range thisGroupFsHandlers {
  157. fsHandlers = append(fsHandlers, thisHandler)
  158. log.Println(thisHandler.Name + " Mounted as " + thisHandler.UUID + ":/ for group " + pg.Name)
  159. }
  160. //Create a storage pool from these handlers
  161. sp, err := storage.NewStoragePool(thisGroupFsHandlers, pg.Name)
  162. if err != nil {
  163. log.Println("Failed to create storage pool for " + pg.Name)
  164. return errors.New("Failed to create storage pool for " + pg.Name)
  165. }
  166. //Set other permission to denied by default
  167. sp.OtherPermission = "denied"
  168. //Assign storage pool to group
  169. pg.StoragePool = sp
  170. } else {
  171. //Storage configuration not exists. Fill in the basic information and move to next storage pool
  172. pg.StoragePool.Owner = pg.Name
  173. pg.StoragePool.OtherPermission = "denied"
  174. }
  175. return nil
  176. }
  177. func GetFsHandlerByUUID(uuid string) (*fs.FileSystemHandler, error) {
  178. for _, fsh := range fsHandlers {
  179. if fsh.UUID == uuid {
  180. return fsh, nil
  181. }
  182. }
  183. return nil, errors.New("Filesystem handler with given UUID not found")
  184. }
  185. func RegisterStorageSettings() {
  186. //Storage Pool Configuration
  187. registerSetting(settingModule{
  188. Name: "Storage Pools",
  189. Desc: "Storage Pool Mounting Configuration",
  190. IconPath: "SystemAO/disk/smart/img/small_icon.png",
  191. Group: "Disk",
  192. StartDir: "SystemAO/storage/poolList.html",
  193. RequireAdmin: true,
  194. })
  195. }
  196. //CloseAllStorages Close all storage database
  197. func CloseAllStorages() {
  198. for _, fsh := range fsHandlers {
  199. fsh.FilesystemDatabase.Close()
  200. }
  201. }