feat(lite/pool/VMs): ability to copy selected VMs (#6847)

This commit is contained in:
Thierry Goettelmann
2023-06-09 14:59:39 +02:00
committed by GitHub
parent 55b2e0292f
commit 27b5737f65
8 changed files with 75 additions and 8 deletions

View File

@@ -16,6 +16,7 @@
- Display an error message if the data cannot be fetched (PR [#6525](https://github.com/vatesfr/xen-orchestra/pull/6525))
- Add "Under Construction" views (PR [#6673](https://github.com/vatesfr/xen-orchestra/pull/6673))
- Ability to change the state of selected VMs from the pool's list of VMs (PR [#6782](https://github.com/vatesfr/xen-orchestra/pull/6782))
- Ability to copy selected VMs from the pool's list of VMs (PR [#6847](https://github.com/vatesfr/xen-orchestra/pull/6847))
## **0.1.0**

View File

@@ -0,0 +1,56 @@
<template>
<MenuItem
v-tooltip="!areAllSelectedVmsHalted && $t('selected-vms-in-execution')"
:busy="areSomeSelectedVmsCloning"
:disabled="!areAllSelectedVmsHalted"
:icon="faCopy"
@click="handleCopy"
>
{{ $t("copy") }}
</MenuItem>
</template>
<script lang="ts" setup>
import MenuItem from "@/components/menu/MenuItem.vue";
import { vTooltip } from "@/directives/tooltip.directive";
import { isOperationsPending } from "@/libs/utils";
import { POWER_STATE, VM_OPERATION, type XenApiVm } from "@/libs/xen-api";
import { useVmStore } from "@/stores/vm.store";
import { useXenApiStore } from "@/stores/xen-api.store";
import { faCopy } from "@fortawesome/free-solid-svg-icons";
import { computed } from "vue";
const props = defineProps<{
selectedRefs: string[];
}>();
const { getByOpaqueRef } = useVmStore().subscribe();
const selectedVms = computed(() =>
props.selectedRefs
.map((vmRef) => getByOpaqueRef(vmRef))
.filter((vm): vm is XenApiVm => vm !== undefined)
);
const areAllSelectedVmsHalted = computed(() =>
selectedVms.value.every(
(selectedVm) => selectedVm.power_state === POWER_STATE.HALTED
)
);
const areSomeSelectedVmsCloning = computed(() =>
selectedVms.value.some((vm) => isOperationsPending(vm, VM_OPERATION.CLONE))
);
const handleCopy = async () => {
const xapiStore = useXenApiStore();
const vmRefsToClone = Object.fromEntries(
selectedVms.value.map((vm) => [vm.$ref, `${vm.name_label} (COPY)`])
);
await xapiStore.getXapi().vm.clone(vmRefsToClone);
};
</script>
<style lang="postcss" scoped></style>

View File

@@ -9,7 +9,7 @@
<UiIcon :icon="faAngleDown" />
</UiButton>
</template>
<VmsPowerActionsMenu :vm-refs="[vm.$ref]" />
<VmActionPowerStateItems :vm-refs="[vm.$ref]" />
</AppMenu>
</template>
</TitleBar>
@@ -21,7 +21,7 @@ import TitleBar from "@/components/TitleBar.vue";
import UiIcon from "@/components/ui/icon/UiIcon.vue";
import UiButton from "@/components/ui/UiButton.vue";
import { useVmStore } from "@/stores/vm.store";
import VmsPowerActionsMenu from "@/components/vm/VmsPowerActionsMenu.vue";
import VmActionPowerStateItems from "@/components/vm/VmActionItems/VmActionPowerStateItems.vue";
import {
faAngleDown,
faDisplay,

View File

@@ -12,15 +12,13 @@
<MenuItem :icon="faPowerOff">
{{ $t("change-power-state") }}
<template #submenu>
<VmsPowerActionsMenu :vm-refs="selectedRefs" />
<VmActionPowerStateItems :vm-refs="selectedRefs" />
</template>
</MenuItem>
<MenuItem v-tooltip="$t('coming-soon')" :icon="faRoute">
{{ $t("migrate") }}
</MenuItem>
<MenuItem v-tooltip="$t('coming-soon')" :icon="faCopy">
{{ $t("copy") }}
</MenuItem>
<VmActionCopyItem :selected-refs="selectedRefs" />
<MenuItem v-tooltip="$t('coming-soon')" :icon="faEdit">
{{ $t("edit-config") }}
</MenuItem>
@@ -60,13 +58,13 @@
import AppMenu from "@/components/menu/AppMenu.vue";
import MenuItem from "@/components/menu/MenuItem.vue";
import UiButton from "@/components/ui/UiButton.vue";
import VmActionCopyItem from "@/components/vm/VmActionItems/VmActionCopyItem.vue";
import { useUiStore } from "@/stores/ui.store";
import VmsPowerActionsMenu from "@/components/vm/VmsPowerActionsMenu.vue";
import VmActionPowerStateItems from "@/components/vm/VmActionItems/VmActionPowerStateItems.vue";
import { vTooltip } from "@/directives/tooltip.directive";
import {
faCamera,
faCode,
faCopy,
faDisplay,
faEdit,
faEllipsis,

View File

@@ -333,6 +333,7 @@ export default class XenApi {
XenApiVm["$ref"],
XenApiVm["power_state"]
>;
type VmRefsToClone = Record<XenApiVm["$ref"], /* Cloned VM name */ string>;
return {
start: (vmRefs: VmRefs) =>
@@ -383,6 +384,15 @@ export default class XenApi {
)
);
},
clone: (vmRefsToClone: VmRefsToClone) => {
const vmRefs = Object.keys(vmRefsToClone);
return Promise.all(
vmRefs.map((vmRef) =>
this._call("VM.clone", [vmRef, vmRefsToClone[vmRef]])
)
);
},
};
}
}

View File

@@ -99,6 +99,7 @@
},
"resume": "Resume",
"save": "Save",
"selected-vms-in-execution": "Some selected VMs are running",
"send-us-feedback": "Send us feedback",
"settings": "Settings",
"shutdown": "Shutdown",

View File

@@ -99,6 +99,7 @@
},
"resume": "Reprendre",
"save": "Enregistrer",
"selected-vms-in-execution": "Certaines VMs sélectionnées sont en cours d'exécution",
"send-us-feedback": "Envoyez-nous vos commentaires",
"settings": "Paramètres",
"shutdown": "Arrêter",