storage.go 8.7 KB

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