diff --git a/controller/system_backup_controller.go b/controller/system_backup_controller.go index 3f084da633..6a5348e5c4 100644 --- a/controller/system_backup_controller.go +++ b/controller/system_backup_controller.go @@ -826,12 +826,18 @@ func (c *SystemBackupController) createVolumeBackup(volume *longhorn.Volume, sys return nil, errors.Wrapf(err, "failed to create Volume %v snapshot %s", volume.Name, snapshot.Name) } + defaultBackupTarget, err := c.ds.GetDefaultBackupTargetRO() + if err != nil { + return nil, errors.Wrapf(err, "failed to get default backup target") + } + backup = &longhorn.Backup{ ObjectMeta: metav1.ObjectMeta{ Name: volumeBackupName, }, Spec: longhorn.BackupSpec{ - SnapshotName: snapshot.Name, + SnapshotName: snapshot.Name, + BackupTargetName: defaultBackupTarget.Name, }, } backup, err = c.ds.CreateBackup(backup, volume.Name) diff --git a/controller/system_restore_controller_test.go b/controller/system_restore_controller_test.go index c459c6f831..ed5d2ef2e7 100644 --- a/controller/system_restore_controller_test.go +++ b/controller/system_restore_controller_test.go @@ -736,6 +736,9 @@ func fakeSystemRolloutBackupTargetDefault(c *C, informerFactory lhinformers.Shar BackupTargetURL: "", CredentialSecret: "", }, + Status: longhorn.BackupTargetStatus{ + Default: true, + }, } backupTarget, err := lhClient.LonghornV1beta2().BackupTargets(TestNamespace).Create(context.TODO(), backupTarget, metav1.CreateOptions{}) c.Assert(err, IsNil) 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()) }