| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508 |
- <template>
- <base-dialog @cancel="cancelDialog" :width="1000">
- <div slot="header">{{action}}</div>
- <div slot="body">
- <a-alert type="warning" class="mb-2" v-if="tips.length">
- <template v-slot:message>
- <div class="messages-list">
- <p v-for="(item,index) in tips" :key="index" class="mb-1">{{ item }}</p>
- </div>
- </template>
- </a-alert>
- <template v-if="isShowColumns">
- <dialog-selected-tips :name="$t('dictionary.server')" :count="params.data.length" :action="action" />
- <dialog-table :data="params.data" :columns="params.columns.filter(item => ['name', 'os_dist', 'instance_type'].includes(item.field))" />
- </template>
- <a-form
- v-bind="formItemLayout"
- :form="form.fc">
- <a-form-item v-show="!imgHidden" :label="$t('compute.text_267')">
- <div slot="help">
- <div class="help-color">{{$t('compute.text_302')}}</div>
- </div>
- <os-select
- :type="type"
- :form="form"
- :types="osSelectTypes"
- :hypervisor="hypervisor"
- :image-params="image"
- :ignoreOptions="ignoreImageOptions"
- :osType="osType"
- :os-arch="osArch"
- :cache-image-params="cacheImageParams"
- :decorator="decorators.imageOS"
- :sys-disk-size="sysDiskSize"
- :imageCloudproviderDisabled="true"
- :cloudproviderParamsExtra="cloudproviderParamsExtra"
- @updateImageMsg="updateImageMsgDebounce"
- :imageTypeMap="imageTypeMap"
- :edit="true" />
- </a-form-item>
- <a-form-item v-show="imgHidden" :label="$t('compute.text_267')">
- <div>{{ imgHidden.text }}</div>
- </a-form-item>
- <a-form-item :label="$t('compute.text_308')" v-if="!isZStack" class="mb-0">
- <server-password :decorator="decorators.loginConfig" :loginTypes="loginTypes" :form="form" />
- </a-form-item>
- <a-form-item v-if="isShowAgent" :label="$t('compute.agent.label')" :extra="$t('compute.agent.extra')">
- <a-checkbox v-decorator="decorators.deploy_telegraf">{{ $t('compute.agent.install.plugin') }}</a-checkbox>
- </a-form-item>
- <a-form-item :label="$t('compute.text_494')" :extra="$t('compute.text_1220')">
- <a-switch :checkedChildren="$t('compute.text_115')" :unCheckedChildren="$t('compute.text_116')" v-decorator="decorators.autoStart" />
- </a-form-item>
- </a-form>
- </div>
- <div slot="footer">
- <a-button type="primary" @click="handleConfirm" :loading="loading">{{ $t('dialog.ok') }}</a-button>
- <a-button @click="cancelDialog">{{ $t('dialog.cancel') }}</a-button>
- </div>
- </base-dialog>
- </template>
- <script>
- import _ from 'lodash'
- import { mapGetters } from 'vuex'
- import OsSelect from '@Compute/sections/OsSelect'
- import ServerPassword from '@Compute/sections/ServerPassword'
- import { SERVER_TYPE, LOGIN_TYPES_MAP } from '@Compute/constants'
- import DialogMixin from '@/mixins/dialog'
- import WindowsMixin from '@/mixins/windows'
- import { HYPERVISORS_MAP } from '@/constants'
- import { Manager } from '@/utils/manager'
- import { IMAGES_TYPE_MAP, HOST_CPU_ARCHS } from '@/constants/compute'
- import { isRequired, passwordValidator } from '@/utils/validate'
- import { findPlatform } from '@/utils/common/hypervisor'
- export default {
- name: 'VmRebuildRootDialog',
- components: {
- OsSelect,
- ServerPassword,
- },
- provide: function () {
- return {
- form: this.form,
- }
- },
- mixins: [DialogMixin, WindowsMixin],
- data () {
- return {
- loading: false,
- action: this.$t('compute.text_357'),
- form: {
- fc: this.$form.createForm(this, {
- onValuesChange: (props, values) => {
- Object.keys(values).forEach((key) => {
- this.$set(this.form.fd, key, values[key])
- })
- },
- }),
- fd: {},
- },
- ignoreImageOptions: [
- IMAGES_TYPE_MAP.iso.key,
- IMAGES_TYPE_MAP.host.key,
- IMAGES_TYPE_MAP.snapshot.key,
- ],
- formItemLayout: {
- wrapperCol: {
- span: 20,
- },
- labelCol: {
- span: 4,
- },
- },
- detailData: {},
- firstLoad: true,
- cloudproviderParamsExtra: {
- scope: this.$store.getters.scope,
- filter: `id.equals("${this.params.data[0].manager_id}")`,
- },
- imageTypeMap: {},
- }
- },
- computed: {
- ...mapGetters(['userInfo', 'auth']),
- enableMFA () {
- return this.userInfo.enable_mfa && this.auth.auth.system_totp_on
- },
- type () {
- const brand = this.params.data[0].brand
- return findPlatform(brand)
- },
- osSelectTypes () {
- if (HYPERVISORS_MAP.ctyun.key === this.params.data[0].hypervisor) {
- return ['public', 'public_customize']
- }
- return []
- },
- imageType () {
- if (this.type === SERVER_TYPE.idc && this.hypervisor === HYPERVISORS_MAP.esxi.key) {
- return IMAGES_TYPE_MAP.vmware.key
- } else if (this.type === SERVER_TYPE.public) {
- return IMAGES_TYPE_MAP.public.key
- } else if (this.type === SERVER_TYPE.private) {
- return IMAGES_TYPE_MAP.private.key
- } else {
- return IMAGES_TYPE_MAP.standard.key
- }
- },
- hypervisor () {
- return this.params.data[0].hypervisor
- },
- osArch () {
- const { instance_type = '', os_arch } = this.params.data[0]
- if (instance_type.startsWith('k') || os_arch === HOST_CPU_ARCHS.arm.capabilityKey) {
- return HOST_CPU_ARCHS.arm.capabilityKey
- }
- return ''
- },
- image () {
- const params = {
- limit: 0,
- details: true,
- status: 'active',
- os_arch: HOST_CPU_ARCHS.x86.key,
- }
- if (this.osArch === HOST_CPU_ARCHS.arm.capabilityKey) {
- params.os_arch = HOST_CPU_ARCHS.arm.key
- }
- return params
- },
- isZStack () {
- return this.hypervisor === HYPERVISORS_MAP.zstack.key
- },
- decorators () {
- const validateToImage = (isZStack) => {
- return (rule, value, callback) => {
- if (isZStack) {
- callback()
- } else {
- isRequired()(rule, value, callback)
- }
- }
- }
- return {
- imageOS: {
- prefer_manager: [
- 'prefer_manager',
- {
- initialValue: _.get(this.params, 'data[0].manager_id') || '',
- rules: [
- { required: true, message: this.$t('compute.text_149') },
- ],
- },
- ],
- os: [
- 'os',
- {
- initialValue: '',
- rules: [
- { required: !this.isZStack, message: this.$t('compute.text_153') },
- ],
- },
- ],
- image: [
- 'image',
- {
- initialValue: { key: '', label: '' },
- rules: [
- { validator: validateToImage(this.isZStack), message: this.$t('compute.text_214') },
- ],
- },
- ],
- imageType: [
- 'imageType',
- {
- initialValue: this.imageType,
- },
- ],
- },
- loginConfig: {
- loginType: [
- 'loginType',
- {
- initialValue: 'random',
- },
- ],
- keypair: [
- 'loginKeypair',
- {
- initialValue: undefined,
- rules: [
- { required: true, message: this.$t('compute.text_203') },
- ],
- },
- ],
- password: [
- 'loginPassword',
- {
- initialValue: '',
- rules: [
- { required: true, message: this.$t('compute.text_204') },
- { validator: passwordValidator, trigger: 'blur' },
- ],
- },
- ],
- },
- autoStart: [
- 'autoStart',
- {
- valuePropName: 'checked',
- initialValue: true,
- },
- ],
- deploy_telegraf: [
- 'deploy_telegraf',
- {
- valuePropName: 'checked',
- initialValue: true,
- },
- ],
- }
- },
- cacheImageParams () {
- const params = {
- details: false,
- order_by: 'ref_count',
- order: 'desc',
- zone: this.params.data[0].zone_id,
- }
- if (this.hypervisor === HYPERVISORS_MAP.esxi.key) {
- params.image_type = 'system'
- params.manager = this.params.data[0].manager_id
- }
- return params
- },
- isFreezeImg () {
- // if (this.hypervisor) {
- // return [HYPERVISORS_MAP.openstack.key].includes(this.hypervisor.toLowerCase())
- // }
- return false
- },
- imgHidden () {
- if (this.hypervisor) {
- if (this.isFreezeImg) {
- const pdata = this.detailData[0]
- if (pdata && pdata.disks_info && pdata.disks_info[0] && pdata.disks_info[0].image) {
- return {
- text: pdata.disks_info[0].image,
- isImage: true,
- }
- } else {
- return {
- text: this.$t('compute.text_1221'),
- isImage: false,
- }
- }
- } else {
- return false
- }
- }
- return false
- },
- tips () {
- if (this.hypervisor === HYPERVISORS_MAP.openstack.key) {
- return [this.$t('compute.text_1222')]
- }
- if (this.hypervisor === HYPERVISORS_MAP.zstack.key) {
- return [this.$t('compute.text_1223')]
- }
- if (this.params.data.every(item => item.hypervisor === HYPERVISORS_MAP.kvm.key)) {
- return [
- this.$t('compute.kvm_rebuild_tip1'),
- this.$t('compute.kvm_rebuild_tip2'),
- this.$t('compute.kvm_rebuild_tip3'),
- this.$t('compute.kvm_rebuild_tip4'),
- this.$t('compute.kvm_rebuild_tip5'),
- this.$t('compute.kvm_rebuild_tip6'),
- ]
- }
- if (this.params.data.length === 1) {
- return [this.$t('compute.text_1224')]
- }
- return ''
- },
- osType () {
- return this.params.data[0].os_type
- },
- loginTypes () {
- const loginTypes = { ...LOGIN_TYPES_MAP }
- const hypervisor = this.hypervisor
- if (HYPERVISORS_MAP.ucloud.key === hypervisor) {
- delete loginTypes[LOGIN_TYPES_MAP.image.key]
- delete loginTypes[LOGIN_TYPES_MAP.keypair.key]
- }
- if (HYPERVISORS_MAP.aws.key === hypervisor) {
- delete loginTypes[LOGIN_TYPES_MAP.random.key]
- delete loginTypes[LOGIN_TYPES_MAP.password.key]
- }
- if ([HYPERVISORS_MAP.azure.key, HYPERVISORS_MAP.huawei.key].includes(hypervisor)) {
- delete loginTypes[LOGIN_TYPES_MAP.image.key]
- }
- if (HYPERVISORS_MAP.ctyun.key === hypervisor) {
- delete loginTypes[LOGIN_TYPES_MAP.keypair.key]
- delete loginTypes[LOGIN_TYPES_MAP.image.key]
- }
- if (HYPERVISORS_MAP.google.key === hypervisor) {
- delete loginTypes[LOGIN_TYPES_MAP.image.key]
- }
- if (HYPERVISORS_MAP.qcloud.key === hypervisor) {
- delete loginTypes[LOGIN_TYPES_MAP.image.key]
- }
- if (this.osType === 'Windows') {
- // 以下平台在选择 windows 镜像时禁用关联密钥
- delete loginTypes[LOGIN_TYPES_MAP.keypair.key]
- }
- return Object.keys(loginTypes)
- },
- sysDiskSize () {
- if (this.detailData.length === 1) {
- const diskInfos = this.detailData[0].disks_info
- const sysDisk = diskInfos.find((item) => { return item.disk_type === 'sys' || item.index === 0 })
- if (sysDisk) {
- return sysDisk.size
- }
- }
- return 0
- },
- isShowColumns () {
- return this.params.columns?.length > 0
- },
- isShowAgent () {
- const { os } = this.form.fd
- if (![HYPERVISORS_MAP.kvm.key, HYPERVISORS_MAP.esxi.key].includes(this.hypervisor)) return false
- if (os === 'Windows') {
- return this.osArch !== HOST_CPU_ARCHS.arm.capabilityKey
- }
- return true
- },
- },
- // watch: {
- // type: {
- // handler (val) {
- // if (val === SERVER_TYPE.public) {
- // this.$nextTick(() => {
- // this.form.fc.setFieldsValue({ 'imageType': IMAGES_TYPE_MAP.public.key })
- // })
- // }
- // },
- // immediate: true,
- // },
- // },
- created () {
- this.serversManager = new Manager('servers', 'v2')
- this.fetchData()
- this.updateImageMsgDebounce = _.debounce(this.updateImageMsg, 600)
- },
- methods: {
- async doRebuildRootSubmit (data) {
- const { autoStart, image, loginType, loginKeypair, loginPassword, deploy_telegraf } = data
- const ids = this.params.data.map(item => item.id)
- const params = {
- reset_password: true,
- auto_start: autoStart,
- image_id: image.key,
- }
- // if (this.isZStack) {
- // params.image_id = this.detailData[0].disks_info[0].image_id
- // }
- if (loginType === 'keypair') {
- params.keypair = loginKeypair
- params.reset_password = false
- } else if (loginType === 'image') {
- params.reset_password = false // 如果登录方式为创建后设置, 则增加参数 reset_password = false
- } else if (loginType === 'password') {
- params.password = loginPassword
- }
- if (this.isZStack) {
- params.reset_password = false
- }
- // 安装监控 agent
- if (this.isShowAgent && deploy_telegraf) {
- params.deploy_telegraf = deploy_telegraf
- }
- return this.params.onManager('batchPerformAction', {
- steadyStatus: ['running', 'ready'],
- id: ids,
- managerArgs: {
- action: 'rebuild-root',
- data: params,
- },
- })
- },
- async handleConfirm () {
- this.loading = true
- try {
- const values = await this.form.fc.validateFields()
- const success = async () => {
- this.loading = true
- await this.doRebuildRootSubmit(values)
- this.loading = false
- this.cancelDialog()
- }
- if (this.enableMFA) {
- this.createDialog('SecretVertifyDialog', {
- action: this.$t('table.title.mfa_validate'),
- success,
- })
- } else {
- success()
- }
- this.loading = false
- } catch (error) {
- this.loading = false
- }
- },
- fetchData () {
- const ids = []
- this.params.data.forEach((item) => {
- ids.push(item.id)
- })
- this.fetchdone = false
- this.serversManager.batchGet({ id: ids })
- .then((res) => {
- this.fetchdone = true
- this.detailData = res.data.data
- this.$set(this.form.fd, 'vmem', _.get(res.data, 'data[0].vmem_size'))
- this.setImageTypeMap(this.detailData)
- })
- .catch(() => {
- this.fetchdone = true
- })
- },
- setImageTypeMap (serverlist) {
- const firstManagerId = serverlist[0].manager_id
- if (serverlist.some(val => val.manager_id !== firstManagerId)) { // 说明多台主机是不在同一个订阅下
- this.imageTypeMap = {
- public_customize: {
- ...IMAGES_TYPE_MAP.public_customize,
- disabled: true,
- tooltip: this.$t('compute.text_1225', [this.$t('dictionary.server'), IMAGES_TYPE_MAP.public_customize.label]),
- },
- }
- }
- },
- updateImageMsg (imageMsg) {
- if (this.firstLoad) {
- const detailData = this.detailData || []
- const diskInfo = (detailData[0] && detailData[0].disks_info) || []
- if (diskInfo.length > 0) {
- const image = diskInfo[0] || {}
- if (imageMsg.name !== image.image) return
- if (!image.image_id) return
- this.$nextTick(() => {
- this.form.fc.setFieldsValue({
- image: {
- key: image.image_id,
- label: image.image || '',
- },
- })
- })
- }
- this.firstLoad = false
- }
- },
- },
- }
- </script>
|