storage.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  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. "imuslab.com/arozos/mod/storage/bridge"
  12. fs "imuslab.com/arozos/mod/filesystem"
  13. storage "imuslab.com/arozos/mod/storage"
  14. )
  15. var (
  16. baseStoragePool *storage.StoragePool //base storage pool, all user can access these virtual roots
  17. fsHandlers []*fs.FileSystemHandler //All File system handlers. All opened handles must be registered in here
  18. //storagePools []*storage.StoragePool //All Storage pool opened
  19. bridgeManager *bridge.Record //Manager to handle bridged FSH
  20. )
  21. func StorageInit() {
  22. //Load the default handler for the user storage root
  23. if !fs.FileExists(filepath.Clean(*root_directory) + "/") {
  24. os.MkdirAll(filepath.Clean(*root_directory)+"/", 0755)
  25. }
  26. //Start loading the base storage pool
  27. err := LoadBaseStoragePool()
  28. if err != nil {
  29. panic(err)
  30. }
  31. //Create a brdige record manager
  32. bm := bridge.NewBridgeRecord("system/bridge.json")
  33. bridgeManager = bm
  34. }
  35. func LoadBaseStoragePool() error {
  36. //Use for Debian buster local file system
  37. localFileSystem := "ext4"
  38. if runtime.GOOS == "windows" {
  39. localFileSystem = "ntfs"
  40. }
  41. baseHandler, err := fs.NewFileSystemHandler(fs.FileSystemOption{
  42. Name: "User",
  43. Uuid: "user",
  44. Path: filepath.ToSlash(filepath.Clean(*root_directory)) + "/",
  45. Hierarchy: "user",
  46. Automount: false,
  47. Filesystem: localFileSystem,
  48. })
  49. if err != nil {
  50. log.Println("Failed to initiate user root storage directory: "+*root_directory, err.Error())
  51. return err
  52. }
  53. fsHandlers = append(fsHandlers, baseHandler)
  54. /*
  55. //Load the special share folder as storage unit
  56. shareHandler, err := fs.NewFileSystemHandler(fs.FileSystemOption{
  57. Name: "Share",
  58. Uuid: "share",
  59. Path: filepath.ToSlash(filepath.Clean(*tmp_directory)) + "/",
  60. Access: "readonly",
  61. Hierarchy: "share",
  62. Automount: false,
  63. Filesystem: "share",
  64. })
  65. if err != nil {
  66. log.Println("Failed to initiate share virtual storage directory: " + err.Error())
  67. return err
  68. }
  69. fsHandlers = append(fsHandlers, shareHandler)
  70. */
  71. //Load the tmp folder as storage unit
  72. tmpHandler, err := fs.NewFileSystemHandler(fs.FileSystemOption{
  73. Name: "tmp",
  74. Uuid: "tmp",
  75. Path: filepath.ToSlash(filepath.Clean(*tmp_directory)) + "/",
  76. Hierarchy: "user",
  77. Automount: false,
  78. Filesystem: localFileSystem,
  79. })
  80. if err != nil {
  81. log.Println("Failed to initiate tmp storage directory: "+*tmp_directory, err.Error())
  82. return err
  83. }
  84. fsHandlers = append(fsHandlers, tmpHandler)
  85. /*
  86. DEBUG REMOVE AFTERWARD
  87. */
  88. /*
  89. webdh, err := fs.NewFileSystemHandler(fs.FileSystemOption{
  90. Name: "Loopback",
  91. Uuid: "loopback",
  92. Path: "http://192.168.1.214:8081/webdav/user",
  93. Access: "readwrite",
  94. Hierarchy: "public",
  95. Automount: false,
  96. Filesystem: "webdav",
  97. Username: "TC",
  98. Password: "password",
  99. })
  100. if err != nil {
  101. log.Println(err.Error())
  102. } else {
  103. fsHandlers = append(fsHandlers, webdh)
  104. }
  105. */
  106. //Load all the storage config from file
  107. rawConfig, err := ioutil.ReadFile(*storage_config_file)
  108. if err != nil {
  109. //File not found. Use internal storage only
  110. log.Println("Storage configuration file not found. Using internal storage only.")
  111. } else {
  112. //Configuration loaded. Initializing handler
  113. externalHandlers, err := fs.NewFileSystemHandlersFromJSON(rawConfig)
  114. if err != nil {
  115. log.Println("Failed to load storage configuration: " + err.Error() + " -- Skipping")
  116. } else {
  117. for _, thisHandler := range externalHandlers {
  118. fsHandlers = append(fsHandlers, thisHandler)
  119. log.Println(thisHandler.Name + " Mounted as " + thisHandler.UUID + ":/")
  120. }
  121. }
  122. }
  123. //Create a base storage pool for all users
  124. sp, err := storage.NewStoragePool(fsHandlers, "system")
  125. if err != nil {
  126. log.Println("Failed to create base Storaeg Pool")
  127. return err
  128. }
  129. //Update the storage pool permission to readwrite
  130. sp.OtherPermission = "readwrite"
  131. baseStoragePool = sp
  132. return nil
  133. }
  134. //Initialize group storage pool
  135. func GroupStoragePoolInit() {
  136. //Mount permission groups
  137. for _, pg := range permissionHandler.PermissionGroups {
  138. //For each group, check does this group has a config file
  139. err := LoadStoragePoolForGroup(pg)
  140. if err != nil {
  141. continue
  142. }
  143. //Do something else, WIP
  144. }
  145. //Start editing interface for Storage Pool Editor
  146. StoragePoolEditorInit()
  147. }
  148. func LoadStoragePoolForGroup(pg *permission.PermissionGroup) error {
  149. expectedConfigPath := "./system/storage/" + pg.Name + ".json"
  150. if fs.FileExists(expectedConfigPath) {
  151. //Read the config file
  152. pgStorageConfig, err := ioutil.ReadFile(expectedConfigPath)
  153. if err != nil {
  154. log.Println("Failed to read config for " + pg.Name + ": " + err.Error())
  155. return errors.New("Failed to read config for " + pg.Name + ": " + err.Error())
  156. }
  157. //Generate fsHandler form json
  158. thisGroupFsHandlers, err := fs.NewFileSystemHandlersFromJSON(pgStorageConfig)
  159. if err != nil {
  160. log.Println("Failed to load storage configuration: " + err.Error())
  161. return errors.New("Failed to load storage configuration: " + err.Error())
  162. }
  163. //Add these to mounted handlers
  164. for _, thisHandler := range thisGroupFsHandlers {
  165. fsHandlers = append(fsHandlers, thisHandler)
  166. log.Println(thisHandler.Name + " Mounted as " + thisHandler.UUID + ":/ for group " + pg.Name)
  167. }
  168. //Create a storage pool from these handlers
  169. sp, err := storage.NewStoragePool(thisGroupFsHandlers, pg.Name)
  170. if err != nil {
  171. log.Println("Failed to create storage pool for " + pg.Name)
  172. return errors.New("Failed to create storage pool for " + pg.Name)
  173. }
  174. //Set other permission to denied by default
  175. sp.OtherPermission = "denied"
  176. //Assign storage pool to group
  177. pg.StoragePool = sp
  178. } else {
  179. //Storage configuration not exists. Fill in the basic information and move to next storage pool
  180. //Create a new empty storage pool for this group
  181. sp, err := storage.NewStoragePool([]*fs.FileSystemHandler{}, pg.Name)
  182. if err != nil {
  183. log.Println("Failed to create empty storage pool for group: ", pg.Name)
  184. }
  185. pg.StoragePool = sp
  186. pg.StoragePool.OtherPermission = "denied"
  187. }
  188. return nil
  189. }
  190. //Check if a storage pool exists by its group owner name
  191. func StoragePoolExists(poolOwner string) bool {
  192. _, err := GetStoragePoolByOwner(poolOwner)
  193. return err == nil
  194. }
  195. func GetAllStoragePools() []*storage.StoragePool {
  196. //Append the base pool
  197. results := []*storage.StoragePool{baseStoragePool}
  198. //Add each permissionGroup's pool
  199. for _, pg := range permissionHandler.PermissionGroups {
  200. results = append(results, pg.StoragePool)
  201. }
  202. return results
  203. }
  204. func GetStoragePoolByOwner(owner string) (*storage.StoragePool, error) {
  205. sps := GetAllStoragePools()
  206. for _, pool := range sps {
  207. if pool.Owner == owner {
  208. return pool, nil
  209. }
  210. }
  211. return nil, errors.New("Storage pool owned by " + owner + " not found")
  212. }
  213. func GetFSHandlerSubpathFromVpath(vpath string) (*fs.FileSystemHandler, string, error) {
  214. VirtualRootID, subpath, err := fs.GetIDFromVirtualPath(vpath)
  215. if err != nil {
  216. return nil, "", errors.New("Unable to resolve requested path: " + err.Error())
  217. }
  218. fsh, err := GetFsHandlerByUUID(VirtualRootID)
  219. if err != nil {
  220. return nil, "", errors.New("Unable to resolve requested path: " + err.Error())
  221. }
  222. if fsh == nil || fsh.FileSystemAbstraction == nil {
  223. return nil, "", errors.New("Unable to resolve requested path: " + err.Error())
  224. }
  225. return fsh, subpath, nil
  226. }
  227. func GetFsHandlerByUUID(uuid string) (*fs.FileSystemHandler, error) {
  228. //Filter out the :/ fropm uuid if exists
  229. if strings.Contains(uuid, ":") {
  230. uuid = strings.Split(uuid, ":")[0]
  231. }
  232. for _, fsh := range fsHandlers {
  233. if fsh.UUID == uuid {
  234. return fsh, nil
  235. }
  236. }
  237. return nil, errors.New("Filesystem handler with given UUID not found")
  238. }
  239. func RegisterStorageSettings() {
  240. //Storage Pool Configuration
  241. registerSetting(settingModule{
  242. Name: "Storage Pools",
  243. Desc: "Storage Pool Mounting Configuration",
  244. IconPath: "SystemAO/disk/smart/img/small_icon.png",
  245. Group: "Disk",
  246. StartDir: "SystemAO/storage/poolList.html",
  247. RequireAdmin: true,
  248. })
  249. }
  250. //CloseAllStorages Close all storage database
  251. func CloseAllStorages() {
  252. for _, fsh := range fsHandlers {
  253. fsh.FilesystemDatabase.Close()
  254. }
  255. }
  256. func closeAllStoragePools() {
  257. for _, sp := range GetAllStoragePools() {
  258. sp.Close()
  259. }
  260. }