storage.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. package main
  2. import (
  3. "errors"
  4. "io/ioutil"
  5. "log"
  6. "os"
  7. "path/filepath"
  8. "runtime"
  9. "strings"
  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. storagePools []*storage.StoragePool //All Storage pool opened
  18. )
  19. func StorageInit() {
  20. //Load the default handler for the user storage root
  21. if !fileExists(filepath.Clean(*root_directory) + "/") {
  22. os.MkdirAll(filepath.Clean(*root_directory)+"/", 0755)
  23. }
  24. //Start loading the base storage pool
  25. err := LoadBaseStoragePool()
  26. if err != nil {
  27. panic(err)
  28. }
  29. }
  30. func LoadBaseStoragePool() error {
  31. //Use for Debian buster local file system
  32. localFileSystem := "ext4"
  33. if runtime.GOOS == "windows" {
  34. localFileSystem = "ntfs"
  35. }
  36. baseHandler, err := fs.NewFileSystemHandler(fs.FileSystemOption{
  37. Name: "User",
  38. Uuid: "user",
  39. Path: filepath.ToSlash(filepath.Clean(*root_directory)) + "/",
  40. Hierarchy: "user",
  41. Automount: false,
  42. Filesystem: localFileSystem,
  43. })
  44. if err != nil {
  45. log.Println("Failed to initiate user root storage directory: " + *root_directory)
  46. return err
  47. }
  48. fsHandlers = append(fsHandlers, baseHandler)
  49. //Load the tmp folder as storage unit
  50. tmpHandler, err := fs.NewFileSystemHandler(fs.FileSystemOption{
  51. Name: "tmp",
  52. Uuid: "tmp",
  53. Path: filepath.ToSlash(filepath.Clean(*tmp_directory)) + "/",
  54. Hierarchy: "user",
  55. Automount: false,
  56. Filesystem: localFileSystem,
  57. })
  58. if err != nil {
  59. log.Println("Failed to initiate tmp storage directory: " + *tmp_directory)
  60. return err
  61. }
  62. fsHandlers = append(fsHandlers, tmpHandler)
  63. //Load all the storage config from file
  64. rawConfig, err := ioutil.ReadFile(*storage_config_file)
  65. if err != nil {
  66. //File not found. Use internal storage only
  67. log.Println("Storage configuration file not found. Using internal storage only.")
  68. } else {
  69. //Configuration loaded. Initializing handler
  70. externalHandlers, err := fs.NewFileSystemHandlersFromJSON(rawConfig)
  71. if err != nil {
  72. log.Println("Failed to load storage configuration: " + err.Error() + " -- Skipping")
  73. } else {
  74. for _, thisHandler := range externalHandlers {
  75. fsHandlers = append(fsHandlers, thisHandler)
  76. log.Println(thisHandler.Name + " Mounted as " + thisHandler.UUID + ":/")
  77. }
  78. }
  79. }
  80. //Create a base storage pool for all users
  81. sp, err := storage.NewStoragePool(fsHandlers, "system")
  82. if err != nil {
  83. log.Println("Failed to create base Storaeg Pool")
  84. return err
  85. }
  86. //Push base pool into the opened storage pool list
  87. storagePools = append(storagePools, sp)
  88. //Update the storage pool permission to readwrite
  89. sp.OtherPermission = "readwrite"
  90. baseStoragePool = sp
  91. return nil
  92. }
  93. //Initialize group storage pool
  94. func GroupStoragePoolInit() {
  95. //Mount permission groups
  96. for _, pg := range permissionHandler.PermissionGroups {
  97. //For each group, check does this group has a config file
  98. err := LoadStoragePoolForGroup(pg)
  99. if err != nil {
  100. continue
  101. }
  102. //Do something else, WIP
  103. }
  104. //Start editing interface for Storage Pool Editor
  105. StoragePoolEditorInit()
  106. }
  107. func LoadStoragePoolForGroup(pg *permission.PermissionGroup) error {
  108. expectedConfigPath := "./system/storage/" + pg.Name + ".json"
  109. if fileExists(expectedConfigPath) {
  110. //Read the config file
  111. pgStorageConfig, err := ioutil.ReadFile(expectedConfigPath)
  112. if err != nil {
  113. log.Println("Failed to read config for " + pg.Name + ": " + err.Error())
  114. return errors.New("Failed to read config for " + pg.Name + ": " + err.Error())
  115. }
  116. //Generate fsHandler form json
  117. thisGroupFsHandlers, err := fs.NewFileSystemHandlersFromJSON(pgStorageConfig)
  118. if err != nil {
  119. log.Println("Failed to load storage configuration: " + err.Error())
  120. return errors.New("Failed to load storage configuration: " + err.Error())
  121. }
  122. //Add these to mounted handlers
  123. for _, thisHandler := range thisGroupFsHandlers {
  124. fsHandlers = append(fsHandlers, thisHandler)
  125. log.Println(thisHandler.Name + " Mounted as " + thisHandler.UUID + ":/ for group " + pg.Name)
  126. }
  127. //Create a storage pool from these handlers
  128. sp, err := storage.NewStoragePool(thisGroupFsHandlers, pg.Name)
  129. if err != nil {
  130. log.Println("Failed to create storage pool for " + pg.Name)
  131. return errors.New("Failed to create storage pool for " + pg.Name)
  132. }
  133. //Set other permission to denied by default
  134. sp.OtherPermission = "denied"
  135. //Assign storage pool to group
  136. pg.StoragePool = sp
  137. storagePools = append(storagePools, sp)
  138. } else {
  139. //Storage configuration not exists. Fill in the basic information and move to next storage pool
  140. pg.StoragePool.Owner = pg.Name
  141. pg.StoragePool.OtherPermission = "denied"
  142. }
  143. return nil
  144. }
  145. func GetFsHandlerByUUID(uuid string) (*fs.FileSystemHandler, error) {
  146. //Filter out the :/ fropm uuid if exists
  147. if strings.Contains(uuid, ":") {
  148. uuid = strings.Split(uuid, ":")[0]
  149. }
  150. for _, fsh := range fsHandlers {
  151. if fsh.UUID == uuid {
  152. return fsh, nil
  153. }
  154. }
  155. return nil, errors.New("Filesystem handler with given UUID not found")
  156. }
  157. func RegisterStorageSettings() {
  158. //Storage Pool Configuration
  159. registerSetting(settingModule{
  160. Name: "Storage Pools",
  161. Desc: "Storage Pool Mounting Configuration",
  162. IconPath: "SystemAO/disk/smart/img/small_icon.png",
  163. Group: "Disk",
  164. StartDir: "SystemAO/storage/poolList.html",
  165. RequireAdmin: true,
  166. })
  167. }
  168. //CloseAllStorages Close all storage database
  169. func CloseAllStorages() {
  170. for _, fsh := range fsHandlers {
  171. fsh.FilesystemDatabase.Close()
  172. }
  173. }
  174. func closeAllStoragePools() {
  175. for _, sp := range storagePools {
  176. sp.Close()
  177. }
  178. }