From e23a1247fc007363356f0f0d89fb23101c885bc3 Mon Sep 17 00:00:00 2001 From: James Lu Date: Wed, 25 Sep 2024 09:09:39 +0800 Subject: [PATCH] feat(backup): upgrade CRs for multiple backup store Upgrade CRs for Volume, BackupVolume, Backup, BackupBackingImage, and BackingImageDataSource. Ref: 5411 Signed-off-by: James Lu --- types/types.go | 3 + upgrade/util/util.go | 60 ++++++++++++ upgrade/v17xto180/upgrade.go | 179 +++++++++++++++++++++++++++++++++++ 3 files changed, 242 insertions(+) diff --git a/types/types.go b/types/types.go index a13b845394..37ba442020 100644 --- a/types/types.go +++ b/types/types.go @@ -29,6 +29,9 @@ const ( LonghornKindEngine = "Engine" LonghornKindReplica = "Replica" LonghornKindBackup = "Backup" + LonghornKindBackupBackingImage = "BackupBackingImage" + LonghornKindBackupTarget = "BackupTarget" + LonghornKindBackupVolume = "BackupVolume" LonghornKindSnapshot = "Snapshot" LonghornKindEngineImage = "EngineImage" LonghornKindInstanceManager = "InstanceManager" diff --git a/upgrade/util/util.go b/upgrade/util/util.go index cad3038e55..3bbaaada1b 100644 --- a/upgrade/util/util.go +++ b/upgrade/util/util.go @@ -532,6 +532,46 @@ func ListAndUpdateEnginesInProvidedCache(namespace string, lhClient *lhclientset return engines, nil } +// ListAndUpdateBackupTargetsInProvidedCache list all backup targets and save them into the provided cached `resourceMap`. This method is not thread-safe. +func ListAndUpdateBackupTargetsInProvidedCache(namespace string, lhClient *lhclientset.Clientset, resourceMaps map[string]interface{}) (map[string]*longhorn.BackupTarget, error) { + if v, ok := resourceMaps[types.LonghornKindBackupTarget]; ok { + return v.(map[string]*longhorn.BackupTarget), nil + } + + backupTargets := map[string]*longhorn.BackupTarget{} + backupTargetList, err := lhClient.LonghornV1beta2().BackupTargets(namespace).List(context.TODO(), metav1.ListOptions{}) + if err != nil { + return nil, err + } + for i, backupTarget := range backupTargetList.Items { + backupTargets[backupTarget.Name] = &backupTargetList.Items[i] + } + + resourceMaps[types.LonghornKindBackupTarget] = backupTargets + + return backupTargets, nil +} + +// ListAndUpdateBackupVolumesInProvidedCache list all backup volumes and save them into the provided cached `resourceMap`. This method is not thread-safe. +func ListAndUpdateBackupVolumesInProvidedCache(namespace string, lhClient *lhclientset.Clientset, resourceMaps map[string]interface{}) (map[string]*longhorn.BackupVolume, error) { + if v, ok := resourceMaps[types.LonghornKindBackupVolume]; ok { + return v.(map[string]*longhorn.BackupVolume), nil + } + + backupVolumes := map[string]*longhorn.BackupVolume{} + backupVolumeList, err := lhClient.LonghornV1beta2().BackupVolumes(namespace).List(context.TODO(), metav1.ListOptions{}) + if err != nil { + return nil, err + } + for i, backupVolume := range backupVolumeList.Items { + backupVolumes[backupVolume.Name] = &backupVolumeList.Items[i] + } + + resourceMaps[types.LonghornKindBackupVolume] = backupVolumes + + return backupVolumes, nil +} + // ListAndUpdateBackupsInProvidedCache list all backups and save them into the provided cached `resourceMap`. This method is not thread-safe. func ListAndUpdateBackupsInProvidedCache(namespace string, lhClient *lhclientset.Clientset, resourceMaps map[string]interface{}) (map[string]*longhorn.Backup, error) { if v, ok := resourceMaps[types.LonghornKindBackup]; ok { @@ -552,6 +592,26 @@ func ListAndUpdateBackupsInProvidedCache(namespace string, lhClient *lhclientset return backups, nil } +// ListAndUpdateBackupBackingImagesInProvidedCache list all backupBackingImages and save them into the provided cached `resourceMap`. This method is not thread-safe. +func ListAndUpdateBackupBackingImagesInProvidedCache(namespace string, lhClient *lhclientset.Clientset, resourceMaps map[string]interface{}) (map[string]*longhorn.BackupBackingImage, error) { + if v, ok := resourceMaps[types.LonghornKindBackupBackingImage]; ok { + return v.(map[string]*longhorn.BackupBackingImage), nil + } + + bbis := map[string]*longhorn.BackupBackingImage{} + bbisList, err := lhClient.LonghornV1beta2().BackupBackingImages(namespace).List(context.TODO(), metav1.ListOptions{}) + if err != nil { + return nil, err + } + for i, bids := range bbisList.Items { + bbis[bids.Name] = &bbisList.Items[i] + } + + resourceMaps[types.LonghornKindBackupBackingImage] = bbis + + return bbis, nil +} + // ListAndUpdateSnapshotsInProvidedCache list all snapshots and save them into the provided cached `resourceMap`. This method is not thread-safe. func ListAndUpdateSnapshotsInProvidedCache(namespace string, lhClient *lhclientset.Clientset, resourceMaps map[string]interface{}) (map[string]*longhorn.Snapshot, error) { if v, ok := resourceMaps[types.LonghornKindSnapshot]; ok { diff --git a/upgrade/v17xto180/upgrade.go b/upgrade/v17xto180/upgrade.go index 2948aa8f5c..39a5fb3cbf 100644 --- a/upgrade/v17xto180/upgrade.go +++ b/upgrade/v17xto180/upgrade.go @@ -8,6 +8,7 @@ import ( "github.com/longhorn/longhorn-manager/types" + longhorn "github.com/longhorn/longhorn-manager/k8s/pkg/apis/longhorn/v1beta2" lhclientset "github.com/longhorn/longhorn-manager/k8s/pkg/client/clientset/versioned" upgradeutil "github.com/longhorn/longhorn-manager/upgrade/util" ) @@ -17,9 +18,187 @@ const ( ) func UpgradeResources(namespace string, lhClient *lhclientset.Clientset, kubeClient *clientset.Clientset, resourceMaps map[string]interface{}) error { + if err := upgradeVolumes(namespace, lhClient, resourceMaps); err != nil { + return err + } + + if err := upgradeBackupVolumes(namespace, lhClient, resourceMaps); err != nil { + return err + } + if err := upgradeBackups(namespace, lhClient, resourceMaps); err != nil { + return err + } + + if err := upgradeBackupBackingImages(namespace, lhClient, resourceMaps); err != nil { + return err + } + + if err := upgradeBackingImageDataSources(namespace, lhClient, resourceMaps); err != nil { + return err + } + return upgradeBackingImages(namespace, lhClient, resourceMaps) } +func upgradeVolumes(namespace string, lhClient *lhclientset.Clientset, resourceMaps map[string]interface{}) (err error) { + defer func() { + err = errors.Wrapf(err, upgradeLogPrefix+"upgrade volume failed") + }() + + volumesMap, err := upgradeutil.ListAndUpdateVolumesInProvidedCache(namespace, lhClient, resourceMaps) + if err != nil { + if apierrors.IsNotFound(err) { + return nil + } + return errors.Wrapf(err, "failed to list all existing Longhorn volumes during the volume upgrade") + } + + for _, v := range volumesMap { + if v.Spec.BackupTargetName == "" { + v.Spec.BackupTargetName = types.DefaultBackupTargetName + } + } + + return nil +} + +func upgradeBackupVolumes(namespace string, lhClient *lhclientset.Clientset, resourceMaps map[string]interface{}) (err error) { + defer func() { + err = errors.Wrapf(err, upgradeLogPrefix+"upgrade backup volume failed") + }() + + backupVolumeMap, err := upgradeutil.ListAndUpdateBackupVolumesInProvidedCache(namespace, lhClient, resourceMaps) + if err != nil { + if apierrors.IsNotFound(err) { + return nil + } + return errors.Wrapf(err, "failed to list all existing Longhorn BackupVolumes during the Longhorn BackupVolume upgrade") + } + + for _, bv := range backupVolumeMap { + if bv.Spec.BackupTargetName == "" { + bv.Spec.BackupTargetName = types.DefaultBackupTargetName + } + + if bv.Spec.VolumeName == "" { + bv.Spec.VolumeName = bv.Name + } + + if bv.Labels == nil { + bv.Labels = make(map[string]string) + } + + _, exists := bv.Labels[types.LonghornLabelBackupVolume] + if !exists { + bv.Labels[types.LonghornLabelBackupVolume] = bv.Spec.VolumeName + } + + _, exists = bv.Labels[types.LonghornLabelBackupTarget] + if !exists { + bv.Labels[types.LonghornLabelBackupTarget] = types.DefaultBackupTargetName + } + } + + return nil +} + +func upgradeBackups(namespace string, lhClient *lhclientset.Clientset, resourceMaps map[string]interface{}) (err error) { + defer func() { + err = errors.Wrapf(err, upgradeLogPrefix+"upgrade backup failed") + }() + + backupMap, err := upgradeutil.ListAndUpdateBackupsInProvidedCache(namespace, lhClient, resourceMaps) + if err != nil { + if apierrors.IsNotFound(err) { + return nil + } + return errors.Wrapf(err, "failed to list all existing Longhorn Backups during the Longhorn Backup upgrade") + } + + for _, b := range backupMap { + if b.Spec.BackupTargetName == "" { + b.Spec.BackupTargetName = types.DefaultBackupTargetName + } + + if b.Labels == nil { + b.Labels = make(map[string]string) + } + + _, exists := b.Labels[types.LonghornLabelBackupTarget] + if !exists { + b.Labels[types.LonghornLabelBackupTarget] = b.Spec.BackupTargetName + } + + _, exists = b.Labels[types.LonghornLabelBackupVolume] + if !exists { + b.Labels[types.LonghornLabelBackupVolume] = b.Status.VolumeName + } + } + + return nil +} + +func upgradeBackupBackingImages(namespace string, lhClient *lhclientset.Clientset, resourceMaps map[string]interface{}) (err error) { + defer func() { + err = errors.Wrapf(err, upgradeLogPrefix+"upgrade backup backing images failed") + }() + + backupBackingImageMap, err := upgradeutil.ListAndUpdateBackupBackingImagesInProvidedCache(namespace, lhClient, resourceMaps) + if err != nil { + if apierrors.IsNotFound(err) { + return nil + } + return errors.Wrapf(err, "failed to list all existing Longhorn Backups during the Longhorn Backup Backing Images upgrade") + } + + for _, bbi := range backupBackingImageMap { + if bbi.Spec.BackingImage == "" { + bbi.Spec.BackingImage = bbi.Status.BackingImage + } + + if bbi.Spec.BackupTargetName == "" { + bbi.Spec.BackupTargetName = types.DefaultBackupTargetName + } + + if bbi.Labels == nil { + bbi.Labels = make(map[string]string) + } + + _, exists := bbi.Labels[types.LonghornLabelBackupTarget] + if !exists { + bbi.Labels[types.LonghornLabelBackupTarget] = bbi.Spec.BackupTargetName + } + + _, exists = bbi.Labels[types.LonghornLabelBackingImage] + if !exists { + bbi.Labels[types.LonghornLabelBackingImage] = bbi.Spec.BackingImage + } + } + + return nil +} + +func upgradeBackingImageDataSources(namespace string, lhClient *lhclientset.Clientset, resourceMaps map[string]interface{}) (err error) { + defer func() { + err = errors.Wrapf(err, upgradeLogPrefix+"upgrade backing image data source failed") + }() + + backingImageDataSourcesMap, err := upgradeutil.ListAndUpdateBackingImageDataSourcesInProvidedCache(namespace, lhClient, resourceMaps) + if err != nil { + if apierrors.IsNotFound(err) { + return nil + } + return errors.Wrapf(err, "failed to list all existing Longhorn Backups during the Longhorn Backup Backing Images upgrade") + } + + for _, bids := range backingImageDataSourcesMap { + if _, exists := bids.Spec.Parameters[longhorn.DataSourceTypeRestoreParameterBackupTargetName]; !exists { + bids.Spec.Parameters[longhorn.DataSourceTypeRestoreParameterBackupTargetName] = types.DefaultBackupTargetName + } + } + return nil +} + func upgradeBackingImages(namespace string, lhClient *lhclientset.Clientset, resourceMaps map[string]interface{}) (err error) { defer func() { err = errors.Wrapf(err, upgradeLogPrefix+"upgrade backing image failed")