diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index 3edd7cca6a4..6be6d3cbb4f 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -12,6 +12,7 @@ > Users must be able to say: “Nice enhancement, I'm eager to test it” - [Proxies] Display the current proxy version (PR [#8104](https://github.com/vatesfr/xen-orchestra/pull/8104)) +- [Backup] Long-term retention ### Bug fixes diff --git a/packages/xo-web/src/common/intl/messages.js b/packages/xo-web/src/common/intl/messages.js index d2b8a7c4a23..663ea8bb157 100644 --- a/packages/xo-web/src/common/intl/messages.js +++ b/packages/xo-web/src/common/intl/messages.js @@ -623,6 +623,11 @@ const messages = { cbtDestroySnapshotDataDisabledInformation: 'Snapshot data can be purged only when NBD is enabled and rolling snapshot is not used', shorterBackupReports: 'Shorter backup reports', + longTermRetention: 'Long-term retention of backups', + numberOfDailyBackupsKept: 'Number of daily backups kept', + numberOfWeeklyBackupsKept: 'Number of weekly backups kept', + numberOfMonthlyBackupsKept: 'Number of monthly backups kept', + numberOfYearlyBackupsKept: 'Number of yearly backups kept', // ------ New Remote ----- newRemote: 'New file system remote', @@ -1523,8 +1528,7 @@ const messages = { ha: 'HA', srHaTooltip: 'SR used for High Availability', nestedVirt: 'Nested virtualization', - nestedVirtualizationWarning: - 'Unstable feature, insecure for the host, usage is discouraged. Click for more details.', + nestedVirtualizationWarning: 'Unstable feature, insecure for the host, usage is discouraged. Click for more details.', vmAffinityHost: 'Affinity host', vmNeedToBeHalted: 'The VM needs to be halted', vmVga: 'VGA', diff --git a/packages/xo-web/src/xo-app/backup/new/index.js b/packages/xo-web/src/xo-app/backup/new/index.js index e34c0c7c7b6..f2c5df96256 100644 --- a/packages/xo-web/src/xo-app/backup/new/index.js +++ b/packages/xo-web/src/xo-app/backup/new/index.js @@ -599,6 +599,18 @@ const New = decorate([ reportRecipients: (reportRecipients.splice(key, 1), reportRecipients), }) }, + setLongTermRetention({ setGlobalSettings }, retention, granularity) { + const { propSettings, settings = propSettings } = this.state + const longTermRetention = settings.getIn(['', 'longTermRetention']) ?? {} + + if (retention > 0) { + longTermRetention[granularity] = { retention, settings: {} } + } else { + delete longTermRetention[granularity] + } + + setGlobalSettings({ longTermRetention: isEmpty(longTermRetention) ? undefined : longTermRetention }) + }, setReportWhen: ({ setGlobalSettings }, { value }) => () => { @@ -679,6 +691,10 @@ const New = decorate([ inputNRetriesVmBackupFailures: generateId, inputBackupReportTplId: generateId, inputTimeoutId: generateId, + inputLongTermRetentionDaily: generateId, + inputLongTermRetentionWeekly: generateId, + inputLongTermRetentionMonthly: generateId, + inputLongTermRetentionYearly: generateId, // In order to keep the user preference, the offline backup is kept in the DB // and it's considered active only when the full mode is enabled @@ -789,6 +805,7 @@ const New = decorate([ checkpointSnapshot, concurrency, fullInterval, + longTermRetention = {}, maxExportRate, nbdConcurrency = 1, nRetriesVmBackupFailures = 0, @@ -1244,6 +1261,51 @@ const New = decorate([ + + {_('longTermRetention')} + + + + effects.setLongTermRetention(value, 'daily')} + value={longTermRetention.daily?.retention} + /> + + + + effects.setLongTermRetention(value, 'weekly')} + value={longTermRetention.weekly?.retention} + /> + + + + effects.setLongTermRetention(value, 'monthly')} + value={longTermRetention.monthly?.retention} + /> + + + + effects.setLongTermRetention(value, 'yearly')} + value={longTermRetention.yearly?.retention} + /> + + +