mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-03 04:12:31 +01:00
1233 lines
42 KiB
Vue
1233 lines
42 KiB
Vue
// Licensed to the Apache Software Foundation (ASF) under one
|
|
// or more contributor license agreements. See the NOTICE file
|
|
// distributed with this work for additional information
|
|
// regarding copyright ownership. The ASF licenses this file
|
|
// to you under the Apache License, Version 2.0 (the
|
|
// "License"); you may not use this file except in compliance
|
|
// with the License. You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing,
|
|
// software distributed under the License is distributed on an
|
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
// KIND, either express or implied. See the License for the
|
|
// specific language governing permissions and limitations
|
|
// under the License.
|
|
|
|
<template>
|
|
<div
|
|
:class="'form-layout'"
|
|
@keyup.ctrl.enter="handleSubmit">
|
|
<span v-if="uploadPercentage > 0">
|
|
<loading-outlined />
|
|
{{ $t('message.upload.file.processing') }}
|
|
<a-progress :percent="uploadPercentage" />
|
|
</span>
|
|
<a-spin :spinning="loading" v-else>
|
|
<a-form
|
|
:ref="formRef"
|
|
:model="form"
|
|
:rules="rules"
|
|
@finish="handleSubmit"
|
|
layout="vertical">
|
|
<div v-if="currentForm === 'Create'">
|
|
<a-form-item name="url" ref="url">
|
|
<template #label>
|
|
<tooltip-label :title="$t('label.url')" :tooltip="apiParams.url.description"/>
|
|
</template>
|
|
<a-input
|
|
v-focus="currentForm === 'Create'"
|
|
v-model:value="form.url"
|
|
:placeholder="apiParams.url.description" />
|
|
</a-form-item>
|
|
</div>
|
|
<div v-else-if="currentForm === 'Upload'">
|
|
<a-form-item :label="$t('label.templatefileupload')" name="file" ref="file">
|
|
<a-upload-dragger
|
|
:multiple="false"
|
|
:fileList="fileList"
|
|
@remove="handleRemove"
|
|
:beforeUpload="beforeUpload"
|
|
v-model:value="form.file">
|
|
<p class="ant-upload-drag-icon">
|
|
<cloud-upload-outlined />
|
|
</p>
|
|
<p class="ant-upload-text" v-if="fileList.length === 0">
|
|
{{ $t('label.volume.volumefileupload.description') }}
|
|
</p>
|
|
</a-upload-dragger>
|
|
</a-form-item>
|
|
</div>
|
|
<a-form-item ref="name" name="name">
|
|
<template #label>
|
|
<tooltip-label :title="$t('label.name')" :tooltip="apiParams.name.description"/>
|
|
</template>
|
|
<a-input
|
|
v-model:value="form.name"
|
|
:placeholder="apiParams.name.description"
|
|
v-focus="currentForm === 'Upload'"/>
|
|
</a-form-item>
|
|
<a-form-item ref="displaytext" name="displaytext">
|
|
<template #label>
|
|
<tooltip-label :title="$t('label.displaytext')" :tooltip="apiParams.displaytext.description"/>
|
|
</template>
|
|
<a-input
|
|
v-model:value="form.displaytext"
|
|
:placeholder="apiParams.displaytext.description" />
|
|
</a-form-item>
|
|
<div v-if="currentForm === 'Create'">
|
|
<a-form-item
|
|
name="zoneids"
|
|
ref="zoneids">
|
|
<template #label>
|
|
<tooltip-label :title="$t('label.zone')" :tooltip="apiParams.zoneids.description"/>
|
|
</template>
|
|
<a-select
|
|
v-model:value="form.zoneids"
|
|
:loading="zones.loading"
|
|
mode="multiple"
|
|
optionFilterProp="label"
|
|
:filterOption="(input, option) => {
|
|
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
|
}"
|
|
:placeholder="apiParams.zoneids.description"
|
|
@change="handlerSelectZone">
|
|
<a-select-option v-for="opt in zones.opts" :key="opt.id" :label="opt.name || opt.description">
|
|
<span>
|
|
<resource-icon v-if="opt.icon" :image="opt.icon.base64image" size="1x" style="margin-right: 5px"/>
|
|
<global-outlined v-else style="margin-right: 5px" />
|
|
{{ opt.name || opt.description }}
|
|
</span>
|
|
</a-select-option>
|
|
</a-select>
|
|
</a-form-item>
|
|
</div>
|
|
<div v-else>
|
|
<a-form-item
|
|
ref="zoneid"
|
|
name="zoneid">
|
|
<template #label>
|
|
<tooltip-label :title="$t('label.zoneid')" :tooltip="apiParams.zoneid.description"/>
|
|
</template>
|
|
<a-select
|
|
v-model:value="form.zoneid"
|
|
showSearch
|
|
optionFilterProp="label"
|
|
:filterOption="(input, option) => {
|
|
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
|
}"
|
|
@change="handlerSelectZone"
|
|
:placeholder="apiParams.zoneid.description"
|
|
:loading="zones.loading">
|
|
<a-select-option :value="zone.id" v-for="zone in filteredZones" :key="zone.id" :label="zone.name || zone.description">
|
|
<span>
|
|
<resource-icon v-if="zone.icon" :image="zone.icon.base64image" size="1x" style="margin-right: 5px"/>
|
|
<global-outlined v-else style="margin-right: 5px" />
|
|
{{ zone.name || zone.description }}
|
|
</span>
|
|
</a-select-option>
|
|
</a-select>
|
|
</a-form-item>
|
|
</div>
|
|
<a-form-item name="domainid" ref="domainid" v-if="'listDomains' in $store.getters.apis">
|
|
<template #label>
|
|
<tooltip-label :title="$t('label.domainid')" :tooltip="apiParams.domainid.description"/>
|
|
</template>
|
|
<a-select
|
|
v-model:value="form.domainid"
|
|
showSearch
|
|
optionFilterProp="label"
|
|
:filterOption="(input, option) => {
|
|
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
|
}"
|
|
:loading="domainLoading"
|
|
:placeholder="apiParams.domainid.description"
|
|
@change="val => { handleDomainChange(val) }">
|
|
<a-select-option v-for="(opt, optIndex) in this.domains" :key="optIndex" :label="opt.path || opt.name || opt.description" :value="opt.id">
|
|
<span>
|
|
<resource-icon v-if="opt && opt.icon" :image="opt.icon.base64image" size="1x" style="margin-right: 5px"/>
|
|
<block-outlined v-else style="margin-right: 5px" />
|
|
{{ opt.path || opt.name || opt.description }}
|
|
</span>
|
|
</a-select-option>
|
|
</a-select>
|
|
</a-form-item>
|
|
<a-form-item name="account" ref="account" v-if="domainid">
|
|
<template #label>
|
|
<tooltip-label :title="$t('label.account')" :tooltip="apiParams.account.description"/>
|
|
</template>
|
|
<a-select
|
|
v-model:value="form.account"
|
|
showSearch
|
|
optionFilterProp="label"
|
|
:filterOption="(input, option) => {
|
|
return option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
|
}"
|
|
:placeholder="apiParams.account.description"
|
|
@change="val => { handleAccountChange(val) }">
|
|
<a-select-option v-for="(acc, index) in accounts" :value="acc.name" :key="index">
|
|
{{ acc.name }}
|
|
</a-select-option>
|
|
</a-select>
|
|
</a-form-item>
|
|
<a-row :gutter="12">
|
|
<a-col :md="24" :lg="12">
|
|
<a-form-item ref="hypervisor" name="hypervisor">
|
|
<template #label>
|
|
<tooltip-label :title="$t('label.hypervisor')" :tooltip="apiParams.hypervisor.description"/>
|
|
</template>
|
|
<a-select
|
|
v-model:value="form.hypervisor"
|
|
:loading="hyperVisor.loading"
|
|
:placeholder="apiParams.hypervisor.description"
|
|
@change="handlerSelectHyperVisor"
|
|
showSearch
|
|
optionFilterProp="label"
|
|
:filterOption="(input, option) => {
|
|
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
|
}" >
|
|
<a-select-option v-for="(opt, optIndex) in hyperVisor.opts" :key="optIndex" :label="opt.name || opt.description">
|
|
{{ opt.name || opt.description }}
|
|
</a-select-option>
|
|
</a-select>
|
|
</a-form-item>
|
|
</a-col>
|
|
<a-col :md="24" :lg="12">
|
|
<a-form-item ref="format" name="format">
|
|
<template #label>
|
|
<tooltip-label :title="$t('label.format')" :tooltip="apiParams.format.description"/>
|
|
</template>
|
|
<a-select
|
|
v-model:value="form.format"
|
|
:placeholder="apiParams.format.description"
|
|
@change="val => { selectedFormat = val }"
|
|
showSearch
|
|
optionFilterProp="label"
|
|
:filterOption="(input, option) => {
|
|
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
|
}" >
|
|
<a-select-option v-for="opt in format.opts" :key="opt.id" :label="opt.name || opt.description">
|
|
{{ opt.name || opt.description }}
|
|
</a-select-option>
|
|
</a-select>
|
|
</a-form-item>
|
|
</a-col>
|
|
</a-row>
|
|
<a-row :gutter="12">
|
|
<a-col :md="24" :lg="12" v-if="(hyperKVMShow || hyperCustomShow) && currentForm === 'Create'">
|
|
<a-form-item ref="directdownload" name="directdownload">
|
|
<template #label>
|
|
<tooltip-label :title="$t('label.directdownload')" :tooltip="apiParams.directdownload.description"/>
|
|
</template>
|
|
<a-switch v-model:checked="form.directdownload" @change="handleChangeDirect" />
|
|
</a-form-item>
|
|
</a-col>
|
|
<a-col :md="24" :lg="12">
|
|
<a-form-item ref="checksum" name="checksum">
|
|
<template #label>
|
|
<tooltip-label :title="$t('label.checksum')" :tooltip="apiParams.checksum.description"/>
|
|
</template>
|
|
<a-input
|
|
v-model:value="form.checksum"
|
|
:placeholder="apiParams.checksum.description" />
|
|
</a-form-item>
|
|
</a-col>
|
|
</a-row>
|
|
<a-row :gutter="12" v-if="allowed && hyperXenServerShow">
|
|
<a-form-item ref="xenserverToolsVersion61plus" name="xenserverToolsVersion61plus" v-if="hyperXenServerShow" :label="$t('label.xenservertoolsversion61plus')">
|
|
<a-switch v-model:checked="form.xenserverToolsVersion61plus" />
|
|
</a-form-item>
|
|
</a-row>
|
|
|
|
<a-form-item ref="deployasis" name="deployasis" v-if="selectedFormat === 'OVA'">
|
|
<template #label>
|
|
<tooltip-label :title="$t('label.deployasis')" :tooltip="apiParams.deployasis.description"/>
|
|
</template>
|
|
<a-switch
|
|
v-model:checked="form.deployasis"
|
|
:checked="deployasis"
|
|
@change="val => deployasis = val"/>
|
|
</a-form-item>
|
|
|
|
<a-row :gutter="12" v-if="hyperKVMShow || hyperVMWShow">
|
|
<a-col :md="24" :lg="hyperKVMShow ? 24 : 12" v-if="hyperKVMShow || (hyperVMWShow && !deployasis)">
|
|
<a-form-item ref="rootDiskControllerType" name="rootDiskControllerType" :label="$t('label.rootdiskcontrollertype')">
|
|
<a-select
|
|
v-model:value="form.rootDiskControllerType"
|
|
:loading="rootDisk.loading"
|
|
:placeholder="$t('label.rootdiskcontrollertype')"
|
|
showSearch
|
|
optionFilterProp="label"
|
|
:filterOption="(input, option) => {
|
|
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
|
}" >
|
|
<a-select-option v-for="opt in rootDisk.opts" :key="opt.id" :label="opt.name || opt.description">
|
|
{{ opt.name || opt.description }}
|
|
</a-select-option>
|
|
</a-select>
|
|
</a-form-item>
|
|
</a-col>
|
|
<a-col :md="24" :lg="12" v-if="hyperVMWShow && !deployasis">
|
|
<a-form-item ref="nicAdapterType" name="nicAdapterType" :label="$t('label.nicadaptertype')">
|
|
<a-select
|
|
v-model:value="form.nicAdapterType"
|
|
showSearch
|
|
optionFilterProp="label"
|
|
:filterOption="(input, option) => {
|
|
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
|
}"
|
|
:placeholder="$t('label.nicadaptertype')">
|
|
<a-select-option v-for="opt in nicAdapterType.opts" :key="opt.id" :label="opt.name || opt.description">
|
|
{{ opt.name || opt.description }}
|
|
</a-select-option>
|
|
</a-select>
|
|
</a-form-item>
|
|
</a-col>
|
|
</a-row>
|
|
<a-form-item
|
|
:label="$t('label.keyboardtype')"
|
|
v-if="hyperVMWShow && !deployasis"
|
|
name="keyboardType"
|
|
ref="keyboardType">
|
|
<a-select
|
|
v-model:value="form.keyboardType"
|
|
showSearch
|
|
optionFilterProp="label"
|
|
:filterOption="(input, option) => {
|
|
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
|
}"
|
|
:placeholder="$t('label.keyboard')">
|
|
<a-select-option v-for="opt in keyboardType.opts" :key="opt.id" :label="opt.name || opt.description">
|
|
{{ opt.name || opt.description }}
|
|
</a-select-option>
|
|
</a-select>
|
|
</a-form-item>
|
|
<a-form-item
|
|
name="ostypeid"
|
|
ref="ostypeid"
|
|
v-if="!hyperVMWShow || (hyperVMWShow && !deployasis)">
|
|
<template #label>
|
|
<tooltip-label :title="$t('label.ostypeid')" :tooltip="apiParams.ostypeid.description"/>
|
|
</template>
|
|
<a-select
|
|
showSearch
|
|
optionFilterProp="label"
|
|
:filterOption="(input, option) => {
|
|
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
|
}"
|
|
v-model:value="form.ostypeid"
|
|
:loading="osTypes.loading"
|
|
:placeholder="apiParams.ostypeid.description">
|
|
<a-select-option v-for="opt in osTypes.opts" :key="opt.id" :label="opt.name || opt.description">
|
|
{{ opt.name || opt.description }}
|
|
</a-select-option>
|
|
</a-select>
|
|
</a-form-item>
|
|
<a-form-item
|
|
name="templatetype"
|
|
ref="templatetype">
|
|
<template #label>
|
|
<tooltip-label :title="$t('label.templatetype')" :tooltip="apiParams.templatetype.description"/>
|
|
</template>
|
|
<a-select
|
|
showSearch
|
|
optionFilterProp="label"
|
|
:filterOption="(input, option) => {
|
|
return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
|
}"
|
|
v-model:value="form.templatetype"
|
|
:placeholder="apiParams.templatetype.description">
|
|
<a-select-option v-for="opt in templateTypes.opts" :key="opt.id">
|
|
{{ opt.name || opt.description }}
|
|
</a-select-option>
|
|
</a-select>
|
|
</a-form-item>
|
|
<a-form-item
|
|
name="arch"
|
|
ref="arch">
|
|
<template #label>
|
|
<tooltip-label :title="$t('label.arch')" :tooltip="apiParams.arch.description"/>
|
|
</template>
|
|
<a-select
|
|
showSearch
|
|
optionFilterProp="label"
|
|
:filterOption="(input, option) => {
|
|
return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
|
}"
|
|
v-model:value="form.arch"
|
|
:placeholder="apiParams.arch.description">
|
|
<a-select-option v-for="opt in architectureTypes.opts" :key="opt.id">
|
|
{{ opt.name || opt.description }}
|
|
</a-select-option>
|
|
</a-select>
|
|
</a-form-item>
|
|
<a-form-item ref="templatetag" name="templatetag" v-if="isAdminRole">
|
|
<template #label>
|
|
<tooltip-label :title="$t('label.templatetag')" :tooltip="apiParams.templatetag.description"/>
|
|
</template>
|
|
<a-input
|
|
v-model:value="form.templatetag"
|
|
:placeholder="apiParams.templatetag.description"
|
|
v-focus="currentForm !== 'Create'"/>
|
|
</a-form-item>
|
|
<a-row :gutter="12">
|
|
<a-col :md="24" :lg="12">
|
|
<a-form-item
|
|
name="userdataid"
|
|
ref="userdataid">
|
|
<template #label>
|
|
<tooltip-label :title="$t('label.userdata')" :tooltip="linkUserDataParams.userdataid.description"/>
|
|
</template>
|
|
<a-select
|
|
showSearch
|
|
optionFilterProp="label"
|
|
:filterOption="(input, option) => {
|
|
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
|
}"
|
|
v-model:value="userdataid"
|
|
:placeholder="linkUserDataParams.userdataid.description"
|
|
:loading="userdata.loading">
|
|
<a-select-option v-for="opt in userdata.opts" :key="opt.id" :label="opt.name || opt.description">
|
|
{{ opt.name || opt.description }}
|
|
</a-select-option>
|
|
</a-select>
|
|
</a-form-item>
|
|
</a-col>
|
|
<a-col :md="24" :lg="12">
|
|
<a-form-item ref="userdatapolicy" name="userdatapolicy">
|
|
<template #label>
|
|
<tooltip-label :title="$t('label.userdatapolicy')" :tooltip="linkUserDataParams.userdatapolicy.description"/>
|
|
</template>
|
|
<a-select
|
|
showSearch
|
|
v-model:value="userdatapolicy"
|
|
:placeholder="linkUserDataParams.userdatapolicy.description"
|
|
optionFilterProp="label"
|
|
:filterOption="(input, option) => {
|
|
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
|
}" >
|
|
<a-select-option v-for="opt in userdatapolicylist.opts" :key="opt.id" :label="opt.id || opt.description">
|
|
{{ opt.id || opt.description }}
|
|
</a-select-option>
|
|
</a-select>
|
|
</a-form-item>
|
|
</a-col>
|
|
</a-row>
|
|
<a-row :gutter="12">
|
|
<a-col :md="24" :lg="24">
|
|
<a-form-item ref="groupenabled" name="groupenabled">
|
|
<a-checkbox-group
|
|
v-model:value="form.groupenabled"
|
|
style="width: 100%;"
|
|
>
|
|
<a-row>
|
|
<a-col :span="12">
|
|
<a-checkbox value="isextractable">
|
|
{{ $t('label.isextractable') }}
|
|
</a-checkbox>
|
|
</a-col>
|
|
<a-col :span="12">
|
|
<a-checkbox value="passwordenabled">
|
|
{{ $t('label.passwordenabled') }}
|
|
</a-checkbox>
|
|
</a-col>
|
|
<a-col :span="12">
|
|
<a-checkbox value="isdynamicallyscalable">
|
|
{{ $t('label.isdynamicallyscalable') }}
|
|
</a-checkbox>
|
|
</a-col>
|
|
<a-col :span="12">
|
|
<a-checkbox value="requireshvm">
|
|
{{ $t('label.requireshvm') }}
|
|
</a-checkbox>
|
|
</a-col>
|
|
<a-col :span="12" v-if="isAdminRole">
|
|
<a-checkbox value="isfeatured">
|
|
{{ $t('label.isfeatured') }}
|
|
</a-checkbox>
|
|
</a-col>
|
|
<a-col :span="12" v-if="isAdminRole || $store.getters.features.userpublictemplateenabled">
|
|
<a-checkbox value="ispublic">
|
|
{{ $t('label.ispublic') }}
|
|
</a-checkbox>
|
|
</a-col>
|
|
</a-row>
|
|
</a-checkbox-group>
|
|
</a-form-item>
|
|
</a-col>
|
|
</a-row>
|
|
<div :span="24" class="action-button">
|
|
<a-button @click="closeAction">{{ $t('label.cancel') }}</a-button>
|
|
<a-button :loading="loading" ref="submit" type="primary" @click="handleSubmit">{{ $t('label.ok') }}</a-button>
|
|
</div>
|
|
</a-form>
|
|
</a-spin>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { ref, reactive, toRaw } from 'vue'
|
|
import { api } from '@/api'
|
|
import store from '@/store'
|
|
import { axios } from '../../utils/request'
|
|
import { mixinForm } from '@/utils/mixin'
|
|
import ResourceIcon from '@/components/view/ResourceIcon'
|
|
import TooltipLabel from '@/components/widgets/TooltipLabel'
|
|
|
|
export default {
|
|
name: 'RegisterOrUploadTemplate',
|
|
mixins: [mixinForm],
|
|
props: {
|
|
resource: {
|
|
type: Object,
|
|
required: true
|
|
},
|
|
action: {
|
|
type: Object,
|
|
required: true
|
|
}
|
|
},
|
|
components: {
|
|
ResourceIcon,
|
|
TooltipLabel
|
|
},
|
|
data () {
|
|
return {
|
|
uploadPercentage: 0,
|
|
uploading: false,
|
|
fileList: [],
|
|
zones: {},
|
|
defaultZone: '',
|
|
hyperVisor: {},
|
|
rootDisk: {},
|
|
nicAdapterType: {},
|
|
keyboardType: {},
|
|
format: {},
|
|
osTypes: {},
|
|
defaultOsType: '',
|
|
templateTypes: {},
|
|
userdata: {},
|
|
userdataid: null,
|
|
userdatapolicy: null,
|
|
userdatapolicylist: {},
|
|
defaultOsId: null,
|
|
hyperKVMShow: false,
|
|
hyperCustomShow: false,
|
|
hyperXenServerShow: false,
|
|
hyperVMWShow: false,
|
|
selectedFormat: '',
|
|
deployasis: false,
|
|
zoneError: '',
|
|
loading: false,
|
|
rootAdmin: 'Admin',
|
|
allowed: false,
|
|
allowDirectDownload: false,
|
|
uploadParams: null,
|
|
currentForm: ['plus-outlined', 'PlusOutlined'].includes(this.action.currentAction.icon) ? 'Create' : 'Upload',
|
|
domains: [],
|
|
accounts: [],
|
|
domainLoading: false,
|
|
domainid: null,
|
|
account: null,
|
|
customHypervisorName: 'Custom',
|
|
architectureTypes: {}
|
|
}
|
|
},
|
|
beforeCreate () {
|
|
this.apiParams = this.$getApiParams('registerTemplate')
|
|
this.linkUserDataParams = this.$getApiParams('linkUserDataToTemplate')
|
|
},
|
|
created () {
|
|
this.initForm()
|
|
this.fetchData()
|
|
},
|
|
computed: {
|
|
isAdminRole () {
|
|
return this.$store.getters.userInfo.roletype === 'Admin'
|
|
},
|
|
filteredZones () {
|
|
let zoneList = this.zones.opts
|
|
if (zoneList && zoneList.length > 0 && this.currentForm === 'Upload') {
|
|
zoneList = zoneList.filter(zone => zone.type !== 'Edge')
|
|
}
|
|
return zoneList
|
|
}
|
|
},
|
|
methods: {
|
|
initForm () {
|
|
this.formRef = ref()
|
|
this.form = reactive({
|
|
deployasis: false,
|
|
groupenabled: ['requireshvm']
|
|
})
|
|
this.rules = reactive({
|
|
url: [{ required: true, message: this.$t('message.error.required.input') }],
|
|
file: [{ required: true, message: this.$t('message.error.required.input') }],
|
|
name: [{ required: true, message: this.$t('message.error.required.input') }],
|
|
zoneids: [
|
|
{ type: 'array', required: true, message: this.$t('message.error.select') },
|
|
{
|
|
validator: this.validZone
|
|
}
|
|
],
|
|
zoneid: [{ required: true, message: this.$t('message.error.select') }],
|
|
hypervisor: [{ type: 'number', required: true, message: this.$t('message.error.select') }],
|
|
format: [{ required: true, message: this.$t('message.error.select') }],
|
|
ostypeid: [{ required: true, message: this.$t('message.error.select') }],
|
|
groupenabled: [{ type: 'array' }]
|
|
})
|
|
},
|
|
fetchData () {
|
|
this.fetchCustomHypervisorName()
|
|
this.fetchZone()
|
|
this.fetchOsTypes()
|
|
this.fetchTemplateTypes()
|
|
this.architectureTypes.opts = this.$fetchCpuArchitectureTypes()
|
|
this.fetchUserData()
|
|
this.fetchUserdataPolicy()
|
|
if ('listDomains' in this.$store.getters.apis) {
|
|
this.fetchDomains()
|
|
}
|
|
if (Object.prototype.hasOwnProperty.call(store.getters.apis, 'listConfigurations')) {
|
|
if (this.allowed && this.hyperXenServerShow) {
|
|
this.fetchXenServerProvider()
|
|
}
|
|
}
|
|
},
|
|
handleFormChange (e) {
|
|
this.currentForm = e.target.value
|
|
},
|
|
handleRemove (file) {
|
|
const index = this.fileList.indexOf(file)
|
|
const newFileList = this.fileList.slice()
|
|
newFileList.splice(index, 1)
|
|
this.fileList = newFileList
|
|
this.form.file = undefined
|
|
},
|
|
beforeUpload (file) {
|
|
this.fileList = [file]
|
|
this.form.file = file
|
|
return false
|
|
},
|
|
handleUpload () {
|
|
const { fileList } = this
|
|
const formData = new FormData()
|
|
fileList.forEach(file => {
|
|
formData.append('files[]', file)
|
|
})
|
|
this.uploadPercentage = 0
|
|
axios.post(this.uploadParams.postURL,
|
|
formData,
|
|
{
|
|
headers: {
|
|
'content-type': 'multipart/form-data',
|
|
'x-signature': this.uploadParams.signature,
|
|
'x-expires': this.uploadParams.expires,
|
|
'x-metadata': this.uploadParams.metadata
|
|
},
|
|
onUploadProgress: (progressEvent) => {
|
|
this.uploadPercentage = Number(parseFloat(100 * progressEvent.loaded / progressEvent.total).toFixed(1))
|
|
},
|
|
timeout: 86400000
|
|
}).then((json) => {
|
|
this.$notification.success({
|
|
message: this.$t('message.success.upload'),
|
|
description: this.$t('message.success.upload.template.description')
|
|
})
|
|
this.$emit('refresh-data')
|
|
this.closeAction()
|
|
}).catch(e => {
|
|
this.$notification.error({
|
|
message: this.$t('message.upload.failed'),
|
|
description: `${this.$t('message.upload.template.failed.description')} - ${e}`,
|
|
duration: 0
|
|
})
|
|
})
|
|
},
|
|
fetchCustomHypervisorName () {
|
|
const params = {
|
|
name: 'hypervisor.custom.display.name'
|
|
}
|
|
this.loading = true
|
|
api('listConfigurations', params).then(json => {
|
|
if (json.listconfigurationsresponse.configuration !== null) {
|
|
const config = json.listconfigurationsresponse.configuration[0]
|
|
if (config && config.name === params.name) {
|
|
this.customHypervisorName = config.value
|
|
store.dispatch('SetCustomHypervisorName', this.customHypervisorName)
|
|
}
|
|
}
|
|
}).finally(() => {
|
|
this.loading = false
|
|
})
|
|
},
|
|
fetchZone () {
|
|
const params = {}
|
|
let listZones = []
|
|
params.showicon = true
|
|
this.allowed = false
|
|
|
|
if (store.getters.userInfo.roletype === this.rootAdmin && this.currentForm === 'Create') {
|
|
this.allowed = true
|
|
listZones.push({
|
|
id: this.$t('label.all.zone'),
|
|
name: this.$t('label.all.zone')
|
|
})
|
|
}
|
|
|
|
this.zones.loading = true
|
|
this.zones.opts = []
|
|
|
|
api('listZones', params).then(json => {
|
|
const listZonesResponse = json.listzonesresponse.zone
|
|
listZones = listZones.concat(listZonesResponse)
|
|
this.zones.opts = listZones
|
|
}).finally(() => {
|
|
this.form.zoneid = (this.filteredZones && this.filteredZones[1]) ? this.filteredZones[1].id : ''
|
|
if (!this.form.zoneid) {
|
|
this.form.zoneid = (this.filteredZones && this.filteredZones[0] && this.filteredZones[0].id !== this.$t('label.all.zone')) ? this.filteredZones[0].id : ''
|
|
}
|
|
this.zones.loading = false
|
|
if (this.form.zoneid) {
|
|
this.fetchHyperVisor({ zoneid: this.form.zoneid })
|
|
}
|
|
})
|
|
},
|
|
fetchHyperVisor (params) {
|
|
this.hyperVisor.loading = true
|
|
let listhyperVisors = this.hyperVisor.opts || []
|
|
|
|
api('listHypervisors', params).then(json => {
|
|
const listResponse = json.listhypervisorsresponse.hypervisor || []
|
|
if (listResponse) {
|
|
listhyperVisors = listhyperVisors.concat(listResponse)
|
|
}
|
|
if (this.currentForm === 'Create') {
|
|
listhyperVisors.push({
|
|
name: 'Simulator'
|
|
})
|
|
}
|
|
this.hyperVisor.opts = listhyperVisors
|
|
}).finally(() => {
|
|
this.hyperVisor.loading = false
|
|
})
|
|
},
|
|
fetchOsTypes () {
|
|
this.osTypes.opts = []
|
|
this.osTypes.loading = true
|
|
|
|
api('listOsTypes').then(json => {
|
|
const listOsTypes = json.listostypesresponse.ostype
|
|
this.osTypes.opts = listOsTypes
|
|
this.defaultOsType = this.osTypes.opts[1].description
|
|
this.defaultOsId = this.osTypes.opts[1].name
|
|
}).finally(() => {
|
|
this.osTypes.loading = false
|
|
})
|
|
},
|
|
fetchTemplateTypes () {
|
|
this.templateTypes.opts = []
|
|
const templatetypes = []
|
|
templatetypes.push({
|
|
id: 'USER',
|
|
description: 'USER'
|
|
})
|
|
templatetypes.push({
|
|
id: 'VNF',
|
|
description: 'VNF'
|
|
})
|
|
if (this.isAdminRole) {
|
|
templatetypes.push({
|
|
id: 'SYSTEM',
|
|
description: 'SYSTEM'
|
|
})
|
|
templatetypes.push({
|
|
id: 'BUILTIN',
|
|
description: 'BUILTIN'
|
|
})
|
|
templatetypes.push({
|
|
id: 'ROUTING',
|
|
description: 'ROUTING'
|
|
})
|
|
}
|
|
this.templateTypes.opts = templatetypes
|
|
},
|
|
fetchUserData () {
|
|
const params = {}
|
|
params.listAll = true
|
|
|
|
this.userdata.opts = []
|
|
this.userdata.loading = true
|
|
|
|
api('listUserData', params).then(json => {
|
|
const listUserdata = json.listuserdataresponse.userdata
|
|
this.userdata.opts = listUserdata
|
|
}).finally(() => {
|
|
this.userdata.loading = false
|
|
})
|
|
},
|
|
fetchXenServerProvider () {
|
|
const params = {}
|
|
params.name = 'xenserver.pvdriver.version'
|
|
|
|
this.form.xenserverToolsVersion61plus = true
|
|
|
|
api('listConfigurations', params).then(json => {
|
|
if (json.listconfigurationsresponse.configuration !== null && json.listconfigurationsresponse.configuration[0].value !== 'xenserver61') {
|
|
this.form.xenserverToolsVersion61plus = false
|
|
}
|
|
})
|
|
},
|
|
fetchRootDisk (hyperVisor) {
|
|
const controller = []
|
|
this.rootDisk.opts = []
|
|
|
|
if (hyperVisor === 'KVM') {
|
|
controller.push({
|
|
id: '',
|
|
description: ''
|
|
})
|
|
controller.push({
|
|
id: 'ide',
|
|
description: 'ide'
|
|
})
|
|
controller.push({
|
|
id: 'osdefault',
|
|
description: 'osdefault'
|
|
})
|
|
controller.push({
|
|
id: 'scsi',
|
|
description: 'scsi'
|
|
})
|
|
controller.push({
|
|
id: 'virtio',
|
|
description: 'virtio'
|
|
})
|
|
} else if (hyperVisor === 'VMware') {
|
|
controller.push({
|
|
id: '',
|
|
description: ''
|
|
})
|
|
controller.push({
|
|
id: 'scsi',
|
|
description: 'scsi'
|
|
})
|
|
controller.push({
|
|
id: 'ide',
|
|
description: 'ide'
|
|
})
|
|
controller.push({
|
|
id: 'osdefault',
|
|
description: 'osdefault'
|
|
})
|
|
controller.push({
|
|
id: 'pvscsi',
|
|
description: 'pvscsi'
|
|
})
|
|
controller.push({
|
|
id: 'lsilogic',
|
|
description: 'lsilogic'
|
|
})
|
|
controller.push({
|
|
id: 'lsisas1068',
|
|
description: 'lsilogicsas'
|
|
})
|
|
controller.push({
|
|
id: 'buslogic',
|
|
description: 'buslogic'
|
|
})
|
|
}
|
|
|
|
this.rootDisk.opts = controller
|
|
},
|
|
fetchNicAdapterTypes () {
|
|
const nicAdapterTypes = []
|
|
nicAdapterTypes.push({
|
|
id: '',
|
|
description: ''
|
|
})
|
|
nicAdapterTypes.push({
|
|
id: 'E1000',
|
|
description: 'E1000'
|
|
})
|
|
nicAdapterTypes.push({
|
|
id: 'PCNet32',
|
|
description: 'PCNet32'
|
|
})
|
|
nicAdapterTypes.push({
|
|
id: 'Vmxnet2',
|
|
description: 'Vmxnet2'
|
|
})
|
|
nicAdapterTypes.push({
|
|
id: 'Vmxnet3',
|
|
description: 'Vmxnet3'
|
|
})
|
|
|
|
this.nicAdapterType.opts = nicAdapterTypes
|
|
},
|
|
fetchKeyboardType () {
|
|
const keyboardType = []
|
|
const keyboardOpts = this.$config.keyboardOptions || {}
|
|
keyboardType.push({
|
|
id: '',
|
|
description: ''
|
|
})
|
|
|
|
Object.keys(keyboardOpts).forEach(keyboard => {
|
|
keyboardType.push({
|
|
id: keyboard,
|
|
description: this.$t(keyboardOpts[keyboard])
|
|
})
|
|
})
|
|
|
|
this.keyboardType.opts = keyboardType
|
|
},
|
|
fetchFormat (hyperVisor) {
|
|
const format = []
|
|
|
|
switch (hyperVisor) {
|
|
case 'Hyperv':
|
|
format.push({
|
|
id: 'VHD',
|
|
description: 'VHD'
|
|
})
|
|
format.push({
|
|
id: 'VHDX',
|
|
description: 'VHDX'
|
|
})
|
|
break
|
|
case 'KVM':
|
|
this.hyperKVMShow = true
|
|
format.push({
|
|
id: 'QCOW2',
|
|
description: 'QCOW2'
|
|
})
|
|
format.push({
|
|
id: 'RAW',
|
|
description: 'RAW'
|
|
})
|
|
format.push({
|
|
id: 'VHD',
|
|
description: 'VHD'
|
|
})
|
|
format.push({
|
|
id: 'VMDK',
|
|
description: 'VMDK'
|
|
})
|
|
break
|
|
case 'XenServer':
|
|
this.hyperXenServerShow = true
|
|
format.push({
|
|
id: 'VHD',
|
|
description: 'VHD'
|
|
})
|
|
break
|
|
case 'Simulator':
|
|
format.push({
|
|
id: 'VHD',
|
|
description: 'VHD'
|
|
})
|
|
break
|
|
case 'VMware':
|
|
this.hyperVMWShow = true
|
|
format.push({
|
|
id: 'OVA',
|
|
description: 'OVA'
|
|
})
|
|
break
|
|
case 'BareMetal':
|
|
format.push({
|
|
id: 'BareMetal',
|
|
description: 'BareMetal'
|
|
})
|
|
break
|
|
case 'Ovm':
|
|
format.push({
|
|
id: 'RAW',
|
|
description: 'RAW'
|
|
})
|
|
break
|
|
case 'LXC':
|
|
format.push({
|
|
id: 'TAR',
|
|
description: 'TAR'
|
|
})
|
|
break
|
|
case this.customHypervisorName:
|
|
this.hyperCustomShow = true
|
|
format.push({
|
|
id: 'RAW',
|
|
description: 'RAW'
|
|
})
|
|
break
|
|
default:
|
|
break
|
|
}
|
|
this.format.opts = format
|
|
},
|
|
fetchUserdataPolicy () {
|
|
const userdataPolicy = []
|
|
userdataPolicy.push({
|
|
id: 'allowoverride',
|
|
description: 'allowoverride'
|
|
})
|
|
userdataPolicy.push({
|
|
id: 'append',
|
|
description: 'append'
|
|
})
|
|
userdataPolicy.push({
|
|
id: 'denyoverride',
|
|
description: 'denyoverride'
|
|
})
|
|
this.userdatapolicylist.opts = userdataPolicy
|
|
},
|
|
|
|
handlerSelectZone (value) {
|
|
if (!Array.isArray(value)) {
|
|
value = [value]
|
|
}
|
|
this.hyperVisor.opts = []
|
|
|
|
const allZoneExists = value.filter(zone => zone === this.$t('label.all.zone'))
|
|
if (allZoneExists.length > 0 && value.length > 1) {
|
|
return
|
|
}
|
|
const arrSelectReset = ['hypervisor', 'format', 'rootDiskControllerType', 'nicAdapterType', 'keyboardType']
|
|
this.resetSelect(arrSelectReset)
|
|
|
|
const params = {}
|
|
|
|
if (value.includes(this.$t('label.all.zone'))) {
|
|
this.fetchHyperVisor(params)
|
|
return
|
|
}
|
|
|
|
for (let i = 0; i < value.length; i++) {
|
|
const zoneSelected = this.zones.opts.filter(zone => zone.id === value[i])
|
|
|
|
if (zoneSelected.length > 0) {
|
|
params.zoneid = zoneSelected[0].id
|
|
this.fetchHyperVisor(params)
|
|
}
|
|
}
|
|
},
|
|
handlerSelectHyperVisor (value) {
|
|
const hyperVisor = this.hyperVisor.opts[value].name
|
|
const arrSelectReset = ['format', 'rootDiskControllerType', 'nicAdapterType', 'keyboardType']
|
|
|
|
this.hyperXenServerShow = false
|
|
this.hyperVMWShow = false
|
|
this.hyperKVMShow = false
|
|
this.hyperCustomShow = false
|
|
this.deployasis = false
|
|
this.allowDirectDownload = false
|
|
this.selectedFormat = null
|
|
this.form.deployasis = false
|
|
this.form.directdownload = false
|
|
this.form.xenserverToolsVersion61plus = false
|
|
|
|
this.resetSelect(arrSelectReset)
|
|
this.fetchFormat(hyperVisor)
|
|
this.fetchRootDisk(hyperVisor)
|
|
this.fetchNicAdapterTypes()
|
|
this.fetchKeyboardType()
|
|
|
|
this.form.rootDiskControllerType = this.rootDisk.opts.length > 0 ? 'osdefault' : ''
|
|
},
|
|
handleSubmit (e) {
|
|
e.preventDefault()
|
|
if (this.loading) return
|
|
this.formRef.value.validate().then(() => {
|
|
if (this.currentForm === 'Create') {
|
|
delete this.form.zoneid
|
|
} else {
|
|
delete this.form.zoneids
|
|
}
|
|
const formRaw = toRaw(this.form)
|
|
const formvalues = this.handleRemoveFields(formRaw)
|
|
let params = {}
|
|
for (const key in formvalues) {
|
|
const input = formvalues[key]
|
|
|
|
if (input === undefined) {
|
|
continue
|
|
}
|
|
if (key === 'file') {
|
|
continue
|
|
}
|
|
|
|
if (key === 'zoneids') {
|
|
if (input.length === 1 && input[0] === this.$t('label.all.zone')) {
|
|
params.zoneids = '-1'
|
|
continue
|
|
}
|
|
params[key] = input.join()
|
|
} else if (key === 'hypervisor') {
|
|
params[key] = this.hyperVisor.opts[input].name
|
|
} else if (key === 'groupenabled') {
|
|
for (const index in input) {
|
|
const name = input[index]
|
|
params[name] = true
|
|
}
|
|
} else {
|
|
const formattedDetailData = {}
|
|
switch (key) {
|
|
case 'rootDiskControllerType':
|
|
if (input) {
|
|
formattedDetailData['details[0].rootDiskController'] = input
|
|
}
|
|
break
|
|
case 'nicAdapterType':
|
|
formattedDetailData['details[0].nicAdapter'] = input
|
|
break
|
|
case 'keyboardType':
|
|
formattedDetailData['details[0].keyboard'] = input
|
|
break
|
|
case 'xenserverToolsVersion61plus':
|
|
formattedDetailData['details[0].hypervisortoolsversion'] = input
|
|
break
|
|
}
|
|
|
|
if (Object.keys(formattedDetailData).length > 0) {
|
|
params = Object.assign({}, params, formattedDetailData)
|
|
} else {
|
|
params[key] = input
|
|
}
|
|
}
|
|
}
|
|
if (!('requireshvm' in params)) { // handled as default true by API
|
|
params.requireshvm = false
|
|
}
|
|
if (this.currentForm === 'Create') {
|
|
this.loading = true
|
|
api('registerTemplate', params).then(json => {
|
|
if (this.userdataid !== null) {
|
|
this.linkUserdataToTemplate(this.userdataid, json.registertemplateresponse.template[0].id, this.userdatapolicy)
|
|
}
|
|
this.$notification.success({
|
|
message: this.$t('label.register.template'),
|
|
description: `${this.$t('message.success.register.template')} ${params.name}`
|
|
})
|
|
this.$emit('refresh-data')
|
|
this.closeAction()
|
|
}).catch(error => {
|
|
this.$notifyError(error)
|
|
}).finally(() => {
|
|
this.loading = false
|
|
})
|
|
} else if (this.currentForm === 'Upload') {
|
|
this.loading = true
|
|
if (this.fileList.length > 1) {
|
|
this.$notification.error({
|
|
message: this.$t('message.error.upload.template'),
|
|
description: this.$t('message.error.upload.template.description'),
|
|
duration: 0
|
|
})
|
|
}
|
|
api('getUploadParamsForTemplate', params).then(json => {
|
|
this.uploadParams = (json.postuploadtemplateresponse && json.postuploadtemplateresponse.getuploadparams) ? json.postuploadtemplateresponse.getuploadparams : ''
|
|
this.handleUpload()
|
|
if (this.userdataid !== null) {
|
|
this.linkUserdataToTemplate(this.userdataid, json.postuploadtemplateresponse.template[0].id)
|
|
}
|
|
}).catch(error => {
|
|
this.$notifyError(error)
|
|
}).finally(() => {
|
|
this.loading = false
|
|
})
|
|
}
|
|
}).catch(error => {
|
|
this.formRef.value.scrollToField(error.errorFields[0].name)
|
|
})
|
|
},
|
|
handleChangeDirect (checked) {
|
|
this.allowDirectDownload = checked
|
|
},
|
|
async validZone (rule, value) {
|
|
if (!value || value.length === 0) {
|
|
return Promise.resolve()
|
|
}
|
|
const allZoneExists = value.filter(zone => zone === this.$t('label.all.zone'))
|
|
|
|
if (allZoneExists.length > 0 && value.length > 1) {
|
|
return Promise.reject(this.$t('message.error.zone.combined'))
|
|
}
|
|
|
|
return Promise.resolve()
|
|
},
|
|
closeAction () {
|
|
this.$emit('close-action')
|
|
},
|
|
linkUserdataToTemplate (userdataid, templateid, userdatapolicy) {
|
|
this.loading = true
|
|
const params = {}
|
|
params.userdataid = userdataid
|
|
params.templateid = templateid
|
|
if (userdatapolicy) {
|
|
params.userdatapolicy = userdatapolicy
|
|
}
|
|
api('linkUserDataToTemplate', params).then(json => {
|
|
this.closeAction()
|
|
}).catch(error => {
|
|
this.$notifyError(error)
|
|
}).finally(() => {
|
|
this.loading = false
|
|
})
|
|
},
|
|
resetSelect (arrSelectReset) {
|
|
arrSelectReset.forEach(name => {
|
|
this.form[name] = undefined
|
|
})
|
|
},
|
|
fetchDomains () {
|
|
const params = {}
|
|
params.listAll = true
|
|
params.showicon = true
|
|
params.details = 'min'
|
|
this.domainLoading = true
|
|
api('listDomains', params).then(json => {
|
|
this.domains = json.listdomainsresponse.domain
|
|
}).finally(() => {
|
|
this.domainLoading = false
|
|
this.handleDomainChange(null)
|
|
})
|
|
},
|
|
handleDomainChange (domain) {
|
|
this.domainid = domain
|
|
this.form.account = null
|
|
this.account = null
|
|
if ('listAccounts' in this.$store.getters.apis) {
|
|
this.fetchAccounts()
|
|
}
|
|
},
|
|
fetchAccounts () {
|
|
api('listAccounts', {
|
|
domainid: this.domainid
|
|
}).then(response => {
|
|
this.accounts = response.listaccountsresponse.account || []
|
|
}).catch(error => {
|
|
this.$notifyError(error)
|
|
})
|
|
},
|
|
handleAccountChange (acc) {
|
|
if (acc) {
|
|
this.account = acc.name
|
|
} else {
|
|
this.account = acc
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped lang="less">
|
|
.form-layout {
|
|
width: 80vw;
|
|
|
|
@media (min-width: 700px) {
|
|
width: 550px;
|
|
}
|
|
}
|
|
</style>
|