Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelogs/unreleased/9716-Lyndon-Li
Comment thread
kaovilai marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix issue #9709, add interfaces for CBT service and CBT bitmap
46 changes: 46 additions & 0 deletions pkg/cbtservice/service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
Copyright The Velero Contributors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cbtservice

import "context"

// Range defines the range of a change
type Range struct {
Offset int64
Length int64
}

// SourceInfo is the information provided to the uploader, the uploader calls CBT service with this information
type SourceInfo struct {
// Snapshot is the identifier of the current snapshot
Snapshot string

// ChangeID is the identifier associated to the current snapshot that is used as changeID for following backups
ChangeID string

// VolumeID is the identifier uniquely identifier a volume in the storage to which the CBT is associated
VolumeID string
}

// Service defines the methods for CBT service which could be implemented by Kubernetes SnapshotMetadataService or other customized services
Comment thread
kaovilai marked this conversation as resolved.
type Service interface {
// GetAllocatedBlocks enumerates the allocated blocks of the snapshot and call the record callback
GetAllocatedBlocks(ctx context.Context, snapshot string, record func([]Range) error) error

// GetChangedBlocks enumerates the changed blocks of the snapshot since PIT of changeID and call the record callback
GetChangedBlocks(ctx context.Context, snapshot string, changeID string, record func([]Range) error) error
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To maintain consistency with the SnapshotMetadataService specification, should we align the input parameters of GetChangedBlocks with GetMetadataDeltaRequest, which contain "base_snapshot_id", "target_snapshot_name", "starting_offset", etc?

Same for the method "GetAllocatedBlocks".

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was covered in the design perhaps to be abstract just in case.

ChangeId

ChangeId identifies the base that CBT is generated from, it must strictly map to the parent snapshot in the repository. Otherwise, there will be data corruption in the incremental backup.
Therefore, ChangeId is saved together with the repository snapshot.
The data mover always queries parent snapshot from Unified Repo together with the ChangeId. In this way, no mismatch would happen.
Inside the uploader, the upper layer (DataUpload controller) could also provide the ChangeId as a mechanism of double confirmation. The received ChangeId would be re-evaluated against the one in the provided snapshot.

For Kubernetes API, changeId is represented by BaseSnapshotId.
changeId retrieval is storage specific, generally, it is retrieved from the SnapshotHandle of the VolumeSnapshotContent object; however, storages may also refer to other places to retrieve the changeId.
That is, SnapshotHandle and changeId may be two different values, in this case, the both values need to be preserved.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an abstraction provided by Velero, as the design shared by @kaovilai, this abstraction is for the below purpose:

  1. Support both Kubernetes native CBT service (SnapshotMetadataService) and the possible customized CBT service
  2. It is used by the uploader to translate the entire allocated/changed blocks into the CBT bitmap

Because of 1, the abstraction just purposefully avoids to use the primatives from Kubernetes upstream, e.g., in the upstream target_snapshot_name means the name of the VolumeSnapshot, however, for customized CBT service, it could not be the name of VolumeSnapshot or even not a name (e.g., a snapshot ID instead).
Because of 2, it means it is a special/compacted version when comparing to the upstream primitives, e.g., starting_offset is not required since the uploader always expects to translates the entire CBT, from the begining to end.

}
55 changes: 55 additions & 0 deletions pkg/uploader/cbt/bitmap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
Copyright The Velero Contributors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cbt

import "github.com/vmware-tanzu/velero/pkg/cbtservice"

// Bitmap defines the methods to store and iterate the CBT bitmap
type Bitmap interface {
// Set sets bits within the provided range
Set(cbtservice.Range)

// SetFull sets all bits to the bitmap
SetFull()

// Snapshot returns snapshot of the bitmap
SourceID() string

// ChangeID returns the changeID of the bitmap
ChangeID() string

// Iterator returns the iterator for the CBT Bitmap
Iterator() Iterator
}

// Iterator defines the methods to iterate the CBT bitmap and query the associated information
type Iterator interface {
// ChangeID returns the changeID of the bitmap
ChangeID() string

// Snapshot returns snapshot of the bitmap
Snapshot() string

// BlockSize returns the granularity of the bitmap
BlockSize() int

// Count returns the toal number of count in the bitmap
Count() uint64

// Next returns the offset of the next set block and whether it comes to the end of the iteration
Next() (int64, bool)
}
49 changes: 49 additions & 0 deletions pkg/uploader/cbt/set.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
Copyright The Velero Contributors.

Licensed under the Apache License, Version 2.0 (the "License");
Comment thread
Lyndon-Li marked this conversation as resolved.
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cbt

import (
"context"

"github.com/vmware-tanzu/velero/pkg/cbtservice"
)

// SetBitmapOrFull translates the allocated/changed blocks from CBT service to the given bitmap or set the bitmap to full when error happens
func SetBitmapOrFull(ctx context.Context, service cbtservice.Service, bitmap Bitmap) error {
var err error
if bitmap.ChangeID() == "" {
err = setFromAllocatedBlocks(ctx, service, bitmap)
} else {
err = setFromChangedBlocks(ctx, service, bitmap)
}

if err != nil {
bitmap.SetFull()
}

return err
}

// TODO implement in following PRs
func setFromAllocatedBlocks(_ context.Context, _ cbtservice.Service, _ Bitmap) error {
return nil
}

// TODO implement in following PRs
func setFromChangedBlocks(_ context.Context, _ cbtservice.Service, _ Bitmap) error {
return nil
}
Loading