From 4884f52c9088cdf20b3638480412ec49eaad10b5 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 23 Sep 2025 14:51:42 +0530 Subject: [PATCH] ui: allow provisioning backups during instance deploy (#11612) * ui: allow assigning backup offring during instance deploy Add backup offering selection to Deploy VM wizard and assign selected backup offering to the VM after successful deployment. This enables users to choose a backup offering during VM creation, and the VM is automatically associated with the selected offering post-deployment. Signed-off-by: Abhishek Kumar * changes for schedules Signed-off-by: Abhishek Kumar * fix Signed-off-by: Abhishek Kumar * fix Signed-off-by: Abhishek Kumar * Update ui/public/locales/pt_BR.json * Update ui/src/views/compute/wizard/DeployInstanceBackupSelection.vue Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * address review Signed-off-by: Abhishek Kumar * fix * allow only one schdeule per interval type Signed-off-by: Abhishek Kumar * show message same internaltype schedule * show backup step only when zone has offering --------- Signed-off-by: Abhishek Kumar Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- ui/public/locales/de_DE.json | 1 + ui/public/locales/el_GR.json | 1 + ui/public/locales/en.json | 9 +- ui/public/locales/es.json | 1 + ui/public/locales/ja_JP.json | 1 + ui/public/locales/ko_KR.json | 1 + ui/public/locales/pt_BR.json | 3 +- ui/public/locales/te.json | 1 + ui/public/locales/zh_CN.json | 1 + .../widgets/InfiniteScrollSelect.vue | 2 +- ui/src/config/section/storage.js | 2 +- ui/src/main.js | 4 +- ui/src/utils/plugins.js | 11 ++ ui/src/views/compute/BackupScheduleWizard.vue | 4 +- ui/src/views/compute/DeployVM.vue | 173 +++++++++++++++++- .../views/compute/backup/BackupSchedule.vue | 10 +- ui/src/views/compute/backup/FormSchedule.vue | 24 ++- .../wizard/DeployInstanceBackupSelection.vue | 154 ++++++++++++++++ 18 files changed, 384 insertions(+), 19 deletions(-) create mode 100644 ui/src/views/compute/wizard/DeployInstanceBackupSelection.vue diff --git a/ui/public/locales/de_DE.json b/ui/public/locales/de_DE.json index fd29ac3eb54..d99ba4157df 100644 --- a/ui/public/locales/de_DE.json +++ b/ui/public/locales/de_DE.json @@ -259,6 +259,7 @@ "label.available": "Verfügbar", "label.back": "Zurück", "label.backup": "Backup", +"label.backups": "Backup", "label.backup.attach.restore": "Backup-Volume wiederherstellen und anhängen", "label.backup.offering.assign": "VM zum Backup-Angebot zuordnen", "label.backup.offering.remove": "VM vom Backup-Angebot entfernen", diff --git a/ui/public/locales/el_GR.json b/ui/public/locales/el_GR.json index 6b939f52029..3c0cd6a1706 100644 --- a/ui/public/locales/el_GR.json +++ b/ui/public/locales/el_GR.json @@ -317,6 +317,7 @@ "label.availableprocessors": "Διαθέσιμοι πυρήνες επεξεργαστή", "label.back": "Πίσω", "label.backup": "Αντίγραφα ασφαλείας", +"label.backups": "Αντίγραφα ασφαλείας", "label.backup.attach.restore": "Επαναφορά και επισύναψη τόμου αντιγράφου ασφαλείας", "label.backup.offering.assign": "Αντιστοίχιση εικονικής μηχανής με προσφορά δημιουργίας αντιγράφων ασφαλείας", "label.backup.offering.remove": "Κατάργηση εικονικής μηχανής από την προσφορά δημιουργίας αντιγράφων ασφαλείας", diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 5136f241fb3..b740272bcad 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -252,6 +252,7 @@ "label.add.acl.rule": "Add ACL rule", "label.add.acl": "Add ACL", "label.add.affinity.group": "Add new Affinity Group", +"label.add.backup.schedule": "Add Backup Schedule", "label.add.baremetal.dhcp.device": "Add bare metal DHCP device", "label.add.bgp.peer": "Add BGP Peer", "label.add.bigswitchbcf.device": "Add BigSwitch BCF Controller", @@ -442,14 +443,17 @@ "label.availablevirtualmachinecount": "Available Instances", "label.back": "Back", "label.back.login": "Back to login", -"label.backup": "Backups", +"label.backup": "Backup", +"label.backups": "Backups", "label.backup.attach.restore": "Restore and attach backup volume", "label.backup.configure.schedule": "Configure Backup Schedule", "label.backup.offering.assign": "Assign Instance to backup offering", "label.backup.offering.remove": "Remove Instance from backup offering", "label.backup.offerings": "Backup Offerings", +"label.backup.offering.assign.failed": "Failed to assign Backup Offering", "label.backup.repository": "Backup Repository", "label.backup.restore": "Restore Instance backup", +"label.backup.schedule.create.failed": "Failed to create Backup Schedule", "label.backuplimit": "Backup Limits", "label.backup.storage": "Backup Storage", "label.backupstoragelimit": "Backup Storage Limits (GiB)", @@ -2194,6 +2198,7 @@ "label.select.all": "Select all", "label.select.columns": "Select columns", "label.select.a.zone": "Select a Zone", +"label.select.backup.offering": "Select Backup Offering", "label.select.deployment.infrastructure": "Select deployment infrastructure", "label.select.guest.os.type": "Please select the guest OS type", "label.select.network": "Select Network", @@ -3075,7 +3080,9 @@ "message.backup.attach.restore": "Please confirm that you want to restore and attach the volume from the backup?", "message.backup.create": "Are you sure you want to create an Instance backup?", "message.backup.offering.remove": "Are you sure you want to remove Instance from backup offering and delete the backup chain?", +"message.backup.provision.instance": "Select a backup offering to assign to the Instance. You can also add one or more backup schedules for different interval types to automate backups for this Instance. Assigning a backup offering and schedules helps protect your data by enabling automated and scheduled backups.", "message.backup.restore": "Please confirm that you want to restore the Instance backup?", +"message.backup.update.existing.schedule": "Updating existing backup schedule for the same interval type", "message.cancel.shutdown": "Please confirm that you would like to cancel the shutdown on this Management Server. It will resume accepting any new Async Jobs.", "message.cancel.maintenance": "Please confirm that you would like to cancel the maintenance on this Management Server. It will resume accepting any new Async Jobs.", "message.certificate.upload.processing": "Certificate upload in progress", diff --git a/ui/public/locales/es.json b/ui/public/locales/es.json index ab57c951531..b7a409adad1 100644 --- a/ui/public/locales/es.json +++ b/ui/public/locales/es.json @@ -222,6 +222,7 @@ "label.available": "Disponible", "label.back": "Volver", "label.backup": "Respaldos", +"label.backups": "Respaldos", "label.backup.attach.restore": "Restaurar y conectar un Volumen de Respaldo", "label.backup.offering.assign": "Asignar instancia a una oferta de respaldo", "label.backup.offering.remove": "remover instancia de una oferta de respaldo", diff --git a/ui/public/locales/ja_JP.json b/ui/public/locales/ja_JP.json index 3ab374a2a06..734a0ea851d 100644 --- a/ui/public/locales/ja_JP.json +++ b/ui/public/locales/ja_JP.json @@ -485,6 +485,7 @@ "label.available.public.ips": "使用できるパブリックIPアドレス", "label.back": "戻る", "label.backup": "バックアップ", + "label.backups": "バックアップ", "label.backup.attach.restore": "復元とバックアップボリュームをアタッチ", "label.backup.offering.assign": "VMをバックアップオファリングに割り当て", "label.backup.offering.remove": "VMバックアップオファリングから削除", diff --git a/ui/public/locales/ko_KR.json b/ui/public/locales/ko_KR.json index cc9683633be..1f20c95438d 100644 --- a/ui/public/locales/ko_KR.json +++ b/ui/public/locales/ko_KR.json @@ -269,6 +269,7 @@ "label.available": "\uc0ac\uc6a9 \uac00\ub2a5", "label.back": "\ub4a4\ub85c", "label.backup": "\ubc31\uc5c5", +"label.backups": "\ubc31\uc5c5", "label.backup.attach.restore": "\ubc31\uc5c5 \ubcfc\ub968 \ubcf5\uc6d0 \ubc0f \uc5f0\uacb0", "label.backup.offering.assign": "\uac00\uc0c1\uba38\uc2e0\uc5d0 \ubc31\uc5c5 \uc624\ud37c\ub9c1 \ud560\ub2f9", "label.backup.offering.remove": "\uac00\uc0c1\uba38\uc2e0\uc5d0 \ubc31\uc5c5 \uc624\ud37c\ub9c1 \uc81c\uac70", diff --git a/ui/public/locales/pt_BR.json b/ui/public/locales/pt_BR.json index 09b0242ef1a..711dd36deff 100644 --- a/ui/public/locales/pt_BR.json +++ b/ui/public/locales/pt_BR.json @@ -292,7 +292,8 @@ "label.availability": "Disponibilidade", "label.available": "Dispon\u00edvel", "label.back": "Voltar", -"label.backup": "Backups", +"label.backup": "Backup", +"label.backups": "Backups", "label.backup.attach.restore": "Restaurar e anexar volume de backup", "label.backup.offering.assign": "Atribuir VM a oferta de backup", "label.backup.offering.remove": "Remover VM de oferta de backup", diff --git a/ui/public/locales/te.json b/ui/public/locales/te.json index 957aed4ee88..5f89bbf7ed7 100644 --- a/ui/public/locales/te.json +++ b/ui/public/locales/te.json @@ -419,6 +419,7 @@ "label.back": "వెనుకకు", "label.back.login": "తిరిగి లాగిన్‌కి", "label.backup": "బ్యాకప్‌లు", + "label.backups": "బ్యాకప్‌లు", "label.backup.attach.restore": "బ్యాకప్ వాల్యూమ్‌ను పునరుద్ధరించండి మరియు అటాచ్ చేయండి", "label.backup.configure.schedule": "బ్యాకప్ షెడ్యూల్‌ను కాన్ఫిగర్ చేయండి", "label.backup.offering.assign": "బ్యాకప్ సమర్పణకు ఉదాహరణను కేటాయించండి", diff --git a/ui/public/locales/zh_CN.json b/ui/public/locales/zh_CN.json index d09f960edf5..02149360841 100644 --- a/ui/public/locales/zh_CN.json +++ b/ui/public/locales/zh_CN.json @@ -561,6 +561,7 @@ "label.back": "\u540E\u9000", "label.backup": "\u5907\u4EFD", + "label.backups": "\u5907\u4EFD", "label.backup.attach.restore": "\u6062\u590D\u5E76\u8FDE\u63A5\u5907\u4EFD\u5377", "label.backup.offering.assign": "\u5C06\u865A\u62DF\u673A\u5206\u914D\u7ED9\u5907\u4EFD\u4EA7\u54C1", "label.backup.offering.remove": "\u4ECE\u5907\u4EFD\u4EA7\u54C1\u4E2D\u5220\u9664\u865A\u62DF\u673A", diff --git a/ui/src/components/widgets/InfiniteScrollSelect.vue b/ui/src/components/widgets/InfiniteScrollSelect.vue index c11f9686446..608eeebf133 100644 --- a/ui/src/components/widgets/InfiniteScrollSelect.vue +++ b/ui/src/components/widgets/InfiniteScrollSelect.vue @@ -77,7 +77,7 @@ - + diff --git a/ui/src/config/section/storage.js b/ui/src/config/section/storage.js index 4308832bcf2..df0176e5a2d 100644 --- a/ui/src/config/section/storage.js +++ b/ui/src/config/section/storage.js @@ -415,7 +415,7 @@ export default { }, { name: 'backup', - title: 'label.backup', + title: 'label.backups', icon: 'cloud-upload-outlined', permission: ['listBackups'], params: { listvmdetails: 'true' }, diff --git a/ui/src/main.js b/ui/src/main.js index f117fb57810..7441f801086 100644 --- a/ui/src/main.js +++ b/ui/src/main.js @@ -40,7 +40,8 @@ import { dialogUtilPlugin, cpuArchitectureUtilPlugin, imagesUtilPlugin, - extensionsUtilPlugin + extensionsUtilPlugin, + backupUtilPlugin } from './utils/plugins' import { VueAxios } from './utils/request' import directives from './utils/directives' @@ -63,6 +64,7 @@ vueApp.use(dialogUtilPlugin) vueApp.use(cpuArchitectureUtilPlugin) vueApp.use(imagesUtilPlugin) vueApp.use(extensionsUtilPlugin) +vueApp.use(backupUtilPlugin) vueApp.use(extensions) vueApp.use(directives) diff --git a/ui/src/utils/plugins.js b/ui/src/utils/plugins.js index 61456d98b12..648bc3ae081 100644 --- a/ui/src/utils/plugins.js +++ b/ui/src/utils/plugins.js @@ -597,3 +597,14 @@ export const extensionsUtilPlugin = { } } } + +export const backupUtilPlugin = { + install (app) { + app.config.globalProperties.$isBackupProviderSupportsQuiesceVm = function (provider) { + if (!provider && typeof provider !== 'string') { + return false + } + return ['nas'].includes(provider.toLowerCase()) + } + } +} diff --git a/ui/src/views/compute/BackupScheduleWizard.vue b/ui/src/views/compute/BackupScheduleWizard.vue index a37893d2bc1..650f4915ece 100644 --- a/ui/src/views/compute/BackupScheduleWizard.vue +++ b/ui/src/views/compute/BackupScheduleWizard.vue @@ -21,13 +21,11 @@ + :resource="resource"/> diff --git a/ui/src/views/compute/DeployVM.vue b/ui/src/views/compute/DeployVM.vue index 7872a405a69..854d082075f 100644 --- a/ui/src/views/compute/DeployVM.vue +++ b/ui/src/views/compute/DeployVM.vue @@ -540,6 +540,25 @@ + + + @@ -901,7 +920,7 @@