From 6e833829af50b5c3157621f6b09880f8dfee9d9d Mon Sep 17 00:00:00 2001 From: Bella Khizgiyaev Date: Thu, 28 Sep 2023 18:38:58 +0300 Subject: [PATCH] Delete PVC and PV from destination namespace when the plan is archived Signed-off-by: Bella Khizgiyaev --- pkg/controller/plan/BUILD.bazel | 1 + pkg/controller/plan/kubevirt.go | 83 +++++++++++++------------------- pkg/controller/plan/migration.go | 28 +++++++++++ 3 files changed, 63 insertions(+), 49 deletions(-) diff --git a/pkg/controller/plan/BUILD.bazel b/pkg/controller/plan/BUILD.bazel index 0a233c18d..b0c7511ee 100644 --- a/pkg/controller/plan/BUILD.bazel +++ b/pkg/controller/plan/BUILD.bazel @@ -50,6 +50,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime", "//vendor/k8s.io/apimachinery/pkg/types", "//vendor/k8s.io/apimachinery/pkg/util/validation", + "//vendor/k8s.io/apimachinery/pkg/util/wait", "//vendor/k8s.io/apiserver/pkg/storage/names", "//vendor/k8s.io/client-go/kubernetes/scheme", "//vendor/kubevirt.io/api/core/v1:core", diff --git a/pkg/controller/plan/kubevirt.go b/pkg/controller/plan/kubevirt.go index b0dc61945..a55e3a387 100644 --- a/pkg/controller/plan/kubevirt.go +++ b/pkg/controller/plan/kubevirt.go @@ -21,6 +21,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" k8svalidation "k8s.io/apimachinery/pkg/util/validation" + "k8s.io/apimachinery/pkg/util/wait" cnv "kubevirt.io/api/core/v1" libvirtxml "libvirt.org/libvirt-go-xml" @@ -1340,17 +1341,6 @@ func (r *KubeVirt) podVolumeMounts(vmVolumes []cnv.Volume, configMap *core.Confi switch r.Source.Provider.Type() { case api.Ova: pvcName := fmt.Sprintf("ova-nfs-pvc-%s-%s", r.Source.Provider.Name, r.Plan.Name) - /* - TODO: set ownerReferences the PV and PVC deleted once the plan is done. - cross namespaces are not possible to be used for plan/provider ownership. - optional: PV+PVC per VM, deleted via cleanup. ownership: importer pod? DV? - ownerReference := meta.OwnerReference{ - APIVersion: "forklift.konveyor.io/v1beta1", - Kind: "Plan", - Name: r.Plan.Name, - UID: r.Plan.UID, - } - */ err = r.CreatePvForNfs() if err != nil { return @@ -1848,45 +1838,45 @@ func (r *KubeVirt) EnsurePersistentVolume(vmRef ref.Ref, persistentVolumes []cor return } -func (r *KubeVirt) getOvaPvNfs() (found bool, err error) { - pv := &core.PersistentVolume{} - err = r.Destination.Client.Get( +func GetOvaPvNfs(client client.Client, planName string, providerName string) (pv *core.PersistentVolume, found bool, err error) { + pv = &core.PersistentVolume{} + err = client.Get( context.TODO(), types.NamespacedName{ - Name: fmt.Sprintf("ova-nfs-pv-%s", r.Plan.Name), + Name: fmt.Sprintf("ova-nfs-pv-%s-%s", providerName, planName), }, pv, ) if err != nil { if k8serr.IsNotFound(err) { - return false, nil + return nil, false, nil } err = liberr.Wrap(err) return } - return true, nil + return } -func (r *KubeVirt) getOvaPvcNfs() (found bool, err error) { - pvc := &core.PersistentVolumeClaim{} - err = r.Destination.Client.Get( +func GetOvaPvcNfs(client client.Client, planName string, planNamespace string, providerName string) (pvc *core.PersistentVolumeClaim, found bool, err error) { + pvc = &core.PersistentVolumeClaim{} + err = client.Get( context.TODO(), types.NamespacedName{ - Name: fmt.Sprintf("ova-nfs-pvc-%s-%s", r.Source.Provider.Name, r.Plan.Name), - Namespace: r.Plan.Spec.TargetNamespace, + Name: fmt.Sprintf("ova-nfs-pvc-%s-%s", providerName, planName), + Namespace: planNamespace, }, pvc, ) if err != nil { if k8serr.IsNotFound(err) { - return false, nil + return nil, false, nil } err = liberr.Wrap(err) return } - return true, nil + return } // TODO if we use ownership get it to the method @@ -1900,9 +1890,10 @@ func (r *KubeVirt) CreatePvForNfs() (err error) { nfsServer := splitted[0] nfsPath := splitted[1] - pvName := fmt.Sprintf("ova-nfs-pv-%s", r.Plan.Name) - found, err := r.getOvaPvNfs() + pvName := fmt.Sprintf("ova-nfs-pv-%s-%s", r.Source.Provider.Name, r.Plan.Name) + _, found, err := GetOvaPvNfs(r.Destination.Client, r.Plan.Name, r.Plan.Provider.Source.Name) if err != nil { + r.Log.Error(err, "Failed to get ova PV") return } if found { @@ -1913,7 +1904,6 @@ func (r *KubeVirt) CreatePvForNfs() (err error) { pv := &core.PersistentVolume{ ObjectMeta: meta.ObjectMeta{ Name: pvName, - // OwnerReferences: []meta.OwnerReference{ownerReference}, }, Spec: core.PersistentVolumeSpec{ Capacity: core.ResourceList{ @@ -1938,10 +1928,10 @@ func (r *KubeVirt) CreatePvForNfs() (err error) { return } -// TODO if we use ownership get it to the method func (r *KubeVirt) CreatePvcForNfs(pvcName string) (err error) { - found, err := r.getOvaPvcNfs() + _, found, err := GetOvaPvcNfs(r.Destination.Client, r.Plan.Name, r.Plan.Spec.TargetNamespace, r.Plan.Provider.Source.Name) if err != nil { + r.Log.Error(err, "Failed to get ova PVC") return } if found { @@ -1950,12 +1940,11 @@ func (r *KubeVirt) CreatePvcForNfs(pvcName string) (err error) { } sc := "" - pvName := fmt.Sprintf("ova-nfs-pv-%s", r.Plan.Name) + pvName := fmt.Sprintf("ova-nfs-pv-%s-%s", r.Source.Provider.Name, r.Plan.Name) pvc := &core.PersistentVolumeClaim{ ObjectMeta: meta.ObjectMeta{ Name: pvcName, Namespace: r.Plan.Spec.TargetNamespace, - // OwnerReferences: []meta.OwnerReference{ownerReference}, }, Spec: core.PersistentVolumeClaimSpec{ Resources: core.ResourceRequirements{ @@ -1976,30 +1965,26 @@ func (r *KubeVirt) CreatePvcForNfs(pvcName string) (err error) { return } - // wait until pvc and pv are bounded. - timeout := time.After(5 * time.Minute) - tick := time.Tick(5 * time.Second) pvcNamespacedName := types.NamespacedName{ Namespace: r.Plan.Spec.TargetNamespace, Name: pvcName, } - for { - select { - case <-timeout: - r.Log.Error(err, "Timed out waiting for PVC to be bound") - return fmt.Errorf("timeout passed waiting for the OVA PVC %v", pvc) - case <-tick: - err = r.Get(context.TODO(), pvcNamespacedName, pvc) - if err != nil { - r.Log.Error(err, "Failed to bound OVA plan PVC") - return - } - if pvc.Status.Phase == "Bound" { - return - } + // wait until pvc and pv are bounded. + wait.PollImmediateUntil(5*time.Second, func() (bool, error) { + err := r.Get(context.TODO(), pvcNamespacedName, pvc) + if err != nil { + r.Log.Error(err, "Failed to get OVA plan PVC") + return false, err } - } + + if pvc.Status.Phase == "Bound" { + return true, nil + } + return false, nil + }, context.TODO().Done()) + + return nil } // Ensure the PV exist on the destination. diff --git a/pkg/controller/plan/migration.go b/pkg/controller/plan/migration.go index f3f060b1e..b9211e60f 100644 --- a/pkg/controller/plan/migration.go +++ b/pkg/controller/plan/migration.go @@ -12,6 +12,7 @@ import ( "strings" "time" + "github.com/konveyor/forklift-controller/pkg/apis/forklift/v1beta1" "github.com/konveyor/forklift-controller/pkg/apis/forklift/v1beta1/plan" "github.com/konveyor/forklift-controller/pkg/controller/plan/adapter" plancontext "github.com/konveyor/forklift-controller/pkg/controller/plan/context" @@ -336,6 +337,33 @@ func (r *Migration) Archive() { return } + if r.Plan.Provider.Source.Type() == v1beta1.Ova { + //delete pvc and pv + pvc, _, errPvc := GetOvaPvcNfs(r.Destination.Client, r.Plan.Name, r.Plan.Spec.TargetNamespace, r.Plan.Provider.Source.Name) + if errPvc != nil || pvc == nil { + r.Log.Error(err, "Failed to get the plan PVC") + return + } + + err = r.Destination.Client.Delete(context.TODO(), pvc) + if err != nil { + r.Log.Error(err, "Failed to delete the plan PVC") + return + } + + pv, _, errPv := GetOvaPvNfs(r.Destination.Client, r.Plan.Name, r.Plan.Provider.Source.Name) + if errPv != nil || pv == nil { + r.Log.Error(err, "Failed to get the plan PV") + return + } + + err = r.Destination.Client.Delete(context.TODO(), pv) + if err != nil { + r.Log.Error(err, "Failed to delete the plan PV") + return + } + } + for _, vm := range r.Plan.Status.Migration.VMs { err = r.CleanUp(vm) if err != nil {