Skip to content

Commit

Permalink
Retrieve DataUpload into backup result ConfigMap during volume snapsh…
Browse files Browse the repository at this point in the history
…ot restore.

Fix issue #6117.
Add CSI plugin needs builder functions.

Signed-off-by: Xun Jiang <jxun@vmware.com>
  • Loading branch information
Xun Jiang committed Jun 30, 2023
1 parent a97d01f commit ec4bb42
Show file tree
Hide file tree
Showing 18 changed files with 1,310 additions and 3 deletions.
1 change: 1 addition & 0 deletions changelogs/unreleased/6410-blackpiglet
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Retrieve DataUpload into backup result ConfigMap during volume snapshot restore.
1 change: 1 addition & 0 deletions changelogs/unreleased/6436-qiuming-best
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add data download controller for data mover
23 changes: 23 additions & 0 deletions pkg/apis/velero/v1/labels_annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,27 @@ const (

// AsyncOperationIDLabel is the label key used to identify the async operation ID
AsyncOperationIDLabel = "velero.io/async-operation-id"

// PVCNameLabel is the label key used to identify the the PVC's namespace and name.
// The format is <namespace>/<name>.
PVCNamespaceNameLabel = "velero.io/pvc-namespace-name"

// DynamicPVRestoreLabel is the label key for dynamic PV restore
DynamicPVRestoreLabel = "velero.io/dynamic-pv-restore"

// ResourceUsageLabel is the label key to explain the Velero resource usage.
ResourceUsageLabel = "velero.io/resource-usage"
)

type AsyncOperationIDPrefix string

const (
AsyncOperationIDPrefixDataDownload AsyncOperationIDPrefix = "dd-"
AsyncOperationIDPrefixDataUpload AsyncOperationIDPrefix = "du-"
)

type VeleroResourceUsage string

const (
VeleroResourceUsageDataUploadResult VeleroResourceUsage = "DataUpload"
)
112 changes: 112 additions & 0 deletions pkg/builder/data_download_builder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
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 builder

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

velerov2alpha1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v2alpha1"
)

// DataDownloadBuilder builds DataDownload objects.
type DataDownloadBuilder struct {
object *velerov2alpha1api.DataDownload
}

// ForDataDownload is the constructor of DataDownloadBuilder
func ForDataDownload(namespace, name string) *DataDownloadBuilder {
return &DataDownloadBuilder{
object: &velerov2alpha1api.DataDownload{
TypeMeta: metav1.TypeMeta{
Kind: "DataDownload",
APIVersion: velerov2alpha1api.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
},
}
}

// Result returns the built DataDownload.
func (d *DataDownloadBuilder) Result() *velerov2alpha1api.DataDownload {
return d.object
}

// BackupStorageLocation sets the DataDownload's backup storage location.
func (d *DataDownloadBuilder) BackupStorageLocation(name string) *DataDownloadBuilder {
d.object.Spec.BackupStorageLocation = name
return d
}

// Phase sets the DataDownload's phase.
func (d *DataDownloadBuilder) Phase(phase velerov2alpha1api.DataDownloadPhase) *DataDownloadBuilder {
d.object.Status.Phase = phase
return d
}

// SnapshotID sets the DataDownload's SnapshotID.
func (d *DataDownloadBuilder) SnapshotID(id string) *DataDownloadBuilder {
d.object.Spec.SnapshotID = id
return d
}

// DataMover sets the DataDownload's DataMover.
func (d *DataDownloadBuilder) DataMover(dataMover string) *DataDownloadBuilder {
d.object.Spec.DataMover = dataMover
return d
}

// SourceNamespace sets the DataDownload's SourceNamespace.
func (d *DataDownloadBuilder) SourceNamespace(sourceNamespace string) *DataDownloadBuilder {
d.object.Spec.SourceNamespace = sourceNamespace
return d
}

// TargetVolume sets the DataDownload's TargetVolume.
func (d *DataDownloadBuilder) TargetVolume(targetVolume velerov2alpha1api.TargetVolumeSpec) *DataDownloadBuilder {
d.object.Spec.TargetVolume = targetVolume
return d
}

// Cancel sets the DataDownload's Cancel.
func (d *DataDownloadBuilder) Cancel(cancel bool) *DataDownloadBuilder {
d.object.Spec.Cancel = cancel
return d
}

// OperationTimeout sets the DataDownload's OperationTimeout.
func (d *DataDownloadBuilder) OperationTimeout(timeout metav1.Duration) *DataDownloadBuilder {
d.object.Spec.OperationTimeout = timeout
return d
}

// DataMoverConfig sets the DataDownload's DataMoverConfig.
func (d *DataDownloadBuilder) DataMoverConfig(config *map[string]string) *DataDownloadBuilder {
d.object.Spec.DataMoverConfig = *config
return d
}

// ObjectMeta applies functional options to the DataDownload's ObjectMeta.
func (b *DataDownloadBuilder) ObjectMeta(opts ...ObjectMetaOpt) *DataDownloadBuilder {
for _, opt := range opts {
opt(b.object)
}

return b
}
7 changes: 7 additions & 0 deletions pkg/builder/object_meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,10 @@ func WithCreationTimestamp(t time.Time) func(obj metav1.Object) {
obj.SetCreationTimestamp(metav1.Time{Time: t})
}
}

// WithOwnerReference is a functional option that applies the specified OwnerReference to an object.
func WithOwnerReference(val []metav1.OwnerReference) func(obj metav1.Object) {
return func(obj metav1.Object) {
obj.SetOwnerReferences(val)
}
}
37 changes: 37 additions & 0 deletions pkg/builder/persistent_volume_claim_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package builder

import (
corev1api "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand Down Expand Up @@ -73,3 +74,39 @@ func (b *PersistentVolumeClaimBuilder) Phase(phase corev1api.PersistentVolumeCla
b.object.Status.Phase = phase
return b
}

// RequestResource sets the PersistentVolumeClaim's spec.Resources.Requests.
func (b *PersistentVolumeClaimBuilder) RequestResource(requests corev1api.ResourceList) *PersistentVolumeClaimBuilder {
if b.object.Spec.Resources.Requests == nil {
b.object.Spec.Resources.Requests = make(map[corev1api.ResourceName]resource.Quantity)
}
b.object.Spec.Resources.Requests = requests
return b
}

// LimitResource sets the PersistentVolumeClaim's spec.Resources.Limits.
func (b *PersistentVolumeClaimBuilder) LimitResource(limits corev1api.ResourceList) *PersistentVolumeClaimBuilder {
if b.object.Spec.Resources.Limits == nil {
b.object.Spec.Resources.Limits = make(map[corev1api.ResourceName]resource.Quantity)
}
b.object.Spec.Resources.Limits = limits
return b
}

// DataSource sets the PersistentVolumeClaim's spec.DataSource.
func (b *PersistentVolumeClaimBuilder) DataSource(dataSource *corev1api.TypedLocalObjectReference) *PersistentVolumeClaimBuilder {
b.object.Spec.DataSource = dataSource
return b
}

// DataSourceRef sets the PersistentVolumeClaim's spec.DataSourceRef.
func (b *PersistentVolumeClaimBuilder) DataSourceRef(dataSourceRef *corev1api.TypedLocalObjectReference) *PersistentVolumeClaimBuilder {
b.object.Spec.DataSourceRef = dataSourceRef
return b
}

// Selector sets the PersistentVolumeClaim's spec.Selector.
func (b *PersistentVolumeClaimBuilder) Selector(labelSelector *metav1.LabelSelector) *PersistentVolumeClaimBuilder {
b.object.Spec.Selector = labelSelector
return b
}
4 changes: 4 additions & 0 deletions pkg/cmd/cli/nodeagent/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,10 @@ func (s *nodeAgentServer) run() {
s.logger.WithError(err).Fatal("Unable to create the data upload controller")
}

if err = controller.NewDataDownloadReconciler(s.mgr.GetClient(), s.kubeClient, repoEnsurer, credentialGetter, s.nodeName, s.logger).SetupWithManager(s.mgr); err != nil {
s.logger.WithError(err).Fatal("Unable to create the data download controller")
}

s.logger.Info("Controllers starting...")

if err := s.mgr.Start(ctrl.SetupSignalHandler()); err != nil {
Expand Down
16 changes: 13 additions & 3 deletions pkg/cmd/server/plugin/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@ import (
apiextensions "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"

velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
"github.com/vmware-tanzu/velero/pkg/features"

"github.com/vmware-tanzu/velero/pkg/backup"
"github.com/vmware-tanzu/velero/pkg/client"
velerodiscovery "github.com/vmware-tanzu/velero/pkg/discovery"
"github.com/vmware-tanzu/velero/pkg/features"
veleroplugin "github.com/vmware-tanzu/velero/pkg/plugin/framework"
plugincommon "github.com/vmware-tanzu/velero/pkg/plugin/framework/common"
"github.com/vmware-tanzu/velero/pkg/restore"
Expand Down Expand Up @@ -59,7 +58,8 @@ func NewCommand(f client.Factory) *cobra.Command {
RegisterRestoreItemAction("velero.io/change-pvc-node-selector", newChangePVCNodeSelectorItemAction(f)).
RegisterRestoreItemAction("velero.io/apiservice", newAPIServiceRestoreItemAction).
RegisterRestoreItemAction("velero.io/admission-webhook-configuration", newAdmissionWebhookConfigurationAction).
RegisterRestoreItemAction("velero.io/secret", newSecretRestoreItemAction(f))
RegisterRestoreItemAction("velero.io/secret", newSecretRestoreItemAction(f)).
RegisterRestoreItemAction("velero.io/dataupload", newDataUploadRetrieveAction(f))
if !features.IsEnabled(velerov1api.APIGroupVersionsFeatureFlag) {
// Do not register crd-remap-version BIA if the API Group feature flag is enabled, so that the v1 CRD can be backed up
pluginServer = pluginServer.RegisterBackupItemAction("velero.io/crd-remap-version", newRemapCRDVersionAction(f))
Expand Down Expand Up @@ -245,3 +245,13 @@ func newSecretRestoreItemAction(f client.Factory) plugincommon.HandlerInitialize
return restore.NewSecretAction(logger, client), nil
}
}

func newDataUploadRetrieveAction(f client.Factory) plugincommon.HandlerInitializer {
return func(logger logrus.FieldLogger) (interface{}, error) {
client, err := f.KubeClient()
if err != nil {
return nil, err
}
return restore.NewDataUploadRetrieveAction(logger, client.CoreV1().ConfigMaps(f.Namespace())), nil
}
}
2 changes: 2 additions & 0 deletions pkg/cmd/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,7 @@ High priorities:
- VolumeSnapshotContents are needed as they contain the handle to the volume snapshot in the
storage provider
- VolumeSnapshots are needed to create PVCs using the VolumeSnapshot as their data source.
- DataUploads need to restore before PVC for Snapshot DataMover to work, because PVC needs the DataUploadResults to create DataDownloads.
- PVs go before PVCs because PVCs depend on them.
- PVCs go before pods or controllers so they can be mounted as volumes.
- Service accounts go before secrets so service account token secrets can be filled automatically.
Expand Down Expand Up @@ -551,6 +552,7 @@ var defaultRestorePriorities = restore.Priorities{
"volumesnapshotclass.snapshot.storage.k8s.io",
"volumesnapshotcontents.snapshot.storage.k8s.io",
"volumesnapshots.snapshot.storage.k8s.io",
"datauploads.velero.io",
"persistentvolumes",
"persistentvolumeclaims",
"serviceaccounts",
Expand Down
Loading

0 comments on commit ec4bb42

Please sign in to comment.