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 2, 2023
1 parent 1760225 commit 6e83382
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 49 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
83 changes: 34 additions & 49 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,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
Expand All @@ -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 {
Expand All @@ -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{
Expand All @@ -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 {
Expand All @@ -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{
Expand All @@ -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) {

Check failure on line 1974 in pkg/controller/plan/kubevirt.go

View workflow job for this annotation

GitHub Actions / lint

Error return value of `wait.PollImmediateUntil` is not checked (errcheck)
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.
Expand Down
28 changes: 28 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,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 {
Expand Down

0 comments on commit 6e83382

Please sign in to comment.