From 6b21f08ab0614f00d834e4f3b0ac6caac0026d30 Mon Sep 17 00:00:00 2001
From: OlivierFL <66562640+OlivierFL@users.noreply.github.com>
Date: Thu, 26 Sep 2024 17:10:51 +0200
Subject: [PATCH 1/2] feat(xo-6/dashboard): add VMs protection data (#8007)
---
.../src/components/site/dashboard/Backups.vue | 41 ++++++++++++++++---
@xen-orchestra/web/src/locales/en.json | 6 +++
@xen-orchestra/web/src/locales/fr.json | 6 +++
.../web/src/types/xo/dashboard.type.ts | 5 +++
CHANGELOG.unreleased.md | 2 +
5 files changed, 55 insertions(+), 5 deletions(-)
diff --git a/@xen-orchestra/web/src/components/site/dashboard/Backups.vue b/@xen-orchestra/web/src/components/site/dashboard/Backups.vue
index be1add3ebef..8b58ad50ba7 100644
--- a/@xen-orchestra/web/src/components/site/dashboard/Backups.vue
+++ b/@xen-orchestra/web/src/components/site/dashboard/Backups.vue
@@ -2,8 +2,13 @@
{{ $t('backups') }}
-
-
+
+
+
+
+
+
+
@@ -12,12 +17,14 @@
import { useDashboardStore } from '@/stores/xo-rest-api/dashboard.store'
import CardTitle from '@core/components/card/CardTitle.vue'
import CardNumbers from '@core/components/CardNumbers.vue'
+import Divider from '@core/components/divider/Divider.vue'
import DonutChartWithLegend, {
type DonutChartWithLegendProps,
} from '@core/components/donut-chart-with-legend/DonutChartWithLegend.vue'
import LoadingHero from '@core/components/state-hero/LoadingHero.vue'
+import NoDataHero from '@core/components/state-hero/NoDataHero.vue'
import UiCard from '@core/components/UiCard.vue'
-import { faCircleInfo, faServer } from '@fortawesome/free-solid-svg-icons'
+import { faCircleInfo } from '@fortawesome/free-solid-svg-icons'
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
@@ -25,13 +32,13 @@ const { record, isReady } = useDashboardStore().subscribe()
const { t } = useI18n()
-const title = computed(() => ({
+const jobsTitle = computed(() => ({
label: t('backups.jobs'),
iconTooltip: t('backups.jobs.based-on-last-three'),
icon: faCircleInfo,
}))
-const segments = computed(() => [
+const jobsSegments = computed(() => [
{
label: t('backups.jobs.running-good'),
value: record.value?.backups?.jobs.successful ?? 0,
@@ -53,4 +60,28 @@ const segments = computed(() => [
color: 'disabled',
},
])
+
+const vmsProtectionTitle = computed(() => ({
+ label: t('backups.vms-protection'),
+ iconTooltip: t('backups.vms-protection.tooltip'),
+ icon: faCircleInfo,
+}))
+
+const vmsProtectionSegments = computed(() => [
+ {
+ label: t('backups.vms-protection.protected'),
+ value: record.value?.backups?.vmsProtection.protected ?? 0,
+ color: 'success',
+ },
+ {
+ label: t('backups.vms-protection.unprotected'),
+ value: record.value?.backups?.vmsProtection.unprotected ?? 0,
+ color: 'warning',
+ },
+ {
+ label: t('backups.vms-protection.no-job'),
+ value: record.value?.backups?.vmsProtection.notInJob ?? 0,
+ color: 'danger',
+ },
+])
diff --git a/@xen-orchestra/web/src/locales/en.json b/@xen-orchestra/web/src/locales/en.json
index 1fde8d70511..09ca0a31652 100644
--- a/@xen-orchestra/web/src/locales/en.json
+++ b/@xen-orchestra/web/src/locales/en.json
@@ -12,6 +12,12 @@
"backups.jobs.looks-like-issue": "Looks like there is an issue",
"backups.jobs.running-good": "Running good",
+ "backups.vms-protection": "VMs protection",
+ "backups.vms-protection.no-job": "In no job",
+ "backups.vms-protection.protected": "In at least 1 job & protected",
+ "backups.vms-protection.tooltip": "A VM is protected if it's in a backup job, with an enabled schedule, and the last run succeeded",
+ "backups.vms-protection.unprotected": "In at least 1 job but unprotected",
+
"end-of-life": "End of life",
"eol": "EOL",
"for-backup": "For backup",
diff --git a/@xen-orchestra/web/src/locales/fr.json b/@xen-orchestra/web/src/locales/fr.json
index 0fcd10d4d88..f46573ea675 100644
--- a/@xen-orchestra/web/src/locales/fr.json
+++ b/@xen-orchestra/web/src/locales/fr.json
@@ -12,6 +12,12 @@
"backups.jobs.looks-like-issue": "Il semble qu'il y ait un problème",
"backups.jobs.running-good": "Tout est ok",
+ "backups.vms-protection": "Protection des VMs",
+ "backups.vms-protection.no-job": "Dans aucun job",
+ "backups.vms-protection.protected": "Dans au moins 1 job et protégé",
+ "backups.vms-protection.tooltip": "Une VM est protégée si elle se trouve dans un job, avec une planification activée, et si la dernière exécution a réussi",
+ "backups.vms-protection.unprotected": "Dans au moins 1 job mais sans protection",
+
"end-of-life": "Fin de vie",
"eol": "EOL",
"for-backup": "Pour la sauvegarde",
diff --git a/@xen-orchestra/web/src/types/xo/dashboard.type.ts b/@xen-orchestra/web/src/types/xo/dashboard.type.ts
index 33387df7751..b0c6c692bd4 100644
--- a/@xen-orchestra/web/src/types/xo/dashboard.type.ts
+++ b/@xen-orchestra/web/src/types/xo/dashboard.type.ts
@@ -47,5 +47,10 @@ export type XoDashboard = {
total: number
}
issues: BackupIssue[]
+ vmsProtection: {
+ protected: number
+ unprotected: number
+ notInJob: number
+ }
}
}
diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md
index bcb66d38707..2aa6c3de837 100644
--- a/CHANGELOG.unreleased.md
+++ b/CHANGELOG.unreleased.md
@@ -12,7 +12,9 @@
> Users must be able to say: “Nice enhancement, I'm eager to test it”
- [Hosts] Display a warning for hosts whose TLS key is too short to update to XCP-ng 8.3 (PR [#7995](https://github.com/vatesfr/xen-orchestra/pull/7995))
+- **XO 6**:
- [Dashboard] Display S3 backup repository data (PR [#8006](https://github.com/vatesfr/xen-orchestra/pull/8006))
+ - [Dashboard] Display VMs protection data (PR [#8007](https://github.com/vatesfr/xen-orchestra/pull/8007))
- **xo-cli**
- `rest get --output $file` now displays progress information during download
- `rest post` and `rest put` now accept `--input $file` to upload a file and display progress information
From 943ad781cc4a8a3fa1845159bacbf504ef8f41d9 Mon Sep 17 00:00:00 2001
From: MlssFrncJrg <119158464+MelissaFrncJrg@users.noreply.github.com>
Date: Thu, 26 Sep 2024 17:18:56 +0200
Subject: [PATCH 2/2] fix(xo-server/xo-web/mirrorBackup): correct new schedule
property on edited mirror backup job (#8001)
Introduced by ee0adae
---
CHANGELOG.unreleased.md | 2 ++
packages/xo-server/src/api/mirror-backup.mjs | 4 ----
packages/xo-web/src/xo-app/backup/new/mirror/index.js | 7 +++----
3 files changed, 5 insertions(+), 8 deletions(-)
diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md
index 2aa6c3de837..7d61e6fbece 100644
--- a/CHANGELOG.unreleased.md
+++ b/CHANGELOG.unreleased.md
@@ -45,4 +45,6 @@
- xen-api minor
- xo-cli minor
- xo-server minor
+- xo-web patch
+
diff --git a/packages/xo-server/src/api/mirror-backup.mjs b/packages/xo-server/src/api/mirror-backup.mjs
index 802f25ac522..d8bd341cf5d 100644
--- a/packages/xo-server/src/api/mirror-backup.mjs
+++ b/packages/xo-server/src/api/mirror-backup.mjs
@@ -113,10 +113,6 @@ editJob.params = {
remotes: {
type: 'object',
},
- schedules: {
- type: 'object',
- optional: true,
- },
filter: MIRROR_BACKUP_FILTER,
settings: SCHEMA_SETTINGS,
}
diff --git a/packages/xo-web/src/xo-app/backup/new/mirror/index.js b/packages/xo-web/src/xo-app/backup/new/mirror/index.js
index 951b0f22047..111c9b482fa 100644
--- a/packages/xo-web/src/xo-app/backup/new/mirror/index.js
+++ b/packages/xo-web/src/xo-app/backup/new/mirror/index.js
@@ -189,7 +189,6 @@ const NewMirrorBackup = decorate([
}
const settings = { ...state.settings }
- const schedules = { ...state.schedules }
await Promise.all([
...map(props.schedules, ({ id }) => {
const schedule = state.schedules[id]
@@ -214,16 +213,16 @@ const NewMirrorBackup = decorate([
enabled: schedule.enabled,
})
settings[newSchedule.id] = settings[schedule.id]
- schedules[newSchedule.id] = newSchedule
delete settings[schedule.id]
- delete schedules[schedule.id]
}
}),
])
+ const { schedules, ...jobProps } = normalize({ ...state, settings, isIncremental: state.isIncremental })
+
await editMirrorBackupJob({
id: props.job.id,
- ...normalize({ ...state, settings, schedules, isIncremental: state.isIncremental }),
+ ...jobProps,
})
},
resetMirrorBackup: () => (_, props) => getInitialState(props),