feat(lite/pool/VMs): ability to snapshot selected VMs (#7021)
This commit is contained in:
parent
d8530f9518
commit
a3a2fda157
@ -3,6 +3,7 @@
|
||||
## **next**
|
||||
|
||||
- Ability to migrate selected VMs to another host (PR [#7040](https://github.com/vatesfr/xen-orchestra/pull/7040))
|
||||
- Ability to snapshot selected VMs (PR [#7021](https://github.com/vatesfr/xen-orchestra/pull/7021))
|
||||
|
||||
## **0.1.3** (2023-09-01)
|
||||
|
||||
|
@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<MenuItem
|
||||
:busy="areSomeVmsSnapshoting"
|
||||
:disabled="isDisabled"
|
||||
:icon="faCamera"
|
||||
@click="handleSnapshot"
|
||||
>
|
||||
{{ $t("snapshot") }}
|
||||
</MenuItem>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import MenuItem from "@/components/menu/MenuItem.vue";
|
||||
import { useVmCollection } from "@/stores/xen-api/vm.store";
|
||||
import { VM_OPERATION } from "@/libs/xen-api/xen-api.enums";
|
||||
import type { XenApiVm } from "@/libs/xen-api/xen-api.types";
|
||||
import { useXenApiStore } from "@/stores/xen-api.store";
|
||||
import { faCamera } from "@fortawesome/free-solid-svg-icons";
|
||||
import { computed } from "vue";
|
||||
|
||||
const props = defineProps<{
|
||||
vmRefs: XenApiVm["$ref"][];
|
||||
}>();
|
||||
|
||||
const { getByOpaqueRef, isOperationPending } = useVmCollection();
|
||||
|
||||
const vms = computed(() =>
|
||||
props.vmRefs
|
||||
.map((vmRef) => getByOpaqueRef(vmRef))
|
||||
.filter((vm): vm is XenApiVm => vm !== undefined)
|
||||
);
|
||||
|
||||
const areSomeVmsSnapshoting = computed(() =>
|
||||
vms.value.some((vm) => isOperationPending(vm, VM_OPERATION.SNAPSHOT))
|
||||
);
|
||||
|
||||
const isDisabled = computed(() => vms.value.length === 0 || areSomeVmsSnapshoting.value);
|
||||
|
||||
const handleSnapshot = () => {
|
||||
const vmRefsToSnapshot = Object.fromEntries(
|
||||
vms.value.map((vm) => [
|
||||
vm.$ref,
|
||||
`${vm.name_label}_${new Date().toISOString()}`,
|
||||
])
|
||||
);
|
||||
return useXenApiStore().getXapi().vm.snapshot(vmRefsToSnapshot);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="postcss" scoped></style>
|
@ -20,9 +20,7 @@
|
||||
<MenuItem v-tooltip="$t('coming-soon')" :icon="faEdit">
|
||||
{{ $t("edit-config") }}
|
||||
</MenuItem>
|
||||
<MenuItem v-tooltip="$t('coming-soon')" :icon="faCamera">
|
||||
{{ $t("snapshot") }}
|
||||
</MenuItem>
|
||||
<VmActionSnapshotItem :vm-refs="selectedRefs" />
|
||||
<VmActionExportItem :vm-refs="selectedRefs" />
|
||||
<VmActionDeleteItem :vm-refs="selectedRefs" />
|
||||
</AppMenu>
|
||||
@ -37,11 +35,11 @@ import VmActionDeleteItem from "@/components/vm/VmActionItems/VmActionDeleteItem
|
||||
import VmActionExportItem from "@/components/vm/VmActionItems/VmActionExportItem.vue";
|
||||
import VmActionMigrateItem from "@/components/vm/VmActionItems/VmActionMigrateItem.vue";
|
||||
import VmActionPowerStateItems from "@/components/vm/VmActionItems/VmActionPowerStateItems.vue";
|
||||
import VmActionSnapshotItem from "@/components/vm/VmActionItems/VmActionSnapshotItem.vue";
|
||||
import { vTooltip } from "@/directives/tooltip.directive";
|
||||
import type { XenApiVm } from "@/libs/xen-api/xen-api.types";
|
||||
import { useUiStore } from "@/stores/ui.store";
|
||||
import {
|
||||
faCamera,
|
||||
faEdit,
|
||||
faEllipsis,
|
||||
faPowerOff,
|
||||
|
@ -108,7 +108,7 @@ export default class XenApi {
|
||||
|
||||
async loadRecords<
|
||||
Type extends ObjectType,
|
||||
XRecord extends ObjectTypeToRecord<Type>
|
||||
XRecord extends ObjectTypeToRecord<Type>,
|
||||
>(type: Type): Promise<XRecord[]> {
|
||||
this.emitEvent(`${type}.beforeLoad`);
|
||||
|
||||
@ -134,7 +134,7 @@ export default class XenApi {
|
||||
|
||||
addEventListener<
|
||||
Type extends ObjectType,
|
||||
XRecord extends ObjectTypeToRecord<Type>
|
||||
XRecord extends ObjectTypeToRecord<Type>,
|
||||
>(
|
||||
event: XenApiRecordAfterLoadEvent<Type>,
|
||||
callback: (records: XRecord[]) => void
|
||||
@ -152,7 +152,7 @@ export default class XenApi {
|
||||
|
||||
addEventListener<
|
||||
Type extends ObjectType,
|
||||
XRecord extends ObjectTypeToRecord<Type>
|
||||
XRecord extends ObjectTypeToRecord<Type>,
|
||||
>(
|
||||
event: XenApiRecordAddEvent<Type> | XenApiRecordModEvent<Type>,
|
||||
callback: (record: XRecord) => void
|
||||
@ -160,7 +160,7 @@ export default class XenApi {
|
||||
|
||||
addEventListener<
|
||||
Type extends ObjectType,
|
||||
XRecord extends ObjectTypeToRecord<Type>
|
||||
XRecord extends ObjectTypeToRecord<Type>,
|
||||
>(
|
||||
event: XenApiRecordDelEvent<Type>,
|
||||
callback: (opaqueRef: XRecord["$ref"]) => void
|
||||
@ -189,7 +189,7 @@ export default class XenApi {
|
||||
|
||||
removeEventListener<
|
||||
Type extends ObjectType,
|
||||
XRecord extends ObjectTypeToRecord<Type>
|
||||
XRecord extends ObjectTypeToRecord<Type>,
|
||||
>(
|
||||
event: XenApiRecordAfterLoadEvent<Type>,
|
||||
callback: (records: XRecord[]) => void
|
||||
@ -197,7 +197,7 @@ export default class XenApi {
|
||||
|
||||
removeEventListener<
|
||||
Type extends ObjectType,
|
||||
XRecord extends ObjectTypeToRecord<Type>
|
||||
XRecord extends ObjectTypeToRecord<Type>,
|
||||
>(
|
||||
event: XenApiRecordAddEvent<any> | XenApiRecordModEvent<any>,
|
||||
callback: (record: XRecord) => void
|
||||
@ -205,7 +205,7 @@ export default class XenApi {
|
||||
|
||||
removeEventListener<
|
||||
Type extends ObjectType,
|
||||
XRecord extends ObjectTypeToRecord<Type>
|
||||
XRecord extends ObjectTypeToRecord<Type>,
|
||||
>(
|
||||
event: XenApiRecordDelEvent<Type>,
|
||||
callback: (opaqueRef: XRecord["$ref"]) => void
|
||||
@ -296,7 +296,7 @@ export default class XenApi {
|
||||
XenApiVm["$ref"],
|
||||
XenApiVm["power_state"]
|
||||
>;
|
||||
type VmRefsToClone = Record<XenApiVm["$ref"], /* Cloned VM name */ string>;
|
||||
type VmRefsWithNameLabel = Record<XenApiVm["$ref"], string>;
|
||||
|
||||
return {
|
||||
delete: (vmRefs: VmRefs) =>
|
||||
@ -351,7 +351,7 @@ export default class XenApi {
|
||||
)
|
||||
);
|
||||
},
|
||||
clone: (vmRefsToClone: VmRefsToClone) => {
|
||||
clone: (vmRefsToClone: VmRefsWithNameLabel) => {
|
||||
const vmRefs = Object.keys(vmRefsToClone) as XenApiVm["$ref"][];
|
||||
|
||||
return Promise.all(
|
||||
@ -371,6 +371,15 @@ export default class XenApi {
|
||||
)
|
||||
);
|
||||
},
|
||||
snapshot: (vmRefsToSnapshot: VmRefsWithNameLabel) => {
|
||||
const vmRefs = Object.keys(vmRefsToSnapshot) as XenApiVm["$ref"][];
|
||||
|
||||
return Promise.all(
|
||||
vmRefs.map((vmRef) =>
|
||||
this.call("VM.snapshot", [vmRef, vmRefsToSnapshot[vmRef]])
|
||||
)
|
||||
);
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user