From a782b9356eb678276d974fb51a8f5f922c634c0a Mon Sep 17 00:00:00 2001 From: James Lu Date: Fri, 17 Nov 2023 16:34:58 +0800 Subject: [PATCH] feat(backup): modify csi plugin for backups Support multiple backup stores. Get a default backup target name when trying to do a backup for CSI volume snapshots. Ref: 5411 Signed-off-by: James Lu --- csi/controller_server.go | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/csi/controller_server.go b/csi/controller_server.go index 4ccceed48d..1c0b015f4a 100644 --- a/csi/controller_server.go +++ b/csi/controller_server.go @@ -730,9 +730,21 @@ func (cs *ControllerServer) createCSISnapshotTypeLonghornBackup(req *csi.CreateS return nil, status.Error(codes.InvalidArgument, "Snapshot name must be provided") } + var backupTargetName string + backupTargetListOutput, err := cs.apiClient.BackupTarget.List(&longhornclient.ListOpts{}) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + for _, bt := range backupTargetListOutput.Data { + if bt.Default { + backupTargetName = bt.Name + break + } + } + // We check for backup existence first, since it's possible that the actual volume is no longer available but the // backup still is. - backup, err := cs.getBackup(csiVolumeName, csiSnapshotName) + backup, err := cs.getBackup(csiVolumeName, csiSnapshotName, backupTargetName) if err != nil { // Status code set in waitForBackupControllerSync. return nil, err @@ -794,8 +806,9 @@ func (cs *ControllerServer) createCSISnapshotTypeLonghornBackup(req *csi.CreateS // create backup based on local volume snapshot log.Infof("Creating volume %s backup for snapshot %s", existVol.Name, csiSnapshotName) existVol, err = cs.apiClient.Volume.ActionSnapshotBackup(existVol, &longhornclient.SnapshotInput{ - Labels: csiLabels, - Name: csiSnapshotName, + Labels: csiLabels, + Name: csiSnapshotName, + BackupTargetName: backupTargetName, }) if err != nil { return nil, status.Error(codes.Internal, err.Error()) @@ -805,7 +818,7 @@ func (cs *ControllerServer) createCSISnapshotTypeLonghornBackup(req *csi.CreateS // status. It's possible that the backup operation can't actually be completed, but we need to return quickly so the // CO can unfreeze I/O (if freezing is supported) and without error (if possible) so the CO knows our ID and can use // it in future calls. - backup, err = cs.waitForBackupControllerSync(existVol.Name, csiSnapshotName) + backup, err = cs.waitForBackupControllerSync(existVol.Name, csiSnapshotName, backupTargetName) if err != nil { // Status code set in waitForBackupControllerSync. return nil, err @@ -1165,9 +1178,9 @@ func (cs *ControllerServer) waitForVolumeState(volumeID string, stateDescription // waitForBackupControllerSync returns the backup of the given snapshot of the given volume. It does not return until // the backup controller has synced at least once (so the backup contains information we need). This function does not // wait for the existence of a backup. If one doesn't exist, it returns without error immediately. -func (cs *ControllerServer) waitForBackupControllerSync(volumeName, snapshotName string) (*longhornclient.Backup, error) { +func (cs *ControllerServer) waitForBackupControllerSync(volumeName, snapshotName, backupTargetName string) (*longhornclient.Backup, error) { // Don't wait if we don't need to. - backup, err := cs.getBackup(volumeName, snapshotName) + backup, err := cs.getBackup(volumeName, snapshotName, backupTargetName) if err != nil { return nil, err } @@ -1192,7 +1205,7 @@ func (cs *ControllerServer) waitForBackupControllerSync(volumeName, snapshotName logrus.Warn(msg) return nil, status.Error(codes.DeadlineExceeded, msg) case <-tick: - backup, err := cs.getBackup(volumeName, snapshotName) + backup, err := cs.getBackup(volumeName, snapshotName, backupTargetName) if err != nil { return nil, err } @@ -1207,9 +1220,10 @@ func (cs *ControllerServer) waitForBackupControllerSync(volumeName, snapshotName // snapshot. It does not rely on volume.BackupStatus because volume.BackupStatus.Snapshot is only set if the backup // successfully initializes and after the backup monitor has had a chance to sync. We want to retrieve the backup // (and in particular, its name) as quickly as possible and in any state. -func (cs *ControllerServer) getBackup(volumeName, snapshotName string) (*longhornclient.Backup, error) { +func (cs *ControllerServer) getBackup(volumeName, snapshotName, backupTargetName string) (*longhornclient.Backup, error) { // Successfully returns an empty BackupVolume with volumeName even if one doesn't exist. - backupVolume, err := cs.apiClient.BackupVolume.ById(volumeName) + backupVolumeName := volumeName + "-" + backupTargetName + backupVolume, err := cs.apiClient.BackupVolume.ById(backupVolumeName) if err != nil { return nil, status.Error(codes.Internal, err.Error()) }