Skip to content

Commit

Permalink
Delete PVC and PV from destination namespace when the plan is archived
Browse files Browse the repository at this point in the history
Signed-off-by: Bella Khizgiyaev <[email protected]>
  • Loading branch information
bkhizgiy committed Oct 3, 2023
1 parent 1760225 commit 53a2b98
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 50 deletions.
1 change: 1 addition & 0 deletions pkg/controller/plan/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
91 changes: 41 additions & 50 deletions pkg/controller/plan/kubevirt.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1848,48 +1838,47 @@ 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
func (r *KubeVirt) CreatePvForNfs() (err error) {
sourceProvider := r.Source.Provider
splitted := strings.Split(sourceProvider.Spec.URL, ":")
Expand All @@ -1900,20 +1889,22 @@ 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 {
r.Log.Info("The PV for OVA NFS exists", "PV", pvName)
return
}

labels := map[string]string{"providerName": r.Plan.Provider.Source.Name, "app": "forklift", "migration": r.Migration.Name, "plan": r.Plan.Name}
pv := &core.PersistentVolume{
ObjectMeta: meta.ObjectMeta{
Name: pvName,
// OwnerReferences: []meta.OwnerReference{ownerReference},
Name: pvName,
Labels: labels,
},
Spec: core.PersistentVolumeSpec{
Capacity: core.ResourceList{
Expand All @@ -1938,10 +1929,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 {
Expand All @@ -1950,12 +1941,13 @@ 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)
labels := map[string]string{"providerName": r.Plan.Provider.Source.Name, "app": "forklift", "migration": r.Migration.Name, "plan": r.Plan.Name}
pvc := &core.PersistentVolumeClaim{
ObjectMeta: meta.ObjectMeta{
Name: pvcName,
Namespace: r.Plan.Spec.TargetNamespace,
// OwnerReferences: []meta.OwnerReference{ownerReference},
Labels: labels,
},
Spec: core.PersistentVolumeClaimSpec{
Resources: core.ResourceRequirements{
Expand All @@ -1976,30 +1968,29 @@ 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
}
if err = wait.PollUntilContextTimeout(context.TODO(), 5*time.Second, 15*time.Second, true, func(ctx context.Context) (done bool, err 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

}); err != nil {
r.Log.Error(err, "Failed to bound OVA PVC to PV ")
return

}
return nil
}

// Ensure the PV exist on the destination.
Expand Down
36 changes: 36 additions & 0 deletions pkg/controller/plan/migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -336,6 +337,41 @@ 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 {
r.Log.Error(err, "Failed to get the plan PVC")
return
}
// The PVC was alredy deleted
if pvc == nil {
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 {
r.Log.Error(err, "Failed to get the plan PV")
return
}
// The PV was alredy deleted
if pv == nil {
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 {
Expand Down
4 changes: 4 additions & 0 deletions pkg/controller/provider/ova-setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,13 @@ func (r *Reconciler) createPvForNfs(provider *api.Provider, ctx context.Context,
}
nfsServer := splitted[0]
nfsPath := splitted[1]
labels := map[string]string{"providerName": provider.Name, "app": "forklift"}

pv := &core.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{
Name: pvName,
OwnerReferences: []metav1.OwnerReference{ownerReference},
Labels: labels,
},
Spec: core.PersistentVolumeSpec{
Capacity: core.ResourceList{
Expand All @@ -95,11 +97,13 @@ func (r *Reconciler) createPvForNfs(provider *api.Provider, ctx context.Context,

func (r *Reconciler) createPvcForNfs(provider *api.Provider, ctx context.Context, ownerReference metav1.OwnerReference, pvName, pvcName string) (err error) {
sc := ""
labels := map[string]string{"providerName": provider.Name, "app": "forklift"}
pvc := &core.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: pvcName,
Namespace: provider.Namespace,
OwnerReferences: []metav1.OwnerReference{ownerReference},
Labels: labels,
},
Spec: core.PersistentVolumeClaimSpec{
Resources: core.ResourceRequirements{
Expand Down

0 comments on commit 53a2b98

Please sign in to comment.