Private.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. <template>
  2. <div>
  3. <a-form
  4. class="mt-3"
  5. :form="form.fc"
  6. v-bind="formItemLayout"
  7. @submit="submit"
  8. hideRequiredMark>
  9. <servertemplate v-if="isServertemplate" :decorators="decorators.servertemplate">
  10. <a-form-item :label="$t('compute.text_297', [$t('dictionary.project')])">
  11. <domain-project :fc="form.fc" :decorators="{ project: decorators.project, domain: decorators.domain }" />
  12. </a-form-item>
  13. </servertemplate>
  14. <!-- <a-divider orientation="left">{{$t('compute.text_300')}}</a-divider> -->
  15. <a-form-item v-if="!isServertemplate" :label="$t('compute.text_297', [$t('dictionary.project')])">
  16. <domain-project
  17. :fc="form.fc"
  18. :fd="form.fd"
  19. :decorators="{ project: decorators.project, domain: decorators.domain }"
  20. :ignoreStorage="isInitForm"
  21. @fetchDomainCallback="fetchDomainCallback"
  22. @fetchProjectCallback="fetchProjectCallback" />
  23. </a-form-item>
  24. <a-form-item :label="$t('compute.text_177')" class="mb-0">
  25. <cloudregion-zone
  26. :zone-params="zoneParams"
  27. :cloudregion-params="cloudregionParams"
  28. :decorator="decorators.cloudregionZone"
  29. filterBrandResource="compute_engine" />
  30. </a-form-item>
  31. <a-form-item :label="$t('compute.text_15')" v-if="isHCSO || isHCS">
  32. <base-select
  33. resource="cloudproviders"
  34. v-decorator="decorators.cloudprovider"
  35. :params="policycloudproviderParams"
  36. :isDefaultSelect="true"
  37. :showSync="true"
  38. :select-props="{ placeholder: $t('compute.text_149') }" />
  39. </a-form-item>
  40. <a-form-item :label="$t('compute.text_228')" v-if="!isServertemplate">
  41. <a-input v-decorator="decorators.name" />
  42. <template v-slot:extra>
  43. <name-repeated
  44. res="servers"
  45. :name="form.fd.name"
  46. :default-text="$t('compute.text_893')" />
  47. </template>
  48. </a-form-item>
  49. <a-form-item :label="$t('common.description')" v-if="!isServertemplate">
  50. <a-textarea :auto-size="{ minRows: 1, maxRows: 3 }" v-decorator="decorators.description" :placeholder="$t('common_367')" />
  51. </a-form-item>
  52. <a-form-item :label="$t('compute.text_1041')" v-if="isOpenWorkflow">
  53. <a-input v-decorator="decorators.reason" :placeholder="$t('compute.text_1042')" />
  54. </a-form-item>
  55. <a-form-item v-show="!isServertemplate" :label="$t('compute.text_1132')">
  56. <duration useServerDuration :decorators="decorators.duration" />
  57. </a-form-item>
  58. <a-form-item :label="$t('compute.text_294')" v-show="!isServertemplate">
  59. <a-input-number v-decorator="decorators.count" @blur="countBlur" :min="1" :max="100" />
  60. </a-form-item>
  61. <a-form-item v-if="form.fd.hypervisor === 'zettakit' || form.fd.hypervisor === 'kvm'">
  62. <span slot="label">
  63. {{ $t('compute.text_1152') }}&nbsp;
  64. <a-tooltip :title="$t('compute.vgpu_check.tooltip')">
  65. <a-icon type="question-circle-o" />
  66. </a-tooltip>
  67. </span>
  68. <pci :decorators="decorators.pci" :pciDevTypeOptions="pciDevTypeOptions" :form="form" :pci-options="pciOptions" />
  69. </a-form-item>
  70. <a-form-item :label="$t('compute.text_1058')" class="mb-0">
  71. <cpu-radio :decorator="decorators.vcpu" :options="form.fi.cpuMem.cpus || []" :showUnlimited="true" @change="cpuChange" />
  72. </a-form-item>
  73. <a-form-item :label="$t('compute.text_369')" class="mb-0">
  74. <mem-radio :decorator="decorators.vmem" :options="form.fi.cpuMem.mems_mb || []" :showUnlimited="true" />
  75. </a-form-item>
  76. <a-form-item :label="$t('compute.text_109')" v-if="showSku">
  77. <sku
  78. v-decorator="decorators.sku"
  79. :type="type"
  80. :sku-params="skuParam"
  81. :hypervisor="form.fd.hypervisor" />
  82. </a-form-item>
  83. <a-form-item :label="$t('compute.text_267')" :extra="$t('compute.text_302')">
  84. <os-select
  85. :type="type"
  86. :form="form"
  87. :hypervisor="form.fd.hypervisor"
  88. :decorator="decorators.imageOS"
  89. :os-arch="osArch"
  90. :image-params="imageParams"
  91. :cacheImageParams="cacheImageParams"
  92. :cloudproviderParamsExtra="cloudproviderParamsExtra"
  93. :ignoreOptions="ignoreImageOptions"
  94. @updateImageMsg="updateFi" />
  95. </a-form-item>
  96. <a-form-item :label="$t('compute.text_49')" class="mb-0">
  97. <system-disk
  98. ref="systemDiskRef"
  99. :decorator="decorators.systemDisk"
  100. :type="type"
  101. :form="form"
  102. :hypervisor="form.fd.hypervisor"
  103. :sku="form.fd.sku"
  104. :capability-data="form.fi.capability"
  105. :image="form.fi.imageMsg"
  106. :sizeDisabled="disabledSysDiskSize" />
  107. </a-form-item>
  108. <a-form-item :label="$t('compute.text_50')" v-if="form.fd.hypervisor && form.fd.hypervisor !== 'zettakit' && !isCNware">
  109. <data-disk
  110. :isInitForm="isInitForm"
  111. :decorator="decorators.dataDisk"
  112. :type="type"
  113. :form="form"
  114. :hypervisor="form.fd.hypervisor"
  115. :sku="form.fd.sku"
  116. :defaultType="form.fd.systemDiskType"
  117. :capability-data="form.fi.capability"
  118. ref="dataDiskRef" />
  119. </a-form-item>
  120. <a-form-item :label="$t('compute.text_1372')" v-if="showServerAccount">
  121. <server-account :form="form" :hypervisor="form.fd.hypervisor" :instance_capabilities="form.fi.capability.instance_capabilities" :osType="osType" />
  122. </a-form-item>
  123. <a-form-item :label="$t('compute.text_308')">
  124. <server-password :decorator="decorators.loginConfig" :login-types="loginTypes" :form="form" />
  125. </a-form-item>
  126. <a-form-item :label="$t('compute.text_104')" class="mb-0">
  127. <server-network
  128. ref="networkRef"
  129. :form="form"
  130. :decorator="decorators.network"
  131. :network-list-params="networkParam"
  132. :schedtag-params="schedtagParams"
  133. :networkVpcParams="networkVpcParams"
  134. :vpcResource="vpcResource"
  135. :cloudprovider="this.form.fd.cloudprovider"
  136. :serverCount="form.fd.count"
  137. :key="serverNetwork"
  138. :networkResourceMapper="networkResourceMapper"
  139. :showMacConfig="form.fd.hypervisor === 'kvm'" />
  140. </a-form-item>
  141. <a-form-item :label="$t('compute.text_1154')" class="mb-0">
  142. <tag
  143. v-decorator="decorators.tag" :default-checked="tagDefaultChecked" />
  144. </a-form-item>
  145. <!-- <a-divider orientation="left">{{$t('compute.text_309')}}</a-divider> -->
  146. <a-collapse :bordered="false" v-model="collapseActive">
  147. <a-collapse-panel :header="$t('compute.text_309')" key="1">
  148. <a-form-item v-if="!isServertemplate">
  149. <span slot="label">
  150. {{ $t('common_388') }}&nbsp;
  151. <a-tooltip :title="hostNameTips">
  152. <a-icon type="question-circle-o" />
  153. </a-tooltip>
  154. </span>
  155. <host-name v-decorator="decorators.hostName" :isWindows="isWindows" />
  156. </a-form-item>
  157. <a-form-item :label="$t('compute.text_105')" v-if="showSecgroup">
  158. <secgroup-config
  159. :decorators="decorators.secgroup"
  160. :secgroup-params="secgroupParams"
  161. :hypervisor="form.fd.hypervisor"
  162. :showSecgroupBind="showSecgroupBind" />
  163. </a-form-item>
  164. <a-form-item :label="$t('compute.text_311')" v-show="!isServertemplate" class="mb-0">
  165. <sched-policy
  166. ref="schedPolicyRef"
  167. :provider="cloudprovider"
  168. :server-type="form.fi.createType"
  169. :disabled-host="policyHostDisabled"
  170. :policy-host-params="policyHostParams"
  171. :decorators="decorators.schedPolicy"
  172. :policy-schedtag-params="policySchedtagParams" />
  173. </a-form-item>
  174. <custom-data v-if="showCustomData" ref="customData" :decorators="decorators" :form="form" />
  175. <bastion-host v-if="!isOpenSourceVersion && hasBastionService" :decorator="decorators.bastion_host" :form="form" />
  176. </a-collapse-panel>
  177. </a-collapse>
  178. <bottom-bar
  179. :loading="submiting"
  180. :form="form"
  181. :type="type"
  182. :dataDiskSizes="dataDiskSizes"
  183. :isOpenWorkflow="isOpenWorkflow"
  184. :errors.sync="errors"
  185. :isServertemplate="isServertemplate"
  186. :hasMeterService="hasMeterService"
  187. @add-cart="addShopCart"
  188. @cancel="handleCancel" />
  189. </a-form>
  190. </div>
  191. </template>
  192. <script>
  193. import _ from 'lodash'
  194. import * as R from 'ramda'
  195. import SecgroupConfig from '@Compute/sections/SecgroupConfig'
  196. import { resolveValueChangeField } from '@/utils/common/ant'
  197. import { HYPERVISORS_MAP } from '@/constants'
  198. import { HOST_CPU_ARCHS } from '@/constants/compute'
  199. import { uuid } from '@/utils/utils'
  200. import mixin from './mixin'
  201. export default {
  202. name: 'VMPrivateCreate',
  203. components: {
  204. SecgroupConfig,
  205. },
  206. mixins: [mixin],
  207. computed: {
  208. isArm () {
  209. return this.form.fd.sku && this.form.fd.sku.cpu_arch === HOST_CPU_ARCHS.arm.capabilityKey
  210. },
  211. isLoongarch64 () {
  212. return this.form.fd.sku && this.form.fd.sku.cpu_arch === HOST_CPU_ARCHS.loongarch64.capabilityKey
  213. },
  214. osArch () {
  215. if (this.form.fd.sku && this.form.fd.sku.cpu_arch) {
  216. return this.form.fd.sku.cpu_arch
  217. } else {
  218. return ''
  219. }
  220. },
  221. cloudregionParams () {
  222. return {
  223. cloud_env: 'private',
  224. usable: true,
  225. show_emulated: true,
  226. ...this.scopeParams,
  227. }
  228. },
  229. zoneParams () {
  230. return {
  231. usable: true,
  232. show_emulated: true,
  233. order_by: 'created_at',
  234. order: 'asc',
  235. ...this.scopeParams,
  236. }
  237. },
  238. imageParams () {
  239. const params = {
  240. ...this.scopeParams,
  241. }
  242. if (R.is(Object, this.form.fd.sku)) {
  243. if (this.cloudregionZoneParams.cloudregion) {
  244. params.cloudregion_id = this.cloudregionZoneParams.cloudregion
  245. }
  246. params.os_arch = HOST_CPU_ARCHS.x86.key
  247. if (this.isArm) params.os_arch = HOST_CPU_ARCHS.arm.key
  248. if (this.isLoongarch64) params.os_arch = HOST_CPU_ARCHS.loongarch64.key
  249. }
  250. return params
  251. },
  252. cacheImageParams () {
  253. const params = {
  254. manager_id: this.form.fd.cloudprovider,
  255. }
  256. if (this.form.fd.hypervisor !== HYPERVISORS_MAP.cloudpods.hypervisor) {
  257. params.project_domain = this.project_domain
  258. }
  259. if (R.is(Object, this.form.fd.sku)) {
  260. if (this.cloudregionZoneParams.cloudregion) {
  261. params.cloudregion_id = this.cloudregionZoneParams.cloudregion
  262. }
  263. }
  264. if (this.form.fd.imageType === 'private_iso') {
  265. params.filter = 'name.endswith(".iso")'
  266. }
  267. if (!params.cloudregion_id) return {}
  268. return params
  269. },
  270. showSku () {
  271. return true
  272. },
  273. skuParam () {
  274. const params = {
  275. limit: 0,
  276. postpaid_status: 'available',
  277. cpu_core_count: this.form.fd.vcpu,
  278. memory_size_mb: this.form.fd.vmem,
  279. usable: true,
  280. enabled: true,
  281. ...this.scopeParams,
  282. }
  283. if (this.form.fd.hypervisor === 'nutanix' || this.form.fd.hypervisor === 'incloudsphere' || this.form.fd.hypervisor === 'proxmox' || this.form.fd.hypervisor === 'sangfor' || this.form.fd.hypervisor === 'uis' || this.form.fd.hypervisor === 'cnware') {
  284. params.is_on_premise = true
  285. params.usable = false
  286. } else {
  287. params.private_cloud = true
  288. params.cloudregion_id = this.cloudregionZoneParams.cloudregion
  289. }
  290. return params
  291. },
  292. policyHostParams () {
  293. const zone = _.get(this.form.fd, 'zone.key')
  294. if (zone) {
  295. return {
  296. enabled: 1,
  297. usable: true,
  298. zone,
  299. hypervisor: this.form.fd.hypervisor,
  300. ...this.scopeParams,
  301. }
  302. }
  303. return {}
  304. },
  305. networkParam () {
  306. if (this.form.fd.hypervisor === HYPERVISORS_MAP.cnware.hypervisor) {
  307. return {
  308. filter: 'server_type.notin(ipmi, pxe)',
  309. usable: true,
  310. ...this.scopeParams,
  311. }
  312. }
  313. const params = {
  314. filter: 'server_type.notin(ipmi, pxe)',
  315. usable: true,
  316. zone: _.get(this.form, 'fd.zone.key'),
  317. ...this.scopeParams,
  318. }
  319. return params
  320. },
  321. instanceSpecParmas () {
  322. if (this.form.fd.hypervisor === HYPERVISORS_MAP.hcso.hypervisor || this.form.fd.hypervisor === HYPERVISORS_MAP.hcs.hypervisor) {
  323. const params = {
  324. usable: true,
  325. enabled: true,
  326. provider: HYPERVISORS_MAP.hcso.provider,
  327. }
  328. if (this.form.fd.hypervisor === HYPERVISORS_MAP.hcs.hypervisor) {
  329. params.provider = HYPERVISORS_MAP.hcs.provider
  330. }
  331. if (this.cloudregionZoneParams.cloudregion) {
  332. params.cloudregion_id = this.cloudregionZoneParams.cloudregion
  333. }
  334. return params
  335. } else {
  336. const ret = {
  337. usable: true,
  338. enabled: true,
  339. 'provider.0': HYPERVISORS_MAP.kvm.provider,
  340. 'provider.1': _.get(HYPERVISORS_MAP, `[${this.form.fd.hypervisor}].provider`),
  341. }
  342. if (this.form.fd.hypervisor === HYPERVISORS_MAP.sangfor.hypervisor || this.form.fd.hypervisor === HYPERVISORS_MAP.cnware.hypervisor) {
  343. delete ret.usable
  344. }
  345. return ret
  346. }
  347. },
  348. cloudprovider () {
  349. if (this.form.fd.hypervisor && this.form.fd.hypervisor) {
  350. return HYPERVISORS_MAP[this.form.fd.hypervisor].provider
  351. }
  352. return ''
  353. },
  354. cloudproviderParamsExtra () {
  355. const params = {
  356. manager_id: this.form.fd.cloudprovider,
  357. ...this.scopeParams,
  358. }
  359. if (this.cloudregionZoneParams.cloudregion) {
  360. params.cloudregion_id = this.cloudregionZoneParams.cloudregion
  361. }
  362. return params
  363. },
  364. disabledSysDiskSize () {
  365. if (this.form.fd.systemDiskType) {
  366. return this.form.fd.systemDiskType.key === 'nova'
  367. }
  368. return false
  369. },
  370. policycloudproviderParams () {
  371. const params = {
  372. limit: 0,
  373. brand: this.form.fd.provider,
  374. cloudregion_id: this.form.fd.cloudregion?.key || this.form.fd.cloudregion,
  375. enabled: true,
  376. filter: 'status.equals(\'connected\')',
  377. ...this.scopeParams,
  378. }
  379. if (this.form.fd.zone) {
  380. params.zone_id = this.form.fd.zone?.key || this.form.fd.zone
  381. }
  382. return params
  383. },
  384. showSecgroup () {
  385. const hiddenSecCloudprovider = ['Nutanix', 'SangFor', 'CNware']
  386. return !hiddenSecCloudprovider.includes(this.cloudprovider)
  387. },
  388. systemDiskTypeDisabled () {
  389. return this.form.fd.hypervisor === HYPERVISORS_MAP.nutanix.key
  390. },
  391. ignoreImageOptions () {
  392. if (this.isInCloudSphere || this.isCNware) {
  393. return ['standard', 'customize']
  394. }
  395. if (this.form.fd.hypervisor === HYPERVISORS_MAP.proxmox.key) {
  396. return ['private']
  397. }
  398. return []
  399. },
  400. },
  401. methods: {
  402. onValuesChange (vm, changedFields) {
  403. this.$nextTick(() => {
  404. const formValue = this.form.fc.getFieldsValue()
  405. const newField = resolveValueChangeField(changedFields)
  406. this._setNewFieldToFd(newField, formValue)
  407. const keys = Object.keys(newField)
  408. if (keys.includes('zone')) {
  409. this.fetchCapability()
  410. }
  411. if (keys.includes('project')) {
  412. this.fetchCapability()
  413. }
  414. })
  415. },
  416. fetchCapability () {
  417. const params = {
  418. show_emulated: true,
  419. resource_type: 'shared',
  420. ...this.scopeParams,
  421. $t: uuid(),
  422. }
  423. if (this.project) {
  424. params.tenant_id = this.project
  425. }
  426. let id = this.cloudregionZoneParams.cloudregion
  427. let resource = 'cloudregions'
  428. if (this.cloudregionZoneParams.zone) {
  429. id = this.cloudregionZoneParams.zone
  430. resource = 'zones'
  431. }
  432. const capabilityParams = { id, spec: 'capability', params, $t: uuid() }
  433. if (!id) return
  434. if (R.equals(this.capabilityParams, capabilityParams)) return // 和已有的参数一样则不发请求
  435. this.capabilityParams = capabilityParams
  436. new this.$Manager(resource).getSpecific(capabilityParams)
  437. .then(({ data }) => {
  438. const { cloudregion = {} } = this.form.fd
  439. if (resource === 'cloudregions' && cloudregion.key && id !== cloudregion.key) {
  440. return
  441. }
  442. this.form.fi.capability = {
  443. ...data,
  444. hypervisors: data.hypervisors.filter(val => val !== 'baremetal' && val !== 'pod'),
  445. }
  446. this.form.fc.getFieldDecorator('hypervisor', { preserve: true })
  447. this.form.fc.setFieldsValue({
  448. hypervisor: this.form.fi.capability.hypervisors[0], // 赋值默认第一个平台
  449. })
  450. this.$set(this.form.fd, 'hypervisor', this.form.fi.capability.hypervisors[0])
  451. this.$nextTick(this.fetchInstanceSpecs)
  452. })
  453. },
  454. fetchInstanceSpecs () {
  455. this.serverskusM.get({ id: 'instance-specs', params: this.instanceSpecParmas })
  456. .then(({ data }) => {
  457. this.form.fi.cpuMem = data
  458. const vcpuDecorator = this.decorators.vcpu
  459. const vcpuInit = vcpuDecorator[1].initialValue
  460. const cpu = this.form.fd.vcpu || vcpuInit
  461. this.cpuChange(cpu)
  462. })
  463. },
  464. },
  465. }
  466. </script>