storage.pool.go 19 KB

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