Skip to content

Commit

Permalink
br: support gc immune backup specification
Browse files Browse the repository at this point in the history
Signed-off-by: BornChanger <dawn_catcher@126.com>
  • Loading branch information
BornChanger committed Mar 6, 2024
1 parent f588fed commit 03365ac
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 23 deletions.
12 changes: 12 additions & 0 deletions docs/api-references/federation-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,18 @@ VolumeBackupStatus
<td>
</td>
</tr>
<tr>
<td>
<code>gcImmune</code></br>
<em>
bool
</em>
</td>
<td>
<em>(Optional)</em>
<p>GCImmune indicates whether this EBS volume snapshot backup is immune to GC</p>
</td>
</tr>
</tbody>
</table>
<h3 id="volumebackupschedule">VolumeBackupSchedule</h3>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ spec:
properties:
apiVersion:
type: string
gcImmune:
default: false
type: boolean
kind:
type: string
metadata:
Expand Down
3 changes: 3 additions & 0 deletions manifests/federation-crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ spec:
properties:
apiVersion:
type: string
gcImmune:
default: false
type: boolean
kind:
type: string
metadata:
Expand Down
7 changes: 7 additions & 0 deletions pkg/apis/federation/pingcap/v1alpha1/openapi_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions pkg/apis/federation/pingcap/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ type VolumeBackup struct {

// +k8s:openapi-gen=false
Status VolumeBackupStatus `json:"status,omitempty"`

// GCImmune indicates whether this EBS volume snapshot backup is immune to GC
// +optional
// +kubebuilder:default=false
GCImmune bool `json:"gcImmune,omitempty"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
Expand Down
42 changes: 29 additions & 13 deletions pkg/fedvolumebackup/backupschedule/backup_schedule_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,8 @@ func sortSnapshotBackups(backupsList []*v1alpha1.VolumeBackup) []*v1alpha1.Volum
var ascBackupList = make([]*v1alpha1.VolumeBackup, 0)

for _, backup := range backupsList {
// Only try to GC Completed or Failed VolumeBackup
if !(v1alpha1.IsVolumeBackupFailed(backup) || v1alpha1.IsVolumeBackupComplete(backup)) {
// Only try to GC Completed or Failed VolumeBackup, and skip the backup is immune to GC
if !(v1alpha1.IsVolumeBackupFailed(backup) || v1alpha1.IsVolumeBackupComplete(backup)) || backup.GCImmune {
continue
}
ascBackupList = append(ascBackupList, backup)
Expand Down Expand Up @@ -351,22 +351,38 @@ func (bm *backupScheduleManager) backupGCByMaxBackups(vbs *v1alpha1.VolumeBackup
// In order to avoid throttling, we choose to do delete volumebackup one by one.
// Delete the oldest expired backup
if len(backupsList) > int(*vbs.Spec.MaxBackups) {
backup := backupsList[len(backupsList)-1]
targetIdx := len(backupsList) - 1

// Skip the backup is immune to GC
backup := backupsList[targetIdx]
for {
if backup.GCImmune {
targetIdx--
if targetIdx < 0 {
return
}
backup = backupsList[targetIdx]
} else {
break
}
}

if backup.DeletionTimestamp != nil {
klog.Infof("Deletion is ongoing for backup schedule %s/%s, backup %s", ns, bsName, backup.GetName())
return
} else {
if err = bm.deps.FedVolumeBackupControl.DeleteVolumeBackup(backup); err != nil {
klog.Errorf("backup schedule %s/%s gc backup %s failed, err %v", ns, bsName, backup.GetName(), err)
return
}
klog.Infof("backup schedule %s/%s gc backup %s success", ns, bsName, backup.GetName())
}

if len(backupsList) == 1 {
// All backups have been deleted, so the last backup information in the backupSchedule should be reset
bm.resetLastBackup(vbs)
}
if err = bm.deps.FedVolumeBackupControl.DeleteVolumeBackup(backup); err != nil {
klog.Errorf("backup schedule %s/%s gc backup %s failed, err %v", ns, bsName, backup.GetName(), err)
return
}
klog.Infof("backup schedule %s/%s gc backup %s success", ns, bsName, backup.GetName())

if len(backupsList) == 1 {
// All backups have been deleted, so the last backup information in the backupSchedule should be reset
bm.resetLastBackup(vbs)
}

}
}

Expand Down
47 changes: 37 additions & 10 deletions pkg/fedvolumebackup/backupschedule/backup_schedule_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,16 +239,14 @@ func TestCalculateExpiredBackups(t *testing.T) {

testCases := []*testCase{
// no backup should be deleted
/*
{
backups: []*v1alpha1.VolumeBackup{
fakeBackup(&last10Min),
},
reservedTime: 24 * time.Hour,
expectedDeleteBackupCount: 0,
{
backups: []*v1alpha1.VolumeBackup{
fakeBackup(&last10Min),
},
*/
// 2 backup should be deleted
reservedTime: 24 * time.Hour,
expectedDeleteBackupCount: 0,
},
// 3 backups should be deleted
{
backups: []*v1alpha1.VolumeBackup{
fakeBackup(&last3Day),
Expand All @@ -259,10 +257,21 @@ func TestCalculateExpiredBackups(t *testing.T) {
reservedTime: 24 * time.Hour,
expectedDeleteBackupCount: 3,
},
// 2 backups should be deleted
{
backups: []*v1alpha1.VolumeBackup{
fakeBackup(&last3Day),
fakeImmuneGCBackup(&last2Day),
fakeBackup(&last1Day),
fakeBackup(&last10Min),
},
reservedTime: 24 * time.Hour,
expectedDeleteBackupCount: 2,
},
}

for _, tc := range testCases {
deletedBackups, err := calculateExpiredBackups(tc.backups, tc.reservedTime)
deletedBackups, err := calculateExpiredBackups(sortSnapshotBackups(tc.backups), tc.reservedTime)
g.Expect(err).Should(BeNil())
g.Expect(len(deletedBackups)).Should(Equal(tc.expectedDeleteBackupCount))
}
Expand Down Expand Up @@ -395,6 +404,24 @@ func fakeBackup(ts *time.Time) *v1alpha1.VolumeBackup {
return backup
}
backup.CreationTimestamp = metav1.Time{Time: *ts}
backup.Status.Conditions = append(backup.Status.Conditions, v1alpha1.VolumeBackupCondition{
Type: v1alpha1.VolumeBackupComplete,
Status: v1.ConditionTrue,
})
return backup
}

func fakeImmuneGCBackup(ts *time.Time) *v1alpha1.VolumeBackup {
backup := &v1alpha1.VolumeBackup{}
if ts == nil {
return backup
}
backup.CreationTimestamp = metav1.Time{Time: *ts}
backup.Status.Conditions = append(backup.Status.Conditions, v1alpha1.VolumeBackupCondition{
Type: v1alpha1.VolumeBackupComplete,
Status: v1.ConditionTrue,
})
backup.GCImmune = true
return backup
}

Expand Down

0 comments on commit 03365ac

Please sign in to comment.