Skip to content

Commit

Permalink
feat(backup): modify csi plugin for backups
Browse files Browse the repository at this point in the history
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 <james.lu@suse.com>
  • Loading branch information
mantissahz committed Nov 17, 2023
1 parent 0cb818f commit a782b93
Showing 1 changed file with 23 additions and 9 deletions.
32 changes: 23 additions & 9 deletions csi/controller_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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())
Expand All @@ -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
Expand Down Expand Up @@ -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
}
Expand All @@ -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
}
Expand All @@ -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())
}
Expand Down

0 comments on commit a782b93

Please sign in to comment.