mirror of
https://github.com/vatesfr/xen-orchestra.git
synced 2026-09-10 22:14:48 -05:00
feat(xo6): add smart reboot host button (#10177)
* feat(xo6): reset smart reboot branch ok * Last returns * Remove route map * rebase ok * add check onConfirm smart reboot
This commit is contained in:
@@ -129,6 +129,11 @@ const textMappingsByObject: TextMappingByObject = {
|
||||
message: t('modal:host-force-reboot-message'),
|
||||
action: t('action:force-reboot-host'),
|
||||
},
|
||||
'smart-reboot': {
|
||||
title: t('modal:confirm-host-smart-reboot?', { host: hostName }),
|
||||
message: t('modal:host-smart-reboot-message'),
|
||||
action: t('action:smart-reboot-host'),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -135,6 +135,8 @@
|
||||
"action:sidebar-lock": "Lock sidebar open",
|
||||
"action:sidebar-open": "Open sidebar",
|
||||
"action:sidebar-unlock": "Unlock sidebar",
|
||||
"action:smart-reboot": "Smart reboot",
|
||||
"action:smart-reboot-host": "@:action:smart-reboot host",
|
||||
"action:sort-ascending": "Sort ascending",
|
||||
"action:sort-by": "Sort by",
|
||||
"action:sort-descending": "Sort descending",
|
||||
@@ -517,6 +519,12 @@
|
||||
"job:host-shutdown:bad-power-state": "Host already halted",
|
||||
"job:host-shutdown:in-progress": "Host shut down in progress…",
|
||||
"job:host-shutdown:missing-host": "No host to shut down",
|
||||
"job:host-smart-reboot:bad-power-state": "Host is not running",
|
||||
"job:host-smart-reboot:in-progress": "Host smart reboot in progress…",
|
||||
"job:host-smart-reboot:missing-host": "No host to smart reboot",
|
||||
"job:host-smart-reboot:vm-clean-shutdown-in-progress": "VMs clean shutting down in progress…",
|
||||
"job:host-smart-reboot:vm-hard-shutdown-in-progress": "VMs hard shutting down in progress…",
|
||||
"job:host-smart-reboot:vm-suspend-in-progress": "VMs suspend in progress…",
|
||||
"job:host-start:bad-power-state": "Host already started",
|
||||
"job:host-start:bad-power-state-not-halted": "Host not halted",
|
||||
"job:host-start:in-progress": "Host start in progress…",
|
||||
@@ -676,6 +684,7 @@
|
||||
"modal:confirm-host-forget?": "Are you sure you want to forget {host}?",
|
||||
"modal:confirm-host-reboot?": "Are you sure you want to reboot {host}?",
|
||||
"modal:confirm-host-shutdown?": "Are you sure you want to shut down {host}?",
|
||||
"modal:confirm-host-smart-reboot?": "Are you sure you want to smart reboot {host}?",
|
||||
"modal:confirm-host-start?": "Are you sure you want to start {host}?",
|
||||
"modal:confirm-vm-force-reboot": "Confirm VM force reboot",
|
||||
"modal:confirm-vm-force-shutdown": "Confirm VM force shutdown",
|
||||
@@ -688,6 +697,7 @@
|
||||
"modal:host-forget-message": "This will permanently remove the host from the pool database. Only do this if the host is physically gone or unrecoverable - if it can come back online, use Detach instead. This action cannot be undone.",
|
||||
"modal:host-reboot-message": "The host is about to reboot. Its running VMs will be migrated to other hosts and won't be moved back to it automatically afterwards.",
|
||||
"modal:host-shutdown-message": "This will power off the host. Any VMs still running on it will be shut down immediately unless you've migrated them first.",
|
||||
"modal:host-smart-reboot-message": "All running VMs on this host will be suspended, the host will reboot, then the VMs will automatically resume. This causes temporary downtime. If Xen Orchestra itself runs on this host, VMs may not resume automatically.",
|
||||
"modal:pool-disconnect-message": "The pool will no longer be manageable from XO. You can reconnect it later.",
|
||||
"modal:vm-force-reboot-message": "This will immediately reboot the virtual machine without a clean shutdown. Data loss may occur and ongoing processes will be interrupted.",
|
||||
"modal:vm-force-shutdown-message": "This will immediately power off the virtual machine without a clean shutdown. Data loss may occur and ongoing processes will be interrupted.",
|
||||
@@ -845,6 +855,9 @@
|
||||
"operation:start-on-host": "Starting on host",
|
||||
"operation:suspend": "Suspending",
|
||||
"operation:unpause": "Resuming",
|
||||
"operation:vm-clean-shutdown": "VMs clean shutting down",
|
||||
"operation:vm-hard-shutdown": "VMs hard shutting down",
|
||||
"operation:vm-suspend": "VMs suspending",
|
||||
"options": "Options",
|
||||
"or": "Or",
|
||||
"os-kernel": "OS kernel",
|
||||
@@ -883,8 +896,8 @@
|
||||
"pool-connection-success": "You have successfully connected to the pool. You can now find it in your treeview and start managing your hosts and VMs.",
|
||||
"pool-cpu-usage": "Pool CPU Usage",
|
||||
"pool-disconnect-info": "You will no longer be able to manage this pool from XO. You can reconnect it later.",
|
||||
"pool-forget-confirm-title": "You are about to remove {name} host",
|
||||
"pool-forget-confirm-info": "This will permanently remove this host from XO. To reconnect, you will need to add it again.",
|
||||
"pool-forget-confirm-title": "You are about to remove {name} host",
|
||||
"pool-management": "Pool management",
|
||||
"pool-ram-usage": "Pool RAM Usage",
|
||||
"pool:status:connected": "@:status:connected",
|
||||
|
||||
@@ -135,6 +135,8 @@
|
||||
"action:sidebar-lock": "Verrouiller la barre latérale",
|
||||
"action:sidebar-open": "Ouvrir la barre latérale",
|
||||
"action:sidebar-unlock": "Déverrouiller la barre latérale",
|
||||
"action:smart-reboot": "Redémarrage optimisé",
|
||||
"action:smart-reboot-host": "@:action:smart-reboot de l'hôte",
|
||||
"action:sort-ascending": "Trier par ordre croissant",
|
||||
"action:sort-by": "Trier par",
|
||||
"action:sort-descending": "Trier par ordre décroissant",
|
||||
@@ -517,6 +519,12 @@
|
||||
"job:host-shutdown:bad-power-state": "Hôte déjà arrêté",
|
||||
"job:host-shutdown:in-progress": "Arrêt de l'hôte en cours…",
|
||||
"job:host-shutdown:missing-host": "Aucun hôte à arrêter",
|
||||
"job:host-smart-reboot:bad-power-state": "L'hôte n'est pas démarré",
|
||||
"job:host-smart-reboot:in-progress": "Redémarrage optimisé de l'hôte en cours…",
|
||||
"job:host-smart-reboot:missing-host": "Aucun hôte pour le redémarrage optimisé",
|
||||
"job:host-smart-reboot:vm-clean-shutdown-in-progress": "Arrêt des VMs en cours…",
|
||||
"job:host-smart-reboot:vm-hard-shutdown-in-progress": "Arrêt forcé des VMs en cours…",
|
||||
"job:host-smart-reboot:vm-suspend-in-progress": "Suspension des VMs en cours…",
|
||||
"job:host-start:bad-power-state": "Hôte déjà démarré",
|
||||
"job:host-start:bad-power-state-not-halted": "Hôte non arrêté",
|
||||
"job:host-start:in-progress": "Démarrage de l'hôte en cours…",
|
||||
@@ -676,6 +684,7 @@
|
||||
"modal:confirm-host-forget?": "Êtes-vous sûr de vouloir oublier {host} ?",
|
||||
"modal:confirm-host-reboot?": "Êtes-vous sûr de vouloir redémarrer {host} ?",
|
||||
"modal:confirm-host-shutdown?": "Êtes-vous sûr de vouloir arrêter {host} ?",
|
||||
"modal:confirm-host-smart-reboot?": "Êtes-vous sûr de vouloir effectuer un redémarrage optimisé de {host} ?",
|
||||
"modal:confirm-host-start?": "Êtes-vous sûr de vouloir démarrer {host} ?",
|
||||
"modal:confirm-vm-force-reboot": "Confirmer le redémarrage forcé de la VM",
|
||||
"modal:confirm-vm-force-shutdown": "Confirmer l'arrêt forcé de la VM",
|
||||
@@ -688,6 +697,7 @@
|
||||
"modal:host-forget-message": "Cela supprimera définitivement l'hôte de la base de données du pool. Ne faites cela que si l'hôte est physiquement absent ou irrécupérable - s'il peut revenir en ligne, utilisez à la place Détacher. Cette action ne peut pas être annulée.",
|
||||
"modal:host-reboot-message": "L'hôte va redémarrer. Ses VMs en cours d'exécution seront migrées vers d'autres hôtes et ne reviendront pas automatiquement dessus après l'opération.",
|
||||
"modal:host-shutdown-message": "Cela éteindra l'hôte. Toute VM encore en cours d’exécution sera immédiatement arrêtée, à moins que vous ne l'ayez migrée au préalable.",
|
||||
"modal:host-smart-reboot-message": "Toutes les VMs en cours d'exécution sur cet hôte seront suspendues, l'hôte redémarrera, puis les VMs reprendront automatiquement. Cela entraîne une interruption temporaire. Si Xen Orchestra lui-même s'exécute sur cet hôte, les VMs pourraient ne pas reprendre automatiquement.",
|
||||
"modal:pool-disconnect-message": "Le pool ne pourra plus être géré depuis XO. Vous pourrez le reconnecter ultérieurement.",
|
||||
"modal:vm-force-reboot-message": "Cela redémarrera immédiatement la VM sans arrêt propre. Des pertes de données peuvent survenir et les processus en cours seront interrompus.",
|
||||
"modal:vm-force-shutdown-message": "Cela éteindra immédiatement la VM sans arrêt propre. Des pertes de données peuvent survenir et les processus en cours seront interrompus.",
|
||||
@@ -845,6 +855,9 @@
|
||||
"operation:start-on-host": "Démarrage sur l'hôte",
|
||||
"operation:suspend": "Suspension",
|
||||
"operation:unpause": "Reprise",
|
||||
"operation:vm-clean-shutdown": "Arrêt des VMs",
|
||||
"operation:vm-hard-shutdown": "Arrêt forcé des VMs",
|
||||
"operation:vm-suspend": "Suspension des VMs",
|
||||
"options": "Options",
|
||||
"or": "Ou",
|
||||
"os-kernel": "Noyau de l'OS",
|
||||
@@ -883,8 +896,8 @@
|
||||
"pool-connection-success": "Vous êtes connecté au pool. Vous pouvez désormais le retrouver dans votre arborescence et commencer à gérer vos hôtes et vos machines virtuelles.",
|
||||
"pool-cpu-usage": "Utilisation CPU du Pool",
|
||||
"pool-disconnect-info": "Vous ne pourrez plus gérer ce pool depuis XO. Vous pourrez le reconnecter ultérieurement.",
|
||||
"pool-forget-confirm-title": "Vous êtes sur le point de supprimer l'hôte {name}",
|
||||
"pool-forget-confirm-info": "Cela supprimera définitivement cet hôte de XO. Pour vous reconnecter, vous devrez l'ajouter à nouveau.",
|
||||
"pool-forget-confirm-title": "Vous êtes sur le point de supprimer l'hôte {name}",
|
||||
"pool-management": "Gestion du Pool",
|
||||
"pool-ram-usage": "Utilisation RAM du Pool",
|
||||
"pool:status:connected": "@:status:connected",
|
||||
|
||||
@@ -10,6 +10,7 @@ export type HostActions =
|
||||
| 'disable-and-evacuate-vms'
|
||||
| 'reboot'
|
||||
| 'force-reboot'
|
||||
| 'smart-reboot'
|
||||
|
||||
export type VmBlockedOperations =
|
||||
| 'clean_shutdown'
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<template v-if="isHostRunning">
|
||||
<HostRebootButton :host />
|
||||
<HostForceRebootButton :host />
|
||||
<HostSmartRebootButton :host />
|
||||
<HostShutdownButton :host />
|
||||
</template>
|
||||
<HostStartButton v-else :host />
|
||||
@@ -10,6 +11,7 @@
|
||||
<script lang="ts" setup>
|
||||
import HostForceRebootButton from '@/modules/host/components/actions/reboot/HostForceRebootButton.vue'
|
||||
import HostRebootButton from '@/modules/host/components/actions/reboot/HostRebootButton.vue'
|
||||
import HostSmartRebootButton from '@/modules/host/components/actions/reboot/HostSmartRebootButton.vue'
|
||||
import HostShutdownButton from '@/modules/host/components/actions/shutdown/HostShutdownButton.vue'
|
||||
import HostStartButton from '@/modules/host/components/actions/start/HostStartButton.vue'
|
||||
import type { FrontXoHost } from '@/modules/host/remote-resources/use-xo-host-collection.ts'
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<MenuItem
|
||||
v-tooltip="!canSmartRebootHost && smartRebootHostErrorMessage"
|
||||
:disabled="!canSmartRebootHost"
|
||||
icon="action:smart-reboot"
|
||||
:busy="isSmartRebootingHost"
|
||||
@click="smartRebootHost()"
|
||||
>
|
||||
{{ t('action:smart-reboot') }}
|
||||
</MenuItem>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useXoHostSmartRebootJob } from '@/modules/host/jobs/xo-host-smart-reboot.job.ts'
|
||||
import type { FrontXoHost } from '@/modules/host/remote-resources/use-xo-host-collection.ts'
|
||||
import MenuItem from '@core/components/menu/MenuItem.vue'
|
||||
import { useActionModal } from '@core/composables/modals/use-action-modal.ts'
|
||||
import { vTooltip } from '@core/directives/tooltip.directive.ts'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { host } = defineProps<{
|
||||
host: FrontXoHost
|
||||
}>()
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const {
|
||||
run,
|
||||
canRun: canSmartRebootHost,
|
||||
isRunning: isSmartRebootingHost,
|
||||
errorMessage: smartRebootHostErrorMessage,
|
||||
} = useXoHostSmartRebootJob(() => host)
|
||||
|
||||
const { open: openActionModal } = useActionModal()
|
||||
|
||||
async function smartRebootHost() {
|
||||
const { event } = await openActionModal({
|
||||
props: {
|
||||
accent: 'info',
|
||||
action: 'smart-reboot',
|
||||
object: 'host',
|
||||
hostName: host.name_label,
|
||||
icon: 'status:info-picto',
|
||||
},
|
||||
})
|
||||
|
||||
if (event !== 'onConfirm') {
|
||||
return
|
||||
}
|
||||
|
||||
await run()
|
||||
}
|
||||
</script>
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { FrontXoHost } from '@/modules/host/remote-resources/use-xo-host-collection.ts'
|
||||
import { getHostPendingStateOperation } from '@/modules/host/utils/xo-host.util.ts'
|
||||
import { getHostPendingStateOperation, getHostSmartRebootVmOperation } from '@/modules/host/utils/xo-host.util.ts'
|
||||
import { useXoVmCollection } from '@/modules/vm/remote-resources/use-xo-vm-collection.ts'
|
||||
import type { IconName } from '@core/icons'
|
||||
import useRelativeTime from '@core/composables/relative-time.composable'
|
||||
import { createMapper, useMapper } from '@core/packages/mapper'
|
||||
@@ -14,6 +15,8 @@ export function useXoHostUtils(rawHost: MaybeRefOrGetter<FrontXoHost>) {
|
||||
|
||||
const host = toComputed(rawHost)
|
||||
|
||||
const { vmsByHost } = useXoVmCollection()
|
||||
|
||||
const getPowerState = createMapper<HOST_POWER_STATE, { text: string; icon: IconName | undefined }>(
|
||||
{
|
||||
[HOST_POWER_STATE.RUNNING]: { text: t('host:status:running'), icon: 'status:running-circle' },
|
||||
@@ -29,7 +32,11 @@ export function useXoHostUtils(rawHost: MaybeRefOrGetter<FrontXoHost>) {
|
||||
return useRelativeTime(date)
|
||||
}
|
||||
|
||||
const pendingStateOperation = computed(() => getHostPendingStateOperation(host.value))
|
||||
const pendingStateOperation = computed(
|
||||
() =>
|
||||
getHostPendingStateOperation(host.value) ??
|
||||
getHostSmartRebootVmOperation(host.value, vmsByHost.value.get(host.value.id) ?? [])
|
||||
)
|
||||
|
||||
const isChangingState = computed(() => pendingStateOperation.value !== undefined)
|
||||
|
||||
@@ -41,6 +48,9 @@ export function useXoHostUtils(rawHost: MaybeRefOrGetter<FrontXoHost>) {
|
||||
reboot: t('operation:clean-reboot'),
|
||||
evacuate: t('operation:evacuate'),
|
||||
enable: t('operation:enable'),
|
||||
suspend: t('operation:vm-suspend'),
|
||||
clean_shutdown: t('operation:vm-clean-shutdown'),
|
||||
hard_shutdown: t('operation:vm-hard-shutdown'),
|
||||
unknown: '',
|
||||
},
|
||||
'unknown'
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import { xoHostArg } from '@/modules/host/jobs/xo-host-args.ts'
|
||||
import type { FrontXoHost } from '@/modules/host/remote-resources/use-xo-host-collection.ts'
|
||||
import { isHostOperationPending } from '@/modules/host/utils/xo-host.util.ts'
|
||||
import type { FrontXoTask } from '@/modules/task/remote-resources/use-xo-task-collection.ts'
|
||||
import { useXoVmCollection } from '@/modules/vm/remote-resources/use-xo-vm-collection.ts'
|
||||
import { areVmsOperationPending } from '@/modules/vm/utils/xo-vm.util.ts'
|
||||
import { useXoTaskUtils } from '@/shared/composables/xo-task-utils.composable.ts'
|
||||
import { fetchPost } from '@/shared/utils/fetch.util.ts'
|
||||
import { defineJob, JobError, JobRunningError } from '@core/packages/job'
|
||||
import { HOST_ALLOWED_OPERATIONS, HOST_POWER_STATE, VM_OPERATIONS } from '@vates/types'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
export const useXoHostSmartRebootJob = defineJob('host.smart-reboot', [xoHostArg], () => {
|
||||
const { t } = useI18n()
|
||||
const { monitorTask } = useXoTaskUtils()
|
||||
const { vmsByHost } = useXoVmCollection()
|
||||
|
||||
return {
|
||||
async run(host: FrontXoHost) {
|
||||
const { taskId } = await fetchPost<{ taskId: FrontXoTask['id'] }>(`hosts/${host.id}/actions/smart_reboot`)
|
||||
await monitorTask(taskId)
|
||||
},
|
||||
|
||||
validate: (isRunning, host: FrontXoHost | undefined) => {
|
||||
if (!host) {
|
||||
throw new JobError(t('job:host-smart-reboot:missing-host'))
|
||||
}
|
||||
|
||||
const residentVms = vmsByHost.value.get(host.id) ?? []
|
||||
|
||||
if (isRunning || isHostOperationPending(host, HOST_ALLOWED_OPERATIONS.REBOOT)) {
|
||||
throw new JobRunningError(t('job:host-smart-reboot:in-progress'))
|
||||
}
|
||||
|
||||
if (areVmsOperationPending(residentVms, VM_OPERATIONS.SUSPEND)) {
|
||||
throw new JobRunningError(t('job:host-smart-reboot:vm-suspend-in-progress'))
|
||||
}
|
||||
|
||||
if (areVmsOperationPending(residentVms, VM_OPERATIONS.CLEAN_SHUTDOWN)) {
|
||||
throw new JobRunningError(t('job:host-smart-reboot:vm-clean-shutdown-in-progress'))
|
||||
}
|
||||
|
||||
if (areVmsOperationPending(residentVms, VM_OPERATIONS.HARD_SHUTDOWN)) {
|
||||
throw new JobRunningError(t('job:host-smart-reboot:vm-hard-shutdown-in-progress'))
|
||||
}
|
||||
|
||||
if (host.power_state !== HOST_POWER_STATE.RUNNING) {
|
||||
throw new JobError(t('job:host-smart-reboot:bad-power-state'))
|
||||
}
|
||||
},
|
||||
}
|
||||
})
|
||||
@@ -1,6 +1,8 @@
|
||||
import type { FrontXoHost } from '@/modules/host/remote-resources/use-xo-host-collection.ts'
|
||||
import type { FrontXoVm } from '@/modules/vm/remote-resources/use-xo-vm-collection.ts'
|
||||
import { getVmsPendingOperation } from '@/modules/vm/utils/xo-vm.util.ts'
|
||||
import type { VtsLinkCellProps } from '@core/components/table/cells/VtsLinkCell.vue'
|
||||
import { HOST_ALLOWED_OPERATIONS, HOST_POWER_STATE } from '@vates/types'
|
||||
import { HOST_ALLOWED_OPERATIONS, HOST_POWER_STATE, VM_OPERATIONS } from '@vates/types'
|
||||
import { castArray } from 'lodash-es'
|
||||
|
||||
const RUNNING_CHANGING_STATE_OPERATIONS: Partial<HOST_ALLOWED_OPERATIONS>[] = [
|
||||
@@ -12,6 +14,12 @@ const RUNNING_CHANGING_STATE_OPERATIONS: Partial<HOST_ALLOWED_OPERATIONS>[] = [
|
||||
|
||||
const NOT_RUNNING_CHANGING_STATE_OPERATIONS: Partial<HOST_ALLOWED_OPERATIONS>[] = [HOST_ALLOWED_OPERATIONS.POWER_ON]
|
||||
|
||||
const SMART_REBOOT_SUSPENDING_VM_OPERATIONS: Partial<VM_OPERATIONS>[] = [
|
||||
VM_OPERATIONS.SUSPEND,
|
||||
VM_OPERATIONS.CLEAN_SHUTDOWN,
|
||||
VM_OPERATIONS.HARD_SHUTDOWN,
|
||||
]
|
||||
|
||||
export function isHostOperationPending(
|
||||
host: FrontXoHost,
|
||||
operations: HOST_ALLOWED_OPERATIONS[] | HOST_ALLOWED_OPERATIONS
|
||||
@@ -39,6 +47,13 @@ export function getHostPendingStateOperation(host: FrontXoHost) {
|
||||
)
|
||||
}
|
||||
|
||||
export function getHostSmartRebootVmOperation(host: FrontXoHost, residentVms: FrontXoVm[]) {
|
||||
if (host.enabled) {
|
||||
return undefined
|
||||
}
|
||||
return getVmsPendingOperation(residentVms, SMART_REBOOT_SUSPENDING_VM_OPERATIONS)
|
||||
}
|
||||
|
||||
export function getHostInfo(host: FrontXoHost | undefined): VtsLinkCellProps & { label: string } {
|
||||
return host ? { label: host.name_label, to: `/host/${host.id}/dashboard` } : { label: '' }
|
||||
}
|
||||
|
||||
@@ -33,6 +33,17 @@ export function areVmsOperationPending(vms: FrontXoVm[], operations: VM_OPERATIO
|
||||
return vms.some(vm => isVmOperationPending(vm, operations))
|
||||
}
|
||||
|
||||
export function getVmsPendingOperation(vms: FrontXoVm[], operations: VM_OPERATIONS[] | VM_OPERATIONS) {
|
||||
for (const vm of vms) {
|
||||
const currentOperations = Object.values(vm.current_operations)
|
||||
const currentOperation = castArray(operations).find(operation => currentOperations.includes(operation))
|
||||
|
||||
if (currentOperation !== undefined) {
|
||||
return currentOperation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function areAllVmsHavingPowerState(vms: FrontXoVm[], powerStates: VM_POWER_STATE[]) {
|
||||
return vms.every(vm => powerStates.includes(vm.power_state))
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
- [VIF] Add VIF name in header on VIF detail page (PR [#10252](https://github.com/vatesfr/xen-orchestra/pull/10252))
|
||||
- [XO6/SR] Add dedicated Storage Repository page with general information, space usage, PBD details, custom fields (PR [#10100](https://github.com/vatesfr/xen-orchestra/pull/10100))
|
||||
- [XO5/Backups] Add `Synchronize snapshots` checkbox to backup jobs to get consistent restore points (PR [#10136](https://github.com/vatesfr/xen-orchestra/pull/10136))
|
||||
- [XO6/Host] Add possibility to smart reboot a host (PR [#10177](https://github.com/vatesfr/xen-orchestra/pull/10177))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
|
||||
Reference in New Issue
Block a user