AddBackup.vue 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. <template>
  2. <base-dialog @cancel="cancelDialog">
  3. <div slot="header">{{$t('compute.text_1162')}}</div>
  4. <div slot="body">
  5. <dialog-selected-tips :name="$t('dictionary.server')" :count="params.data.length" :action="$t('compute.text_1162')" />
  6. <dialog-table :data="params.data" :columns="params.columns.slice(0, 3)" />
  7. <a-form :form="form.fc" hideRequiredMark v-bind="formItemLayout">
  8. <a-form-item
  9. :label="$t('compute.text_1163')"
  10. :validate-status="hostValidateStatus"
  11. :help="hostValidateMsg">
  12. <base-select
  13. class="w-100"
  14. v-decorator="decorators.prefer_host_id"
  15. :options="hostsOptions"
  16. :params="selectParams"
  17. :disabled-items="disabledItems"
  18. :select-props="{ placeholder: $t('compute.text_314') }" />
  19. </a-form-item>
  20. <!-- 自动启动 -->
  21. <a-form-item :label="$t('compute.text_494')" :extra="$t('compute.text_495')">
  22. <a-switch
  23. :checkedChildren="$t('compute.text_115')"
  24. :unCheckedChildren="$t('compute.text_116')"
  25. v-decorator="decorators.auto_start" />
  26. </a-form-item>
  27. </a-form>
  28. </div>
  29. <div slot="footer">
  30. <a-button type="primary" @click="handleConfirm" :loading="loading" :disabled="handleConfirmDisabled">{{ $t('dialog.ok') }}</a-button>
  31. <a-button @click="cancelDialog">{{ $t('dialog.cancel') }}</a-button>
  32. </div>
  33. </base-dialog>
  34. </template>
  35. <script>
  36. import { mapGetters } from 'vuex'
  37. import DialogMixin from '@/mixins/dialog'
  38. import WindowsMixin from '@/mixins/windows'
  39. import { typeClouds } from '@/utils/common/hypervisor'
  40. const hypervisorMap = typeClouds.hypervisorMap
  41. export default {
  42. name: 'VmAddBackupDialog',
  43. mixins: [DialogMixin, WindowsMixin],
  44. data () {
  45. return {
  46. loading: false,
  47. form: {
  48. fc: this.$form.createForm(this),
  49. },
  50. forcastData: null,
  51. hosts: [],
  52. decorators: {
  53. prefer_host_id: [
  54. 'prefer_host_id',
  55. {
  56. rules: [
  57. { required: false, message: this.$t('compute.text_1165'), trigger: 'blur' },
  58. ],
  59. },
  60. ],
  61. auto_start: [
  62. 'auto_start',
  63. {
  64. initialValue: false,
  65. valuePropName: 'checked',
  66. },
  67. ],
  68. },
  69. formItemLayout: {
  70. wrapperCol: {
  71. span: 18,
  72. },
  73. labelCol: {
  74. span: 6,
  75. },
  76. },
  77. }
  78. },
  79. computed: {
  80. ...mapGetters(['isAdminMode', 'isDomainMode', 'scope']),
  81. firstData () {
  82. return this.params.data[0]
  83. },
  84. selectParams () {
  85. const params = {
  86. enabled: 1,
  87. host_type: this.firstData.hypervisor,
  88. host_status: 'online',
  89. server_id_for_network: this.firstData.id,
  90. os_arch: this.firstData.os_arch,
  91. }
  92. if (this.firstData.hypervisor === hypervisorMap.kvm.key) {
  93. params.host_type = 'hypervisor'
  94. }
  95. if (this.isAdminMode && this.params.data.length === 1) {
  96. params.project_domain = this.firstData.domain_id
  97. }
  98. if (this.isDomainMode) {
  99. params.scope = this.scope
  100. }
  101. return params
  102. },
  103. disabledItems () {
  104. return [this.firstData.host_id]
  105. },
  106. hostsOptions () {
  107. const hostIds = this.forcastData?.filtered_candidates?.map(v => v.id) || []
  108. if (this.forcastData?.can_create === false) {
  109. return []
  110. }
  111. return this.hosts.filter(v => {
  112. return !hostIds.includes(v.id) && v.id !== this.firstData.host_id
  113. }).map(v => {
  114. return {
  115. key: v.id,
  116. label: v.name,
  117. }
  118. })
  119. },
  120. hostValidateStatus () {
  121. if (this.forcastData && this.hostsOptions?.length === 0) {
  122. return 'error'
  123. }
  124. return 'success'
  125. },
  126. hostValidateMsg () {
  127. if (this.forcastData && this.hostsOptions?.length === 0) {
  128. return this.$t('compute.transfer_host')
  129. }
  130. return this.$t('compute.text_1164')
  131. },
  132. handleConfirmDisabled () {
  133. return this.forcastData && this.hostsOptions?.length === 0
  134. },
  135. },
  136. created () {
  137. this.queryForcastData()
  138. this.queryHosts()
  139. },
  140. methods: {
  141. async handleConfirm () {
  142. this.loading = true
  143. try {
  144. const values = await this.form.fc.validateFields()
  145. const ids = this.params.data.map(item => item.id)
  146. await this.params.onManager('batchPerformAction', {
  147. id: ids,
  148. steadyStatus: ['running', 'ready'],
  149. managerArgs: {
  150. action: 'create-backup',
  151. data: values,
  152. },
  153. })
  154. this.cancelDialog()
  155. } finally {
  156. this.loading = false
  157. }
  158. },
  159. doForecast (live_migrate = true, skip_cpu_check = false, prefer_host_id) {
  160. const manager = new this.$Manager('servers')
  161. const params = {
  162. live_migrate,
  163. skip_cpu_check,
  164. }
  165. if (prefer_host_id) {
  166. params.prefer_host_id = prefer_host_id
  167. }
  168. return manager.performAction({
  169. id: this.params.data[0].id,
  170. action: 'migrate-forecast',
  171. data: params,
  172. })
  173. },
  174. queryForcastData (skip_cpu_check, prefer_host_id) {
  175. const live_migrate = this.firstData.status === 'running'
  176. this.doForecast(live_migrate, skip_cpu_check, prefer_host_id).then((res) => {
  177. this.forcastData = res.data
  178. }).catch((err) => {
  179. console.log(err)
  180. throw err
  181. })
  182. },
  183. queryHosts () {
  184. const hostsManager = new this.$Manager('hosts')
  185. hostsManager.list({ params: this.selectParams }).then((res) => {
  186. this.hosts = res.data.data || []
  187. }).catch((err) => {
  188. console.log(err)
  189. throw err
  190. })
  191. },
  192. },
  193. }
  194. </script>