WizardSource.ts 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. Copyright (C) 2017 Cloudbase Solutions SRL
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. import Api from '../utils/ApiCaller'
  15. import { OptionsSchemaPlugin } from '../plugins/endpoint'
  16. import DomUtils from '../utils/DomUtils'
  17. import configLoader from '../utils/Config'
  18. import type { WizardData } from '../@types/WizardData'
  19. import type { StorageMap } from '../@types/Endpoint'
  20. import type { InstanceScript } from '../@types/Instance'
  21. import DefaultOptionsSchemaParser from '../plugins/endpoint/default/OptionsSchemaPlugin'
  22. import { TransferItem } from '../@types/MainItem'
  23. import { INSTANCE_OSMORPHING_MINION_POOL_MAPPINGS } from '../components/organisms/WizardOptions/WizardOptions'
  24. class WizardSource {
  25. async create(
  26. type: string,
  27. data: WizardData,
  28. defaultStorage: string | null,
  29. storageMap: StorageMap[],
  30. uploadedUserScripts: InstanceScript[],
  31. ): Promise<TransferItem> {
  32. const sourceParser = data.source
  33. ? OptionsSchemaPlugin.for(data.source.type) : DefaultOptionsSchemaParser
  34. const destParser = data.target
  35. ? OptionsSchemaPlugin.for(data.target.type) : DefaultOptionsSchemaParser
  36. const payload: any = {}
  37. payload[type] = {
  38. origin_endpoint_id: data.source ? data.source.id : 'null',
  39. destination_endpoint_id: data.target ? data.target.id : 'null',
  40. network_map: destParser.getNetworkMap(data.networks),
  41. instances: data.selectedInstances ? data.selectedInstances.map(i => i.instance_name || i.id) : 'null',
  42. storage_mappings: destParser.getStorageMap(defaultStorage, storageMap),
  43. notes: data.destOptions ? data.destOptions.description || '' : '',
  44. }
  45. if (data.destOptions && data.destOptions.skip_os_morphing != null) {
  46. payload[type].skip_os_morphing = data.destOptions.skip_os_morphing
  47. }
  48. if (data.sourceOptions) {
  49. const sourceEnv = sourceParser.getDestinationEnv(data.sourceOptions)
  50. if (sourceEnv.minion_pool_id) {
  51. payload[type].origin_minion_pool_id = sourceEnv.minion_pool_id
  52. delete sourceEnv.minion_pool_id
  53. }
  54. payload[type].source_environment = sourceEnv
  55. }
  56. const destEnv = destParser.getDestinationEnv(data.destOptions)
  57. if (destEnv.minion_pool_id) {
  58. payload[type].destination_minion_pool_id = destEnv.minion_pool_id
  59. delete destEnv.minion_pool_id
  60. }
  61. const poolMappings = destEnv[INSTANCE_OSMORPHING_MINION_POOL_MAPPINGS]
  62. if (poolMappings) {
  63. Object.keys(poolMappings).forEach(instanceId => {
  64. if (poolMappings[instanceId]
  65. && payload[type].instances.find((i: string) => i === instanceId)) {
  66. if (!payload[type][
  67. INSTANCE_OSMORPHING_MINION_POOL_MAPPINGS
  68. ]) {
  69. payload[type][
  70. INSTANCE_OSMORPHING_MINION_POOL_MAPPINGS
  71. ] = {}
  72. }
  73. payload[type][
  74. INSTANCE_OSMORPHING_MINION_POOL_MAPPINGS
  75. ][instanceId] = poolMappings[instanceId]
  76. }
  77. })
  78. }
  79. delete destEnv[INSTANCE_OSMORPHING_MINION_POOL_MAPPINGS]
  80. payload[type].destination_environment = destEnv
  81. payload[type].shutdown_instances = Boolean(
  82. data.destOptions && data.destOptions.shutdown_instances,
  83. )
  84. if (type === 'migration') {
  85. payload[type].replication_count = (
  86. data.destOptions && data.destOptions.replication_count) || 2
  87. if (uploadedUserScripts.length) {
  88. payload[type].user_scripts = destParser.getUserScripts(uploadedUserScripts)
  89. }
  90. }
  91. const response = await Api.send({
  92. url: `${configLoader.config.servicesUrls.coriolis}/${Api.projectId}/${type}s`,
  93. method: 'POST',
  94. data: payload,
  95. })
  96. return response.data[type]
  97. }
  98. async createMultiple(
  99. type: string,
  100. data: WizardData,
  101. defaultStorage: string | null,
  102. storageMap: StorageMap[],
  103. uploadedUserScripts: InstanceScript[],
  104. ) {
  105. if (!data.selectedInstances) {
  106. throw new Error('No selected instances')
  107. }
  108. const mainItems = await Promise.all(data.selectedInstances.map(async instance => {
  109. const newData = { ...data }
  110. newData.selectedInstances = [instance]
  111. let mainItem: TransferItem | null = null
  112. try {
  113. mainItem = await this.create(type, newData, defaultStorage, storageMap, uploadedUserScripts)
  114. } finally {
  115. // If an there's an error with the request, return null, don't break the loop.
  116. // eslint-disable-next-line no-unsafe-finally
  117. return mainItem
  118. }
  119. }))
  120. return mainItems
  121. }
  122. setUrlState(data: any) {
  123. const locationExp = /.*?(?:\?|$)/.exec(window.location.href)
  124. if (!locationExp || DomUtils.isSafari()) {
  125. return
  126. }
  127. const location = locationExp[0].replace('?', '')
  128. window.history.replaceState({}, '', `${location}?d=${DomUtils.encodeToBase64Url(data)}`)
  129. }
  130. getUrlState() {
  131. const dataExpExec = /\?d=(.*)/.exec(window.location.href)
  132. let result = null
  133. try {
  134. result = dataExpExec && DomUtils.decodeFromBase64Url(dataExpExec[1])
  135. } catch (err) {
  136. console.error(err)
  137. }
  138. return result
  139. }
  140. }
  141. export default new WizardSource()