mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
storage: Allow creating snapshot from VM snapshot (#587)
In old UI we support creating snapshot from VM snapshot by selecting one of the volume belonging to VM. Allow the same in new UI Co-authored-by: Rakesh Venkatesh <r.venkatesh@global.leaseweb.com> Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
parent
3a81c55932
commit
2bc239fa76
@ -256,6 +256,7 @@ export default {
|
|||||||
columns: () => {
|
columns: () => {
|
||||||
var fields = ['name', 'state', 'volumename', 'intervaltype', 'created']
|
var fields = ['name', 'state', 'volumename', 'intervaltype', 'created']
|
||||||
if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) {
|
if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) {
|
||||||
|
fields.push('domain')
|
||||||
fields.push('account')
|
fields.push('account')
|
||||||
}
|
}
|
||||||
return fields
|
return fields
|
||||||
@ -315,7 +316,7 @@ export default {
|
|||||||
permission: ['listVMSnapshot'],
|
permission: ['listVMSnapshot'],
|
||||||
resourceType: 'VMSnapshot',
|
resourceType: 'VMSnapshot',
|
||||||
columns: () => {
|
columns: () => {
|
||||||
var fields = ['displayname', 'state', 'name', 'type', 'current', 'parentName', 'created']
|
const fields = ['displayname', 'state', 'name', 'type', 'current', 'parentName', 'created']
|
||||||
if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) {
|
if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) {
|
||||||
fields.push('domain')
|
fields.push('domain')
|
||||||
fields.push('account')
|
fields.push('account')
|
||||||
@ -325,6 +326,16 @@ export default {
|
|||||||
details: ['name', 'id', 'displayname', 'description', 'type', 'current', 'parentName', 'virtualmachineid', 'account', 'domain', 'created'],
|
details: ['name', 'id', 'displayname', 'description', 'type', 'current', 'parentName', 'virtualmachineid', 'account', 'domain', 'created'],
|
||||||
searchFilters: ['name', 'domainid', 'account', 'tags'],
|
searchFilters: ['name', 'domainid', 'account', 'tags'],
|
||||||
actions: [
|
actions: [
|
||||||
|
{
|
||||||
|
api: 'createSnapshotFromVMSnapshot',
|
||||||
|
icon: 'camera',
|
||||||
|
label: 'label.action.create.snapshot.from.vmsnapshot',
|
||||||
|
message: 'message.action.create.snapshot.from.vmsnapshot',
|
||||||
|
dataView: true,
|
||||||
|
popup: true,
|
||||||
|
show: (record) => { return (record.state === 'Ready' && record.hypervisor === 'KVM') },
|
||||||
|
component: () => import('@/views/storage/CreateSnapshotFromVMSnapshot.vue')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
api: 'revertToVMSnapshot',
|
api: 'revertToVMSnapshot',
|
||||||
icon: 'sync',
|
icon: 'sync',
|
||||||
|
|||||||
@ -83,6 +83,7 @@
|
|||||||
"label.action.create.template.from.vm": "Create Template from VM",
|
"label.action.create.template.from.vm": "Create Template from VM",
|
||||||
"label.action.create.template.from.volume": "Create Template from Volume",
|
"label.action.create.template.from.volume": "Create Template from Volume",
|
||||||
"label.action.create.template.processing": "Creating Template....",
|
"label.action.create.template.processing": "Creating Template....",
|
||||||
|
"label.action.create.snapshot.from.vmsnapshot": "Create Snapshot from VM Snapshot",
|
||||||
"label.action.create.vm": "Create VM",
|
"label.action.create.vm": "Create VM",
|
||||||
"label.action.create.vm.processing": "Creating VM....",
|
"label.action.create.vm.processing": "Creating VM....",
|
||||||
"label.action.create.volume": "Create Volume",
|
"label.action.create.volume": "Create Volume",
|
||||||
@ -2341,6 +2342,7 @@
|
|||||||
"message.action.cancel.maintenance.mode": "Please confirm that you want to cancel this maintenance.",
|
"message.action.cancel.maintenance.mode": "Please confirm that you want to cancel this maintenance.",
|
||||||
"message.action.change.service.warning.for.instance": "Your instance must be stopped before attempting to change its current service offering.",
|
"message.action.change.service.warning.for.instance": "Your instance must be stopped before attempting to change its current service offering.",
|
||||||
"message.action.change.service.warning.for.router": "Your router must be stopped before attempting to change its current service offering.",
|
"message.action.change.service.warning.for.router": "Your router must be stopped before attempting to change its current service offering.",
|
||||||
|
"message.action.create.snapshot.from.vmsnapshot": "Please confirm that you want to create snapshot from VM Snapshot",
|
||||||
"message.action.delete.backup.offering": "Please confirm that you want to delete this backup offering?",
|
"message.action.delete.backup.offering": "Please confirm that you want to delete this backup offering?",
|
||||||
"message.action.delete.cluster": "Please confirm that you want to delete this cluster.",
|
"message.action.delete.cluster": "Please confirm that you want to delete this cluster.",
|
||||||
"message.action.delete.disk.offering": "Please confirm that you want to delete this disk offering.",
|
"message.action.delete.disk.offering": "Please confirm that you want to delete this disk offering.",
|
||||||
@ -2595,6 +2597,8 @@
|
|||||||
"message.create.internallb.failed": "Failed to create Internal LB",
|
"message.create.internallb.failed": "Failed to create Internal LB",
|
||||||
"message.create.internallb.processing": "Creation of Internal LB is in progress",
|
"message.create.internallb.processing": "Creation of Internal LB is in progress",
|
||||||
"message.create.service.offering": "Service offering created",
|
"message.create.service.offering": "Service offering created",
|
||||||
|
"message.create.snapshot.from.vmsnapshot.failed": "Failed to create Snapshot from VM Snapshot",
|
||||||
|
"message.create.snapshot.from.vmsnapshot.progress": "Snapshot Creation in progress",
|
||||||
"message.create.template": "Are you sure you want to create template?",
|
"message.create.template": "Are you sure you want to create template?",
|
||||||
"message.create.template.vm": "Create VM from template <b id=\"p_name\"></b>",
|
"message.create.template.vm": "Create VM from template <b id=\"p_name\"></b>",
|
||||||
"message.create.template.volume": "Please specify the following information before creating a template of your disk volume: <b><span id=\"volume_name\"></span></b>. Creation of the template can range from several minutes to longer depending on the size of the volume.",
|
"message.create.template.volume": "Please specify the following information before creating a template of your disk volume: <b><span id=\"volume_name\"></span></b>. Creation of the template can range from several minutes to longer depending on the size of the volume.",
|
||||||
@ -3064,6 +3068,7 @@
|
|||||||
"message.success.create.keypair": "Successfully created SSH key pair",
|
"message.success.create.keypair": "Successfully created SSH key pair",
|
||||||
"message.success.create.kubernetes.cluter": "Successfully created Kubernetes cluster",
|
"message.success.create.kubernetes.cluter": "Successfully created Kubernetes cluster",
|
||||||
"message.success.create.l2.network": "Successfully created L2 network",
|
"message.success.create.l2.network": "Successfully created L2 network",
|
||||||
|
"message.success.create.snapshot.from.vmsnapshot": "Successfully created Snapshot from VM snapshot",
|
||||||
"message.success.create.volume": "Successfully created volume",
|
"message.success.create.volume": "Successfully created volume",
|
||||||
"message.success.delete": "Delete success",
|
"message.success.delete": "Delete success",
|
||||||
"message.success.delete.acl.rule": "Successfully removed ACL rule",
|
"message.success.delete.acl.rule": "Successfully removed ACL rule",
|
||||||
|
|||||||
151
ui/src/views/storage/CreateSnapshotFromVMSnapshot.vue
Normal file
151
ui/src/views/storage/CreateSnapshotFromVMSnapshot.vue
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
// 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>
|
||||||
|
<a-spin :spinning="loading">
|
||||||
|
<a-form class="form" :form="form" @submit="handleSubmit" layout="vertical">
|
||||||
|
<a-form-item :label="$t('label.name')">
|
||||||
|
<a-input
|
||||||
|
v-decorator="['name', {
|
||||||
|
rules: [{ required: true, message: $t('message.error.name') }]
|
||||||
|
}]"
|
||||||
|
:placeholder="$t('label.snapshot.name')"/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item :label="$t('label.volume')">
|
||||||
|
<a-select
|
||||||
|
v-decorator="['volumeid', {
|
||||||
|
initialValue: selectedVolumeId,
|
||||||
|
rules: [{ required: true, message: $t('message.error.select') }]}]"
|
||||||
|
:loading="loading"
|
||||||
|
@change="id => (volumes.filter(x => x.id === id))"
|
||||||
|
>
|
||||||
|
<a-select-option
|
||||||
|
v-for="(volume, index) in volumes"
|
||||||
|
:value="volume.id"
|
||||||
|
:key="index">
|
||||||
|
{{ volume.displaytext || volume.name }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
<div :span="24" class="action-button">
|
||||||
|
<a-button @click="closeModal">{{ $t('label.cancel') }}</a-button>
|
||||||
|
<a-button type="primary" @click="handleSubmit">{{ $t('label.ok') }}</a-button>
|
||||||
|
</div>
|
||||||
|
</a-form>
|
||||||
|
</a-spin>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { api } from '@/api'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'CreateSnapshotFromVMSnapshot',
|
||||||
|
props: {
|
||||||
|
resource: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
volumes: [],
|
||||||
|
selectedVolumeId: '',
|
||||||
|
loading: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeCreate () {
|
||||||
|
this.form = this.$form.createForm(this)
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.fetchData()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
fetchData () {
|
||||||
|
this.loading = true
|
||||||
|
api('listVolumes', {
|
||||||
|
virtualmachineid: this.resource.virtualmachineid,
|
||||||
|
listall: true
|
||||||
|
}).then(json => {
|
||||||
|
this.volumes = json.listvolumesresponse.volume || []
|
||||||
|
this.selectedVolumeId = this.volumes[0].id || ''
|
||||||
|
}).finally(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleSubmit (e) {
|
||||||
|
this.form.validateFields((err, values) => {
|
||||||
|
if (err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.loading = true
|
||||||
|
api('createSnapshotFromVMSnapshot', {
|
||||||
|
name: values.name,
|
||||||
|
volumeid: values.volumeid,
|
||||||
|
vmsnapshotid: this.resource.id
|
||||||
|
}).then(response => {
|
||||||
|
this.$pollJob({
|
||||||
|
jobId: response.createsnapshotfromvmsnapshotresponse.jobid,
|
||||||
|
successMessage: this.$t('message.success.create.snapshot.from.vmsnapshot'),
|
||||||
|
successMethod: () => {
|
||||||
|
this.$store.dispatch('AddAsyncJob', {
|
||||||
|
title: this.$t('message.success.create.snapshot.from.vmsnapshot'),
|
||||||
|
jobid: response.createsnapshotfromvmsnapshotresponse.jobid,
|
||||||
|
description: values.name,
|
||||||
|
status: 'progress'
|
||||||
|
})
|
||||||
|
this.$emit('refresh-data')
|
||||||
|
},
|
||||||
|
errorMessage: this.$t('message.create.snapshot.from.vmsnapshot.failed'),
|
||||||
|
errorMethod: () => {
|
||||||
|
this.$emit('refresh-data')
|
||||||
|
},
|
||||||
|
loadingMessage: this.$t('message.create.snapshot.from.vmsnapshot.progress'),
|
||||||
|
catchMessage: this.$t('error.fetching.async.job.result')
|
||||||
|
})
|
||||||
|
}).catch(error => {
|
||||||
|
this.$notifyError(error)
|
||||||
|
}).finally(() => {
|
||||||
|
this.loading = false
|
||||||
|
this.$emit('refresh-data')
|
||||||
|
this.closeModal()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
closeModal () {
|
||||||
|
this.$emit('close-action')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.form {
|
||||||
|
width: 80vw;
|
||||||
|
|
||||||
|
@media (min-width: 500px) {
|
||||||
|
width: 400px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-button {
|
||||||
|
text-align: right;
|
||||||
|
|
||||||
|
button {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
x
Reference in New Issue
Block a user