OptionsSchemaPlugin.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  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. // @flow
  15. import { defaultSchemaToFields } from './ConnectionSchemaPlugin'
  16. import type { Field } from '../../../types/Field'
  17. import type { OptionValues, StorageMap } from '../../../types/Endpoint'
  18. import type { SchemaProperties, SchemaDefinitions } from '../../../types/Schema'
  19. import type { NetworkMap } from '../../../types/Network'
  20. import { executionOptions } from '../../../constants'
  21. const migrationImageOsTypes = ['windows', 'linux']
  22. export const defaultFillFieldValues = (field: Field, option: OptionValues) => {
  23. if (field.type === 'string') {
  24. field.enum = [...option.values]
  25. if (option.config_default) {
  26. field.default = typeof option.config_default === 'string' ? option.config_default : option.config_default.id
  27. }
  28. }
  29. if (field.type === 'array') {
  30. field.enum = [...option.values]
  31. }
  32. }
  33. export const defaultFillMigrationImageMapValues = (field: Field, option: OptionValues): boolean => {
  34. if (field.name !== 'migr_image_map') {
  35. return false
  36. }
  37. field.properties = migrationImageOsTypes.map(os => {
  38. let values = option.values
  39. .filter(v => v.os_type === os || v.os_type === 'unknown')
  40. .sort((v1, v2) => {
  41. if (v1.os_type === 'unknown' && v2.os_type !== 'unknown') {
  42. return 1
  43. } else if (v1.os_type !== 'unknown' && v2.os_type === 'unknown') {
  44. return -1
  45. }
  46. return 0
  47. })
  48. let unknownIndex = values.findIndex(v => v.os_type === 'unknown')
  49. if (unknownIndex > -1 && values.filter(v => v.os_type === 'unknown').length < values.length) {
  50. values.splice(unknownIndex, 0, { separator: true })
  51. }
  52. return {
  53. name: `${os}_os_image`,
  54. type: 'string',
  55. enum: values,
  56. }
  57. })
  58. return true
  59. }
  60. export const defaultGetDestinationEnv = (options: ?{ [string]: mixed }, oldOptions?: ?{ [string]: mixed }): any => {
  61. let env = {}
  62. let specialOptions = ['execute_now', 'separate_vm', 'skip_os_morphing', 'default_storage', 'description']
  63. .concat(executionOptions.map(o => o.name))
  64. .concat(migrationImageOsTypes.map(o => `${o}_os_image`))
  65. if (!options) {
  66. return env
  67. }
  68. Object.keys(options).forEach(optionName => {
  69. if (specialOptions.find(o => o === optionName) || !options || options[optionName] == null || options[optionName] === '') {
  70. return
  71. }
  72. if (optionName.indexOf('/') > 0) {
  73. let parentName = optionName.substr(0, optionName.lastIndexOf('/'))
  74. if (!env[parentName]) {
  75. env[parentName] = oldOptions ? oldOptions[parentName] || {} : {}
  76. }
  77. env[parentName][optionName.substr(optionName.lastIndexOf('/') + 1)] = options ? options[optionName] : null
  78. } else {
  79. env[optionName] = options ? options[optionName] : null
  80. }
  81. })
  82. return env
  83. }
  84. export const defaultGetMigrationImageMap = (options: ?{ [string]: mixed }) => {
  85. let env = {}
  86. if (!options) {
  87. return env
  88. }
  89. migrationImageOsTypes.forEach(os => {
  90. if (!options || !options[`${os}_os_image`]) {
  91. return
  92. }
  93. if (!env.migr_image_map) {
  94. env.migr_image_map = {}
  95. }
  96. env.migr_image_map[os] = options[`${os}_os_image`]
  97. })
  98. return env
  99. }
  100. export default class OptionsSchemaParser {
  101. static parseSchemaToFields(schema: SchemaProperties, schemaDefinitions?: ?SchemaDefinitions) {
  102. return defaultSchemaToFields(schema, schemaDefinitions)
  103. }
  104. static fillFieldValues(field: Field, options: OptionValues[]) {
  105. let option = options.find(f => f.name === field.name)
  106. if (!option) {
  107. return
  108. }
  109. if (!defaultFillMigrationImageMapValues(field, option)) {
  110. defaultFillFieldValues(field, option)
  111. }
  112. }
  113. static getDestinationEnv(options: ?{ [string]: mixed }, oldOptions?: any) {
  114. let env = {
  115. ...defaultGetDestinationEnv(options, oldOptions),
  116. ...defaultGetMigrationImageMap(options),
  117. }
  118. return env
  119. }
  120. static getNetworkMap(networkMappings: ?NetworkMap[]) {
  121. let payload = {}
  122. if (networkMappings && networkMappings.length) {
  123. networkMappings.forEach(mapping => {
  124. payload[mapping.sourceNic.network_name] = mapping.targetNetwork.id
  125. })
  126. }
  127. return payload
  128. }
  129. static getStorageMap(defaultStorage: ?string, storageMap: ?StorageMap[], configDefault?: ?string) {
  130. if (!defaultStorage && !storageMap) {
  131. return null
  132. }
  133. let payload = {}
  134. if (defaultStorage) {
  135. payload.default = defaultStorage
  136. }
  137. if (!storageMap) {
  138. return payload
  139. }
  140. storageMap.forEach(mapping => {
  141. if (mapping.target.id === null && !configDefault) {
  142. return
  143. }
  144. if (mapping.type === 'backend') {
  145. if (!payload.backend_mappings) {
  146. payload.backend_mappings = []
  147. }
  148. payload.backend_mappings.push({
  149. source: mapping.source.storage_backend_identifier,
  150. destination: mapping.target.id === null ? configDefault : mapping.target.name,
  151. })
  152. } else {
  153. if (!payload.disk_mappings) {
  154. payload.disk_mappings = []
  155. }
  156. payload.disk_mappings.push({
  157. disk_id: mapping.source.id.toString(),
  158. destination: mapping.target.id === null ? configDefault : mapping.target.name,
  159. })
  160. }
  161. })
  162. return payload
  163. }
  164. }