storage.pool.go 18 KB

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