| // 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" v-ctrl-enter="handleSubmit"> | 
 |     <a-spin :spinning="loading"> | 
 |       <a-form | 
 |         :ref="formRef" | 
 |         :model="form" | 
 |         :rules="rules" | 
 |         @finish="handleSubmit" | 
 |         layout="vertical"> | 
 |         <a-form-item name="volumeid" ref="volumeid"> | 
 |           <template #label> | 
 |             <tooltip-label :title="$t('label.volumeid')" :tooltip="apiParams.volumeid.description"/> | 
 |           </template> | 
 |           <a-select | 
 |             allowClear | 
 |             v-model:value="form.volumeid" | 
 |             @change="onChangeVolume" | 
 |             :placeholder="apiParams.volumeid.description" | 
 |             v-focus="true" | 
 |             showSearch | 
 |             optionFilterProp="label" | 
 |             :filterOption="(input, option) => { | 
 |               return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0 | 
 |             }"> | 
 |             <a-select-option | 
 |               v-for="volume in listVolumes" | 
 |               :key="volume.id" | 
 |               :label="volume.name"> | 
 |               {{ volume.name }} | 
 |             </a-select-option> | 
 |           </a-select> | 
 |         </a-form-item> | 
 |         <a-form-item name="name" ref="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"/> | 
 |         </a-form-item> | 
 |         <a-form-item name="quiescevm" ref="quiescevm" v-if="isQuiesceVm"> | 
 |           <template #label> | 
 |             <tooltip-label :title="$t('label.quiescevm')" :tooltip="apiParams.quiescevm.description"/> | 
 |           </template> | 
 |           <a-switch v-model:checked="form.quiescevm"/> | 
 |         </a-form-item> | 
 |         <a-form-item name="asyncbackup" ref="asyncbackup"> | 
 |           <template #label> | 
 |             <tooltip-label :title="$t('label.asyncbackup')" :tooltip="apiParams.asyncbackup.description"/> | 
 |           </template> | 
 |           <a-switch v-model:checked="form.asyncbackup"/> | 
 |         </a-form-item> | 
 |         <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 { mixinForm } from '@/utils/mixin' | 
 | import TooltipLabel from '@/components/widgets/TooltipLabel' | 
 |  | 
 | export default { | 
 |   name: 'CreateSnapshotWizard', | 
 |   mixins: [mixinForm], | 
 |   components: { | 
 |     TooltipLabel | 
 |   }, | 
 |   props: { | 
 |     resource: { | 
 |       type: Object, | 
 |       required: true | 
 |     } | 
 |   }, | 
 |   data () { | 
 |     return { | 
 |       loading: false, | 
 |       isQuiesceVm: false, | 
 |       supportsStorageSnapshot: false, | 
 |       listVolumes: [] | 
 |     } | 
 |   }, | 
 |   beforeCreate () { | 
 |     this.apiParams = this.$getApiParams('createSnapshot') | 
 |   }, | 
 |   created () { | 
 |     this.initForm() | 
 |     this.fetchData() | 
 |   }, | 
 |   methods: { | 
 |     initForm () { | 
 |       this.formRef = ref() | 
 |       this.form = reactive({}) | 
 |       this.rules = reactive({ | 
 |         volumeid: [{ required: true, message: this.$t('message.error.select') }] | 
 |       }) | 
 |     }, | 
 |     fetchData () { | 
 |       this.loading = true | 
 |  | 
 |       api('listVolumes', { virtualMachineId: this.resource.id, listall: true }) | 
 |         .then(json => { | 
 |           this.listVolumes = json.listvolumesresponse.volume || [] | 
 |         }) | 
 |         .catch(e => {}) | 
 |         .finally(() => { this.loading = false }) | 
 |     }, | 
 |     handleSubmit (e) { | 
 |       e.preventDefault() | 
 |  | 
 |       if (this.loading) return | 
 |       this.formRef.value.validate().then(() => { | 
 |         const formRaw = toRaw(this.form) | 
 |         const values = this.handleRemoveFields(formRaw) | 
 |         const params = {} | 
 |         params.volumeid = values.volumeid | 
 |         params.name = values.name | 
 |         params.asyncbackup = false | 
 |         if (values.asyncbackup) { | 
 |           params.asyncbackup = values.asyncbackup | 
 |         } | 
 |         params.quiescevm = values.quiescevm | 
 |  | 
 |         const title = this.$t('label.action.vmstoragesnapshot.create') | 
 |         const description = values.name || values.volumeid | 
 |  | 
 |         this.loading = true | 
 |  | 
 |         api('createSnapshot', params) | 
 |           .then(json => { | 
 |             const jobId = json.createsnapshotresponse.jobid | 
 |             if (jobId) { | 
 |               this.$pollJob({ | 
 |                 jobId, | 
 |                 title, | 
 |                 description, | 
 |                 successMethod: result => { | 
 |                   const volumeId = result.jobresult.snapshot.volumeid | 
 |                   const snapshotId = result.jobresult.snapshot.id | 
 |                   const message = `${this.$t('label.create.snapshot.for.volume')} ${volumeId} ${this.$t('label.with.snapshotid')} ${snapshotId}` | 
 |                   this.$notification.success({ | 
 |                     message: message, | 
 |                     duration: 0 | 
 |                   }) | 
 |                 }, | 
 |                 loadingMessage: `${title} ${this.$t('label.in.progress')}`, | 
 |                 catchMessage: this.$t('error.fetching.async.job.result') | 
 |               }) | 
 |             } | 
 |           }).catch(error => { | 
 |             this.$notifyError(error) | 
 |           }).finally(() => { | 
 |             this.loading = false | 
 |             this.closeAction() | 
 |           }) | 
 |       }).catch(error => { | 
 |         this.formRef.value.scrollToField(error.errorFields[0].name) | 
 |       }) | 
 |     }, | 
 |     onChangeVolume (volumeId) { | 
 |       const volumeFilter = this.listVolumes.filter(volume => volume.id === volumeId) | 
 |       if (volumeFilter && volumeFilter.length > 0) { | 
 |         this.isQuiesceVm = volumeFilter[0].quiescevm | 
 |         this.supportsStorageSnapshot = volumeFilter[0].supportsstoragesnapshot | 
 |       } | 
 |     }, | 
 |     closeAction () { | 
 |       this.$emit('close-action') | 
 |     } | 
 |   } | 
 | } | 
 | </script> | 
 |  | 
 | <style scoped lang="less"> | 
 | .form-layout { | 
 |   width: 80vw; | 
 |   @media (min-width: 600px) { | 
 |     width: 450px; | 
 |   } | 
 | } | 
 | </style> |