From fd1c43188fe19947868921978a4defe1d66540c6 Mon Sep 17 00:00:00 2001 From: Divyen Patel Date: Tue, 31 May 2022 12:46:46 -0700 Subject: [PATCH] protect migrated volume from vm deletion --- go.mod | 4 +-- go.sum | 4 +++ ...vmware.com_cnsvspherevolumemigrations.yaml | 3 ++ pkg/apis/migration/migration.go | 36 +++++++++++++++++++ pkg/apis/migration/v1alpha1/types.go | 2 ++ pkg/common/cns-lib/volume/manager.go | 27 ++++++++++++++ pkg/csi/service/vanilla/controller.go | 5 +++ 7 files changed, 79 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 28b3618c24..282091155d 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/fsnotify/fsnotify v1.4.9 github.com/golang/protobuf v1.5.2 - github.com/google/uuid v1.2.0 + github.com/google/uuid v1.3.0 github.com/kubernetes-csi/csi-lib-utils v0.7.0 github.com/kubernetes-csi/csi-proxy/client v1.0.1 github.com/kubernetes-csi/external-snapshotter/client/v4 v4.1.0 @@ -21,7 +21,7 @@ require ( github.com/spf13/viper v1.7.1 github.com/stretchr/testify v1.7.0 github.com/vmware-tanzu/vm-operator-api v0.1.4-0.20211202183846-992b48c128ae - github.com/vmware/govmomi v0.27.4 + github.com/vmware/govmomi v0.28.1-0.20220601190818-0f1f07eeac53 go.uber.org/zap v1.17.0 golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 diff --git a/go.sum b/go.sum index 6e3f5d1f41..6ea043a50e 100644 --- a/go.sum +++ b/go.sum @@ -341,6 +341,8 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I= @@ -691,6 +693,8 @@ github.com/vmware-tanzu/vm-operator-api v0.1.4-0.20211202183846-992b48c128ae/go. github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= github.com/vmware/govmomi v0.27.4 h1:5kY8TAkhB20lsjzrjE073eRb8+HixBI29PVMG5lxq6I= github.com/vmware/govmomi v0.27.4/go.mod h1:daTuJEcQosNMXYJOeku0qdBJP9SOLLWB3Mqz8THtv6o= +github.com/vmware/govmomi v0.28.1-0.20220601190818-0f1f07eeac53 h1:cnB9l4P3oFzDr7WkCwfSdeRXdhetlf/nyD6bDzIbKj8= +github.com/vmware/govmomi v0.28.1-0.20220601190818-0f1f07eeac53/go.mod h1:F7adsVewLNHsW/IIm7ziFURaXDaHEwcc+ym4r3INMdY= github.com/vmware/vmw-guestinfo v0.0.0-20170707015358-25eff159a728/go.mod h1:x9oS4Wk2s2u4tS29nEaDLdzvuHdB19CvSGJjPgkZJNk= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= diff --git a/pkg/apis/migration/config/cns.vmware.com_cnsvspherevolumemigrations.yaml b/pkg/apis/migration/config/cns.vmware.com_cnsvspherevolumemigrations.yaml index 9a0e8f25da..9716e5f415 100644 --- a/pkg/apis/migration/config/cns.vmware.com_cnsvspherevolumemigrations.yaml +++ b/pkg/apis/migration/config/cns.vmware.com_cnsvspherevolumemigrations.yaml @@ -45,6 +45,9 @@ spec: volumepath: description: VolumePath is the vmdk path of the vSphere Volume type: string + protectvolumefromvmdelete: + description: protect volume from vm deletion after vmdk is migrated to CSI + type: boolean required: - volumeid - volumepath diff --git a/pkg/apis/migration/migration.go b/pkg/apis/migration/migration.go index bac91eda81..9532538091 100644 --- a/pkg/apis/migration/migration.go +++ b/pkg/apis/migration/migration.go @@ -73,6 +73,10 @@ type VolumeMigrationService interface { // DeleteVolumeInfo helps delete mapping of volumePath to VolumeID for // specified volumeID. DeleteVolumeInfo(ctx context.Context, volumeID string) error + + // ProtectVolumeFromVMDeletion sets keepAfterDeleteVm control flag on the migrated volume + // Returns an error if not able to set keepAfterDeleteVm control flag on the volume + ProtectVolumeFromVMDeletion(ctx context.Context, volumeID string) error } // volumeMigration holds migrated volume information and provides functionality @@ -235,6 +239,38 @@ func (volumeMigration *volumeMigration) GetVolumeID(ctx context.Context, volumeS return "", ErrVolumeIDNotFound } +// ProtectVolumeFromVMDeletion sets keepAfterDeleteVm control flag on the migrated volume +// Returns an error if not able to set keepAfterDeleteVm control flag on the volume +func (volumeMigration *volumeMigration) ProtectVolumeFromVMDeletion(ctx context.Context, volumeID string) error { + log := logger.GetLogger(ctx) + volumeMigrationResource := &migrationv1alpha1.CnsVSphereVolumeMigration{} + var err error + err = volumeMigration.k8sClient.Get(ctx, client.ObjectKey{Name: volumeID}, volumeMigrationResource) + if err != nil { + log.Errorf("error happened while getting CR for volumeMigration for VolumeID: %q, err: %v", volumeID, err) + return err + } + if !volumeMigrationResource.Spec.ProtectVolumeFromVMDelete { + log.Infof("Set keepAfterDeleteVm control flag using Vslm APIs") + err = (*volumeMigration.volumeManager).ProtectVolumeFromVMDeletion(ctx, volumeID) + if err != nil { + return err + } + } else { + log.Infof("migrated volume with ID: %q is already protected from vm deletion", volumeID) + return nil + } + log.Infof("Migrated Volume with ID: %q is protected from VM deletion", volumeID) + volumeMigrationResource.Spec.ProtectVolumeFromVMDelete = true + err = volumeMigration.k8sClient.Update(ctx, volumeMigrationResource) + if err != nil { + log.Errorf("error happened while updating volumeMigration CR to set ProtectVolumeFromVMDelete true "+ + "for VolumeID: %q, err: %v", volumeID, err) + return err + } + return nil +} + // GetVolumePath returns VolumePath for given VolumeID. // Returns an error if not able to retrieve VolumePath. func (volumeMigration *volumeMigration) GetVolumePath(ctx context.Context, volumeID string) (string, error) { diff --git a/pkg/apis/migration/v1alpha1/types.go b/pkg/apis/migration/v1alpha1/types.go index c37e8d6aac..6b0539665a 100644 --- a/pkg/apis/migration/v1alpha1/types.go +++ b/pkg/apis/migration/v1alpha1/types.go @@ -37,6 +37,8 @@ type CnsVSphereVolumeMigrationSpec struct { VolumePath string `json:"volumepath"` // VolumeID is the FCD ID obtained after register volume with CNS. VolumeID string `json:"volumeid"` + // ProtectVolumeFromVMDelete true means migrated volumes is protected from Node VM deletion + ProtectVolumeFromVMDelete bool `json:"protectvolumefromvmdelete"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/pkg/common/cns-lib/volume/manager.go b/pkg/common/cns-lib/volume/manager.go index e8126b35f0..3f4406f74e 100644 --- a/pkg/common/cns-lib/volume/manager.go +++ b/pkg/common/cns-lib/volume/manager.go @@ -109,6 +109,8 @@ type Manager interface { RegisterDisk(ctx context.Context, path string, name string) (string, error) // RetrieveVStorageObject helps in retreiving virtual disk information for a given volume id. RetrieveVStorageObject(ctx context.Context, volumeID string) (*vim25types.VStorageObject, error) + // ProtectVolumeFromVMDeletion sets keepAfterDeleteVm control flag on migrated volume + ProtectVolumeFromVMDeletion(ctx context.Context, volumeID string) error // CreateSnapshot helps create a snapshot for a block volume CreateSnapshot(ctx context.Context, volumeID string, desc string) (*CnsSnapshotInfo, error) // DeleteSnapshot helps delete a snapshot for a block volume @@ -2260,3 +2262,28 @@ func (m *defaultManager) DeleteSnapshot(ctx context.Context, volumeID string, sn } return err } + +// ProtectVolumeFromVMDeletion helps set keepAfterDeleteVm control flag for given volumeID +func (m *defaultManager) ProtectVolumeFromVMDeletion(ctx context.Context, volumeID string) error { + log := logger.GetLogger(ctx) + err := validateManager(ctx, m) + if err != nil { + log.Errorf("failed to validate volume manager with err: %+v", err) + return err + } + // Set up the VC connection + err = m.virtualCenter.ConnectVslm(ctx) + if err != nil { + log.Errorf("ConnectVslm failed with err: %+v", err) + return err + } + globalObjectManager := vslm.NewGlobalObjectManager(m.virtualCenter.VslmClient) + err = globalObjectManager.SetControlFlags(ctx, vim25types.ID{Id: volumeID}, []string{ + string(vim25types.VslmVStorageObjectControlFlagKeepAfterDeleteVm)}) + if err != nil { + log.Errorf("failed to set control flag keepAfterDeleteVm for volumeID %q with err: %v", volumeID, err) + return err + } + log.Infof("Successfully set keepAfterDeleteVm control flag for volumeID: %q", volumeID) + return nil +} diff --git a/pkg/csi/service/vanilla/controller.go b/pkg/csi/service/vanilla/controller.go index 633f64e0f9..6b33100a3b 100644 --- a/pkg/csi/service/vanilla/controller.go +++ b/pkg/csi/service/vanilla/controller.go @@ -1072,6 +1072,11 @@ func (c *controller) ControllerPublishVolume(ctx context.Context, req *csi.Contr return nil, csifault.CSIInternalFault, logger.LogNewErrorCodef(log, codes.Internal, "failed to get VolumeID from volumeMigrationService for volumePath: %q", volumePath) } + err = volumeMigrationService.ProtectVolumeFromVMDeletion(ctx, req.VolumeId) + if err != nil { + return nil, csifault.CSIInternalFault, logger.LogNewErrorCodef(log, codes.Internal, + "failed to set keepAfterDeleteVm control flag for VolumeID %q", req.VolumeId) + } } var node *cnsvsphere.VirtualMachine if commonco.ContainerOrchestratorUtility.IsFSSEnabled(ctx, common.UseCSINodeId) {