storage.pool.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
  1. package main
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "io/ioutil"
  6. "log"
  7. "net/http"
  8. "os"
  9. "path/filepath"
  10. "strings"
  11. "time"
  12. "imuslab.com/arozos/mod/database"
  13. "imuslab.com/arozos/mod/permission"
  14. "imuslab.com/arozos/mod/storage/bridge"
  15. "imuslab.com/arozos/mod/utils"
  16. "github.com/tidwall/pretty"
  17. fs "imuslab.com/arozos/mod/filesystem"
  18. prout "imuslab.com/arozos/mod/prouter"
  19. storage "imuslab.com/arozos/mod/storage"
  20. )
  21. /*
  22. Storage Pool Handler
  23. author: tobychui
  24. This script handle the storage pool editing of different permission groups
  25. */
  26. func StoragePoolEditorInit() {
  27. adminRouter := prout.NewModuleRouter(prout.RouterOption{
  28. ModuleName: "System Settings",
  29. AdminOnly: true,
  30. UserHandler: userHandler,
  31. DeniedHandler: func(w http.ResponseWriter, r *http.Request) {
  32. utils.SendErrorResponse(w, "Permission Denied")
  33. },
  34. })
  35. //Create the required folder structure
  36. err := os.MkdirAll("./system/storage", 0775)
  37. if err != nil {
  38. log.Println("Create storage pool setting folder failed: ")
  39. log.Fatal(err)
  40. }
  41. adminRouter.HandleFunc("/system/storage/pool/list", HandleListStoragePools)
  42. adminRouter.HandleFunc("/system/storage/pool/listraw", HandleListStoragePoolsConfig)
  43. //adminRouter.HandleFunc("/system/storage/pool/newHandler", HandleStorageNewFsHandler)
  44. adminRouter.HandleFunc("/system/storage/pool/removeHandler", HandleStoragePoolRemove)
  45. adminRouter.HandleFunc("/system/storage/pool/reload", HandleStoragePoolReload)
  46. adminRouter.HandleFunc("/system/storage/pool/toggle", HandleFSHToggle)
  47. adminRouter.HandleFunc("/system/storage/pool/edit", HandleFSHEdit)
  48. adminRouter.HandleFunc("/system/storage/pool/bridge", HandleFSHBridging)
  49. adminRouter.HandleFunc("/system/storage/pool/checkBridge", HandleFSHBridgeCheck)
  50. }
  51. //Handle editing of a given File System Handler
  52. func HandleFSHEdit(w http.ResponseWriter, r *http.Request) {
  53. opr, _ := utils.PostPara(r, "opr")
  54. group, err := utils.PostPara(r, "group")
  55. if err != nil {
  56. utils.SendErrorResponse(w, "Invalid group given")
  57. return
  58. }
  59. if opr == "get" {
  60. uuid, err := utils.PostPara(r, "uuid")
  61. if err != nil {
  62. utils.SendErrorResponse(w, "Invalid UUID")
  63. return
  64. }
  65. //Load
  66. fshOption, err := getFSHConfigFromGroupAndUUID(group, uuid)
  67. if err != nil {
  68. utils.SendErrorResponse(w, err.Error())
  69. return
  70. }
  71. //Hide the password info
  72. fshOption.Username = ""
  73. fshOption.Password = ""
  74. //Return as JSON
  75. js, _ := json.Marshal(fshOption)
  76. utils.SendJSONResponse(w, string(js))
  77. return
  78. } else if opr == "set" {
  79. config, err := utils.PostPara(r, "config")
  80. if err != nil {
  81. utils.SendErrorResponse(w, "Invalid UUID")
  82. return
  83. }
  84. newFsOption, err := buildOptionFromRequestForm(config)
  85. if err != nil {
  86. utils.SendErrorResponse(w, err.Error())
  87. return
  88. }
  89. //systemWideLogger.PrintAndLog("Storage", newFsOption, nil)
  90. uuid := newFsOption.Uuid
  91. //Read and remove the original settings from the config file
  92. err = setFSHConfigByGroupAndId(group, uuid, newFsOption)
  93. if err != nil {
  94. utils.SendErrorResponse(w, err.Error())
  95. } else {
  96. utils.SendOK(w)
  97. }
  98. } else if opr == "new" {
  99. //New handler
  100. config, err := utils.PostPara(r, "config")
  101. if err != nil {
  102. utils.SendErrorResponse(w, "Invalid config")
  103. return
  104. }
  105. newFsOption, err := buildOptionFromRequestForm(config)
  106. if err != nil {
  107. utils.SendErrorResponse(w, err.Error())
  108. return
  109. }
  110. //Check if group exists
  111. if !permissionHandler.GroupExists(group) && group != "system" {
  112. utils.SendErrorResponse(w, "Group not exists: "+group)
  113. return
  114. }
  115. //Validate the config is correct
  116. err = fs.ValidateOption(&newFsOption)
  117. if err != nil {
  118. utils.SendErrorResponse(w, err.Error())
  119. return
  120. }
  121. configFile := "./system/storage.json"
  122. if group != "system" {
  123. configFile = "./system/storage/" + group + ".json"
  124. }
  125. //Merge the old config file if exists
  126. oldConfigs := []fs.FileSystemOption{}
  127. if fs.FileExists(configFile) {
  128. originalConfigFile, _ := ioutil.ReadFile(configFile)
  129. err := json.Unmarshal(originalConfigFile, &oldConfigs)
  130. if err != nil {
  131. systemWideLogger.PrintAndLog("Storage", err.Error(), err)
  132. }
  133. }
  134. oldConfigs = append(oldConfigs, newFsOption)
  135. js, _ := json.MarshalIndent(oldConfigs, "", " ")
  136. err = ioutil.WriteFile(configFile, js, 0775)
  137. if err != nil {
  138. utils.SendErrorResponse(w, err.Error())
  139. return
  140. }
  141. utils.SendOK(w)
  142. } else {
  143. //Unknown
  144. utils.SendErrorResponse(w, "Unknown opr given")
  145. return
  146. }
  147. }
  148. //Get the FSH configuration for the given group and uuid
  149. func getFSHConfigFromGroupAndUUID(group string, uuid string) (*fs.FileSystemOption, error) {
  150. //Spot the desired config file
  151. targerFile := ""
  152. if group == "system" {
  153. targerFile = "./system/storage.json"
  154. } else {
  155. targerFile = "./system/storage/" + group + ".json"
  156. }
  157. //Check if file exists.
  158. if !fs.FileExists(targerFile) {
  159. systemWideLogger.PrintAndLog("Storage", "Config file not found: "+targerFile, nil)
  160. return nil, errors.New("Configuration file not found")
  161. }
  162. if !fs.FileExists(filepath.Dir(targerFile)) {
  163. os.MkdirAll(filepath.Dir(targerFile), 0775)
  164. }
  165. //Load and parse the file
  166. configContent, err := ioutil.ReadFile(targerFile)
  167. if err != nil {
  168. return nil, err
  169. }
  170. loadedConfig := []fs.FileSystemOption{}
  171. err = json.Unmarshal(configContent, &loadedConfig)
  172. if err != nil {
  173. systemWideLogger.PrintAndLog("Storage", "Request to parse config error: "+err.Error()+targerFile, err)
  174. return nil, err
  175. }
  176. //Look for the target fsh uuid
  177. for _, thisFshConfig := range loadedConfig {
  178. if thisFshConfig.Uuid == uuid {
  179. return &thisFshConfig, nil
  180. }
  181. }
  182. return nil, errors.New("No FSH config found with the uuid")
  183. }
  184. func setFSHConfigByGroupAndId(group string, uuid string, options fs.FileSystemOption) error {
  185. //Spot the desired config file
  186. targerFile := ""
  187. if group == "system" {
  188. targerFile = "./system/storage.json"
  189. } else {
  190. targerFile = "./system/storage/" + group + ".json"
  191. }
  192. //Check if file exists.
  193. if !fs.FileExists(targerFile) {
  194. systemWideLogger.PrintAndLog("Storage", "Config file not found: "+targerFile, nil)
  195. return errors.New("Configuration file not found")
  196. }
  197. if !fs.FileExists(filepath.Dir(targerFile)) {
  198. os.MkdirAll(filepath.Dir(targerFile), 0775)
  199. }
  200. //Load and parse the file
  201. configContent, err := ioutil.ReadFile(targerFile)
  202. if err != nil {
  203. return err
  204. }
  205. loadedConfig := []fs.FileSystemOption{}
  206. err = json.Unmarshal(configContent, &loadedConfig)
  207. if err != nil {
  208. systemWideLogger.PrintAndLog("Storage", "Request to parse config error: "+err.Error()+targerFile, err)
  209. return err
  210. }
  211. //Filter the old fs handler option with given uuid
  212. newConfig := []fs.FileSystemOption{}
  213. var overwritingConfig fs.FileSystemOption
  214. for _, fso := range loadedConfig {
  215. if fso.Uuid != uuid {
  216. newConfig = append(newConfig, fso)
  217. } else {
  218. overwritingConfig = fso
  219. }
  220. }
  221. //Continue using the old username and password if it is left empty
  222. if options.Username == "" {
  223. options.Username = overwritingConfig.Username
  224. }
  225. if options.Password == "" {
  226. options.Password = overwritingConfig.Password
  227. }
  228. //Append the new fso to config
  229. newConfig = append(newConfig, options)
  230. //Write config back to file
  231. js, _ := json.MarshalIndent(newConfig, "", " ")
  232. return ioutil.WriteFile(targerFile, js, 0775)
  233. }
  234. //Handle Storage Pool toggle on-off
  235. func HandleFSHToggle(w http.ResponseWriter, r *http.Request) {
  236. fsh, _ := utils.PostPara(r, "fsh")
  237. if fsh == "" {
  238. utils.SendErrorResponse(w, "Invalid File System Handler ID")
  239. return
  240. }
  241. group, _ := utils.PostPara(r, "group")
  242. if group == "" {
  243. utils.SendErrorResponse(w, "Invalid group ID")
  244. return
  245. }
  246. //Check if group exists
  247. if group != "system" && !permissionHandler.GroupExists(group) {
  248. utils.SendErrorResponse(w, "Group not exists")
  249. return
  250. }
  251. //Not allow to modify system reserved fsh
  252. if fsh == "user" || fsh == "tmp" {
  253. utils.SendErrorResponse(w, "Cannot toggle system reserved File System Handler")
  254. return
  255. }
  256. //Check if fsh exists
  257. var targetpg *permission.PermissionGroup
  258. var storagePool *storage.StoragePool
  259. if group == "system" {
  260. //System storage pool.
  261. storagePool = baseStoragePool
  262. } else {
  263. targetpg = permissionHandler.GetPermissionGroupByName(group)
  264. storagePool = targetpg.StoragePool
  265. }
  266. var targetFSH *fs.FileSystemHandler
  267. for _, thisFsh := range storagePool.Storages {
  268. if thisFsh.UUID == fsh {
  269. targetFSH = thisFsh
  270. }
  271. }
  272. //Target File System Handler not found
  273. if targetFSH == nil {
  274. utils.SendErrorResponse(w, "Target File System Handler not found, given: "+fsh)
  275. return
  276. }
  277. if targetFSH.Closed {
  278. //Reopen the fsh database and set this to false
  279. aofsPath := filepath.ToSlash(filepath.Clean(targetFSH.Path)) + "/aofs.db"
  280. conn, err := database.NewDatabase(aofsPath, false)
  281. if err == nil {
  282. targetFSH.FilesystemDatabase = conn
  283. }
  284. targetFSH.Closed = false
  285. } else {
  286. //Close the fsh database and set this to true
  287. if targetFSH.FilesystemDatabase != nil {
  288. targetFSH.FilesystemDatabase.Close()
  289. }
  290. targetFSH.Closed = true
  291. }
  292. //Give it some time to finish unloading
  293. time.Sleep(1 * time.Second)
  294. //Return ok
  295. utils.SendOK(w)
  296. }
  297. //Handle reload of storage pool
  298. func HandleStoragePoolReload(w http.ResponseWriter, r *http.Request) {
  299. pool, _ := utils.PostPara(r, "pool")
  300. //Basepool super long string just to prevent any typo
  301. if pool == "1eb201a3-d0f6-6630-5e6d-2f40480115c5" {
  302. //Reload ALL storage pools
  303. //Reload basepool
  304. baseStoragePool.Close()
  305. emptyPool := storage.StoragePool{}
  306. baseStoragePool = &emptyPool
  307. //Start BasePool again
  308. err := LoadBaseStoragePool()
  309. if err != nil {
  310. systemWideLogger.PrintAndLog("Storage", err.Error(), err)
  311. } else {
  312. //Update userHandler's basePool
  313. userHandler.UpdateStoragePool(baseStoragePool)
  314. }
  315. //Reload all permission group's pool
  316. for _, pg := range permissionHandler.PermissionGroups {
  317. systemWideLogger.PrintAndLog("Storage", "Reloading Storage Pool for: "+pg.Name, err)
  318. //Pool should be exists. Close it
  319. pg.StoragePool.Close()
  320. //Create an empty pool for this permission group
  321. newEmptyPool := storage.StoragePool{}
  322. pg.StoragePool = &newEmptyPool
  323. //Recreate a new pool for this permission group
  324. //If there is no handler in config, the empty one will be kept
  325. LoadStoragePoolForGroup(pg)
  326. }
  327. BridgeStoragePoolInit()
  328. } else {
  329. if pool == "system" {
  330. //Reload basepool
  331. baseStoragePool.Close()
  332. emptyPool := storage.StoragePool{}
  333. baseStoragePool = &emptyPool
  334. //Start BasePool again
  335. err := LoadBaseStoragePool()
  336. if err != nil {
  337. systemWideLogger.PrintAndLog("Storage", err.Error(), err)
  338. } else {
  339. //Update userHandler's basePool
  340. userHandler.UpdateStoragePool(baseStoragePool)
  341. }
  342. BridgeStoragePoolForGroup("system")
  343. } else {
  344. //Reload the given storage pool
  345. if !permissionHandler.GroupExists(pool) {
  346. utils.SendErrorResponse(w, "Permission Pool owner not exists")
  347. return
  348. }
  349. systemWideLogger.PrintAndLog("Storage", "Reloading Storage Pool for: "+pool, nil)
  350. //Pool should be exists. Close it
  351. pg := permissionHandler.GetPermissionGroupByName(pool)
  352. pg.StoragePool.Close()
  353. //Create an empty pool for this permission group
  354. newEmptyPool := storage.StoragePool{}
  355. pg.StoragePool = &newEmptyPool
  356. //Recreate a new pool for this permission group
  357. //If there is no handler in config, the empty one will be kept
  358. LoadStoragePoolForGroup(pg)
  359. BridgeStoragePoolForGroup(pg.Name)
  360. }
  361. }
  362. utils.SendOK(w)
  363. }
  364. func HandleStoragePoolRemove(w http.ResponseWriter, r *http.Request) {
  365. groupname, err := utils.PostPara(r, "group")
  366. if err != nil {
  367. utils.SendErrorResponse(w, "group not defined")
  368. return
  369. }
  370. uuid, err := utils.PostPara(r, "uuid")
  371. if err != nil {
  372. utils.SendErrorResponse(w, "File system handler UUID not defined")
  373. return
  374. }
  375. targetConfigFile := "./system/storage.json"
  376. if groupname == "system" {
  377. if uuid == "user" || uuid == "tmp" {
  378. utils.SendErrorResponse(w, "Cannot remove system reserved file system handlers")
  379. return
  380. }
  381. //Ok to continue
  382. } else {
  383. //Check group exists
  384. if !permissionHandler.GroupExists(groupname) {
  385. utils.SendErrorResponse(w, "Group not exists")
  386. return
  387. }
  388. targetConfigFile = "./system/storage/" + groupname + ".json"
  389. if !fs.FileExists(targetConfigFile) {
  390. //No config. Create an empty one
  391. initConfig := []fs.FileSystemOption{}
  392. js, _ := json.MarshalIndent(initConfig, "", " ")
  393. ioutil.WriteFile(targetConfigFile, js, 0775)
  394. }
  395. }
  396. //Check if this handler is bridged handler
  397. bridged, _ := bridgeManager.IsBridgedFSH(uuid, groupname)
  398. if bridged {
  399. //Bridged FSH. Remove it from bridge config
  400. basePool, err := GetStoragePoolByOwner(groupname)
  401. if err != nil {
  402. utils.SendErrorResponse(w, err.Error())
  403. return
  404. }
  405. err = DebridgeFSHandlerFromGroup(uuid, basePool)
  406. if err != nil {
  407. utils.SendErrorResponse(w, err.Error())
  408. return
  409. }
  410. //Remove it from the config
  411. bridgeManager.RemoveFromConfig(uuid, groupname)
  412. utils.SendOK(w)
  413. return
  414. } else {
  415. //Remove it from the json file
  416. //Read and parse from old config
  417. oldConfigs := []fs.FileSystemOption{}
  418. originalConfigFile, _ := ioutil.ReadFile(targetConfigFile)
  419. err = json.Unmarshal(originalConfigFile, &oldConfigs)
  420. if err != nil {
  421. utils.SendErrorResponse(w, "Failed to parse original config file")
  422. return
  423. }
  424. //Generate new confic by filtering
  425. newConfigs := []fs.FileSystemOption{}
  426. for _, config := range oldConfigs {
  427. if config.Uuid != uuid {
  428. newConfigs = append(newConfigs, config)
  429. }
  430. }
  431. //Parse and put it into file
  432. if len(newConfigs) > 0 {
  433. js, _ := json.Marshal(newConfigs)
  434. resultingJson := pretty.Pretty(js)
  435. ioutil.WriteFile(targetConfigFile, resultingJson, 0777)
  436. } else {
  437. os.Remove(targetConfigFile)
  438. }
  439. }
  440. utils.SendOK(w)
  441. }
  442. //Constract a fsoption from form
  443. func buildOptionFromRequestForm(payload string) (fs.FileSystemOption, error) {
  444. newFsOption := fs.FileSystemOption{}
  445. err := json.Unmarshal([]byte(payload), &newFsOption)
  446. if err != nil {
  447. return fs.FileSystemOption{}, err
  448. }
  449. return newFsOption, nil
  450. }
  451. /*
  452. func HandleStorageNewFsHandler(w http.ResponseWriter, r *http.Request) {
  453. newFsOption, _ := buildOptionFromRequestForm(r)
  454. type errorObject struct {
  455. Message string
  456. Source string
  457. }
  458. //Get group from form data
  459. groupName := r.FormValue("group")
  460. //Check if group exists
  461. if !permissionHandler.GroupExists(groupName) && groupName != "system" {
  462. js, _ := json.Marshal(errorObject{
  463. Message: "Group not exists: " + groupName,
  464. Source: "",
  465. })
  466. http.Redirect(w, r, "../../../SystemAO/storage/error.html#"+string(js), 307)
  467. }
  468. //Validate the config
  469. err := fs.ValidateOption(&newFsOption)
  470. if err != nil {
  471. //Serve an error page
  472. js, _ := json.Marshal(errorObject{
  473. Message: err.Error(),
  474. Source: groupName,
  475. })
  476. http.Redirect(w, r, "../../../SystemAO/storage/error.html#"+string(js), 307)
  477. return
  478. }
  479. //Ok. Append to the record
  480. configFile := "./system/storage.json"
  481. if groupName != "system" {
  482. configFile = "./system/storage/" + groupName + ".json"
  483. }
  484. //If file exists, merge it to
  485. oldConfigs := []fs.FileSystemOption{}
  486. if fs.FileExists(configFile) {
  487. originalConfigFile, _ := ioutil.ReadFile(configFile)
  488. err := json.Unmarshal(originalConfigFile, &oldConfigs)
  489. if err != nil {
  490. systemWideLogger.PrintAndLog(err,nil)
  491. }
  492. }
  493. oldConfigs = append(oldConfigs, newFsOption)
  494. //Prepare the content to be written
  495. js, _ := json.Marshal(oldConfigs)
  496. resultingJson := pretty.Pretty(js)
  497. err = ioutil.WriteFile(configFile, resultingJson, 0775)
  498. if err != nil {
  499. //Write Error. This could sometime happens on Windows host for unknown reason
  500. js, _ := json.Marshal(errorObject{
  501. Message: err.Error(),
  502. Source: groupName,
  503. })
  504. http.Redirect(w, r, "../../../SystemAO/storage/error.html#"+string(js), 307)
  505. return
  506. }
  507. w.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0")
  508. http.Redirect(w, r, "../../../SystemAO/storage/poolEditor.html#"+groupName, 307)
  509. }
  510. */
  511. func HandleListStoragePoolsConfig(w http.ResponseWriter, r *http.Request) {
  512. target, _ := utils.GetPara(r, "target")
  513. if target == "" {
  514. target = "system"
  515. }
  516. target = strings.ReplaceAll(filepath.ToSlash(target), "/", "")
  517. //List the target storage pool config
  518. targetFile := "./system/storage.json"
  519. if target != "system" {
  520. targetFile = "./system/storage/" + target + ".json"
  521. }
  522. if !fs.FileExists(targetFile) {
  523. //Assume no storage.
  524. nofsh := []*fs.FileSystemOption{}
  525. js, _ := json.Marshal(nofsh)
  526. utils.SendJSONResponse(w, string(js))
  527. return
  528. }
  529. //Read and serve it
  530. configContent, err := ioutil.ReadFile(targetFile)
  531. if err != nil {
  532. utils.SendErrorResponse(w, err.Error())
  533. return
  534. } else {
  535. utils.SendJSONResponse(w, string(configContent))
  536. }
  537. }
  538. //Return all storage pool mounted to the system, aka base pool + pg pools
  539. func HandleListStoragePools(w http.ResponseWriter, r *http.Request) {
  540. filter, _ := utils.GetPara(r, "filter")
  541. storagePools := []*storage.StoragePool{}
  542. if filter != "" {
  543. if filter == "system" {
  544. storagePools = append(storagePools, baseStoragePool)
  545. } else {
  546. for _, pg := range userHandler.GetPermissionHandler().PermissionGroups {
  547. if pg.Name == filter {
  548. storagePools = append(storagePools, pg.StoragePool)
  549. }
  550. }
  551. }
  552. } else {
  553. //Add the base pool into the list
  554. storagePools = append(storagePools, baseStoragePool)
  555. for _, pg := range userHandler.GetPermissionHandler().PermissionGroups {
  556. storagePools = append(storagePools, pg.StoragePool)
  557. }
  558. }
  559. js, _ := json.Marshal(storagePools)
  560. utils.SendJSONResponse(w, string(js))
  561. }
  562. //Handler for bridging two FSH, require admin permission
  563. func HandleFSHBridging(w http.ResponseWriter, r *http.Request) {
  564. //Get the target pool and fsh to bridge
  565. basePool, err := utils.PostPara(r, "base")
  566. if err != nil {
  567. utils.SendErrorResponse(w, "Invalid base pool")
  568. return
  569. }
  570. //Add the target FSH into the base pool
  571. basePoolObject, err := GetStoragePoolByOwner(basePool)
  572. if err != nil {
  573. systemWideLogger.PrintAndLog("Storage", "Bridge FSH failed: "+err.Error(), err)
  574. utils.SendErrorResponse(w, "Storage pool not found")
  575. return
  576. }
  577. targetFSH, err := utils.PostPara(r, "fsh")
  578. if err != nil {
  579. utils.SendErrorResponse(w, "Invalid File System Handler given")
  580. return
  581. }
  582. fsh, err := GetFsHandlerByUUID(targetFSH)
  583. if err != nil {
  584. utils.SendErrorResponse(w, "Given File System Handler UUID does not exists")
  585. return
  586. }
  587. err = BridgeFSHandlerToGroup(fsh, basePoolObject)
  588. if err != nil {
  589. utils.SendErrorResponse(w, err.Error())
  590. return
  591. }
  592. bridgeConfig := bridge.BridgeConfig{
  593. FSHUUID: fsh.UUID,
  594. SPOwner: basePoolObject.Owner,
  595. }
  596. //Write changes to file
  597. err = bridgeManager.AppendToConfig(&bridgeConfig)
  598. if err != nil {
  599. utils.SendErrorResponse(w, err.Error())
  600. return
  601. }
  602. utils.SendOK(w)
  603. }
  604. func HandleFSHBridgeCheck(w http.ResponseWriter, r *http.Request) {
  605. basePool, err := utils.PostPara(r, "base")
  606. if err != nil {
  607. utils.SendErrorResponse(w, "Invalid base pool")
  608. return
  609. }
  610. fsh, err := utils.PostPara(r, "fsh")
  611. if err != nil {
  612. utils.SendErrorResponse(w, "Invalid fsh UUID")
  613. return
  614. }
  615. isBridged, err := bridgeManager.IsBridgedFSH(fsh, basePool)
  616. if err != nil {
  617. utils.SendErrorResponse(w, err.Error())
  618. return
  619. }
  620. js, _ := json.Marshal(isBridged)
  621. utils.SendJSONResponse(w, string(js))
  622. }