Skip to content

Commit

Permalink
++
Browse files Browse the repository at this point in the history
Signed-off-by: dmitry.lopatin <[email protected]>
  • Loading branch information
LopatinDmitr committed Dec 13, 2024
1 parent c7c091c commit 13b642e
Show file tree
Hide file tree
Showing 8 changed files with 277 additions and 201 deletions.
2 changes: 1 addition & 1 deletion api/core/v1alpha2/vdcondition/condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const (
SnapshottingType Type = "Snapshotting"
// StorageClassReadyType indicates whether the storage class is ready.
StorageClassReadyType Type = "StorageClassReady"
// InUseType indicates whether the VirtualDisk is attached to a running VirtualMachine or is being used in a process of a VirtualImage creation.
// InUseType indicates whether the VirtualDisk is attached to a running VirtualMachine or is being used in a process of an image creation.
InUseType Type = "InUse"
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,9 @@ func (ds ObjectRefVirtualDisk) Validate(ctx context.Context, cvi *virtv2.Cluster
}

inUseCondition, _ := conditions.GetCondition(vdcondition.InUseType, vd.Status.Conditions)
if inUseCondition.Status == metav1.ConditionTrue && inUseCondition.Reason == vdcondition.AllowedForImageUsage.String() {
if inUseCondition.Status == metav1.ConditionTrue &&
inUseCondition.Reason == vdcondition.AllowedForImageUsage.String() &&
inUseCondition.ObservedGeneration == vd.Status.ObservedGeneration {
return nil
}

Expand Down
29 changes: 18 additions & 11 deletions images/virtualization-artifact/pkg/controller/vd/internal/inuse.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"slices"

corev1 "k8s.io/api/core/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/types"
Expand Down Expand Up @@ -71,7 +70,7 @@ func (h InUseHandler) Handle(ctx context.Context, vd *virtv2.VirtualDisk) (recon
for _, vm := range vms.Items {
if h.isVDAttachedToVM(vd.GetName(), vm) {
if vm.Status.Phase != virtv2.MachineStopped {
allowUseForVM = isVMReady(vm.Status.Conditions)
allowUseForVM = isVMCanStart(vm.Status.Conditions)

if allowUseForVM {
break
Expand All @@ -92,7 +91,7 @@ func (h InUseHandler) Handle(ctx context.Context, vd *virtv2.VirtualDisk) (recon
Namespace: vm.GetNamespace(),
LabelSelector: labels.SelectorFromSet(map[string]string{virtv1.VirtualMachineNameLabel: vm.GetName()}),
})
if err != nil && !k8serrors.IsNotFound(err) {
if err != nil {
return reconcile.Result{}, fmt.Errorf("unable to list virt-launcher Pod for VM %q: %w", vm.GetName(), err)
}

Expand All @@ -117,7 +116,11 @@ func (h InUseHandler) Handle(ctx context.Context, vd *virtv2.VirtualDisk) (recon
allowedPhases := []virtv2.ImagePhase{virtv2.ImageProvisioning, virtv2.ImagePending}

for _, vi := range vis.Items {
if slices.Contains(allowedPhases, vi.Status.Phase) && vi.Spec.DataSource.Type == virtv2.DataSourceTypeObjectRef && vi.Spec.DataSource.ObjectRef != nil && vi.Spec.DataSource.ObjectRef.Kind == virtv2.VirtualDiskKind {
if slices.Contains(allowedPhases, vi.Status.Phase) &&
vi.Spec.DataSource.Type == virtv2.DataSourceTypeObjectRef &&
vi.Spec.DataSource.ObjectRef != nil &&
vi.Spec.DataSource.ObjectRef.Kind == virtv2.VirtualDiskKind &&
vi.Spec.DataSource.ObjectRef.Name == vd.Name {
allowUseForImage = true
break
}
Expand All @@ -129,13 +132,16 @@ func (h InUseHandler) Handle(ctx context.Context, vd *virtv2.VirtualDisk) (recon
return reconcile.Result{}, fmt.Errorf("error getting cluster virtual images: %w", err)
}
for _, cvi := range cvis.Items {
if slices.Contains(allowedPhases, cvi.Status.Phase) && cvi.Spec.DataSource.Type == virtv2.DataSourceTypeObjectRef && cvi.Spec.DataSource.ObjectRef != nil && cvi.Spec.DataSource.ObjectRef.Kind == virtv2.VirtualDiskKind {
if slices.Contains(allowedPhases, cvi.Status.Phase) &&
cvi.Spec.DataSource.Type == virtv2.DataSourceTypeObjectRef &&
cvi.Spec.DataSource.ObjectRef != nil &&
cvi.Spec.DataSource.ObjectRef.Kind == virtv2.VirtualDiskKind &&
cvi.Spec.DataSource.ObjectRef.Name == vd.Name {
allowUseForImage = true
}
}

cb := conditions.NewConditionBuilder(vdcondition.InUseType)

switch {
case allowUseForVM && inUseCondition.Status == metav1.ConditionUnknown:
if inUseCondition.Reason != vdcondition.AllowedForVirtualMachineUsage.String() {
Expand All @@ -156,19 +162,20 @@ func (h InUseHandler) Handle(ctx context.Context, vd *virtv2.VirtualDisk) (recon
conditions.SetCondition(cb, &vd.Status.Conditions)
}
default:
needChange := false
setUnknown := false

if inUseCondition.Reason == vdcondition.AllowedForVirtualMachineUsage.String() && !allowUseForVM {
needChange = true
setUnknown = true
}

if inUseCondition.Reason == vdcondition.AllowedForImageUsage.String() && !allowUseForImage {
needChange = true
setUnknown = true
}

if needChange {
if setUnknown {
cb.Generation(vd.Generation).Status(metav1.ConditionUnknown).Reason(conditions.ReasonUnknown).Message("")
conditions.SetCondition(cb, &vd.Status.Conditions)
return reconcile.Result{Requeue: true}, nil
}
}

Expand All @@ -185,7 +192,7 @@ func (h InUseHandler) isVDAttachedToVM(vdName string, vm virtv2.VirtualMachine)
return false
}

func isVMReady(conditions []metav1.Condition) bool {
func isVMCanStart(conditions []metav1.Condition) bool {
critConditions := []string{
vmcondition.TypeIPAddressReady.String(),
vmcondition.TypeClassReady.String(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ package internal
import (
"context"

"github.com/onsi/ginkgo/v2"
"github.com/onsi/gomega"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
Expand All @@ -34,24 +34,24 @@ import (
"github.com/deckhouse/virtualization/api/core/v1alpha2/vmcondition"
)

var _ = ginkgo.Describe("InUseHandler", func() {
var _ = Describe("InUseHandler", func() {
var (
scheme *runtime.Scheme
ctx context.Context
handler *InUseHandler
)

ginkgo.BeforeEach(func() {
BeforeEach(func() {
scheme = runtime.NewScheme()
gomega.Expect(clientgoscheme.AddToScheme(scheme)).To(gomega.Succeed())
gomega.Expect(virtv2.AddToScheme(scheme)).To(gomega.Succeed())
gomega.Expect(virtv1.AddToScheme(scheme)).To(gomega.Succeed())
Expect(clientgoscheme.AddToScheme(scheme)).To(Succeed())
Expect(virtv2.AddToScheme(scheme)).To(Succeed())
Expect(virtv1.AddToScheme(scheme)).To(Succeed())

ctx = context.TODO()
})

ginkgo.Context("when VirtualDisk is not in use", func() {
ginkgo.It("must set status Unknown and reason Unknown", func() {
Context("when VirtualDisk is not in use", func() {
It("must set status Unknown and reason Unknown", func() {
vd := &virtv2.VirtualDisk{
ObjectMeta: metav1.ObjectMeta{
Name: "test-vd",
Expand All @@ -66,17 +66,17 @@ var _ = ginkgo.Describe("InUseHandler", func() {
handler = NewInUseHandler(k8sClient)

result, err := handler.Handle(ctx, vd)
gomega.Expect(err).ToNot(gomega.HaveOccurred())
gomega.Expect(result).To(gomega.Equal(ctrl.Result{}))
Expect(err).ToNot(HaveOccurred())
Expect(result).To(Equal(ctrl.Result{}))

cond, _ := conditions.GetCondition(vdcondition.InUseType, vd.Status.Conditions)
gomega.Expect(cond).ToNot(gomega.BeNil())
gomega.Expect(cond.Status).To(gomega.Equal(metav1.ConditionUnknown))
Expect(cond).ToNot(BeNil())
Expect(cond.Status).To(Equal(metav1.ConditionUnknown))
})
})

ginkgo.Context("when VirtualDisk is used by running VirtualMachine", func() {
ginkgo.It("must set status True and reason AllowedForVirtualMachineUsage", func() {
Context("when VirtualDisk is used by running VirtualMachine", func() {
It("must set status True and reason AllowedForVirtualMachineUsage", func() {
vd := &virtv2.VirtualDisk{
ObjectMeta: metav1.ObjectMeta{
Name: "test-vd",
Expand Down Expand Up @@ -115,18 +115,18 @@ var _ = ginkgo.Describe("InUseHandler", func() {
handler = NewInUseHandler(k8sClient)

result, err := handler.Handle(ctx, vd)
gomega.Expect(err).ToNot(gomega.HaveOccurred())
gomega.Expect(result).To(gomega.Equal(ctrl.Result{}))
Expect(err).ToNot(HaveOccurred())
Expect(result).To(Equal(ctrl.Result{}))

cond, _ := conditions.GetCondition(vdcondition.InUseType, vd.Status.Conditions)
gomega.Expect(cond).ToNot(gomega.BeNil())
gomega.Expect(cond.Status).To(gomega.Equal(metav1.ConditionTrue))
gomega.Expect(cond.Reason).To(gomega.Equal(vdcondition.AllowedForVirtualMachineUsage.String()))
Expect(cond).ToNot(BeNil())
Expect(cond.Status).To(Equal(metav1.ConditionTrue))
Expect(cond.Reason).To(Equal(vdcondition.AllowedForVirtualMachineUsage.String()))
})
})

ginkgo.Context("when VirtualDisk is used by not ready VirtualMachine", func() {
ginkgo.It("must set status True and reason AllowedForVirtualMachineUsage", func() {
Context("when VirtualDisk is used by not ready VirtualMachine", func() {
It("it sets Unknown", func() {
vd := &virtv2.VirtualDisk{
ObjectMeta: metav1.ObjectMeta{
Name: "test-vd",
Expand Down Expand Up @@ -166,17 +166,17 @@ var _ = ginkgo.Describe("InUseHandler", func() {
handler = NewInUseHandler(k8sClient)

result, err := handler.Handle(ctx, vd)
gomega.Expect(err).ToNot(gomega.HaveOccurred())
gomega.Expect(result).To(gomega.Equal(ctrl.Result{}))
Expect(err).ToNot(HaveOccurred())
Expect(result).To(Equal(ctrl.Result{}))

cond, _ := conditions.GetCondition(vdcondition.InUseType, vd.Status.Conditions)
gomega.Expect(cond).ToNot(gomega.BeNil())
gomega.Expect(cond.Status).To(gomega.Equal(metav1.ConditionUnknown))
Expect(cond).ToNot(BeNil())
Expect(cond.Status).To(Equal(metav1.ConditionUnknown))
})
})

ginkgo.Context("when VirtualDisk is used by VirtualImage", func() {
ginkgo.It("must set status True and reason AllowedForImageUsage", func() {
Context("when VirtualDisk is used by VirtualImage", func() {
It("must set status True and reason AllowedForImageUsage", func() {
vd := &virtv2.VirtualDisk{
ObjectMeta: metav1.ObjectMeta{
Name: "test-vd",
Expand Down Expand Up @@ -211,18 +211,18 @@ var _ = ginkgo.Describe("InUseHandler", func() {
handler = NewInUseHandler(k8sClient)

result, err := handler.Handle(ctx, vd)
gomega.Expect(err).ToNot(gomega.HaveOccurred())
gomega.Expect(result).To(gomega.Equal(ctrl.Result{}))
Expect(err).ToNot(HaveOccurred())
Expect(result).To(Equal(ctrl.Result{}))

cond, _ := conditions.GetCondition(vdcondition.InUseType, vd.Status.Conditions)
gomega.Expect(cond).ToNot(gomega.BeNil())
gomega.Expect(cond.Status).To(gomega.Equal(metav1.ConditionTrue))
gomega.Expect(cond.Reason).To(gomega.Equal(vdcondition.AllowedForImageUsage.String()))
Expect(cond).ToNot(BeNil())
Expect(cond.Status).To(Equal(metav1.ConditionTrue))
Expect(cond.Reason).To(Equal(vdcondition.AllowedForImageUsage.String()))
})
})

ginkgo.Context("when VirtualDisk is used by ClusterVirtualImage", func() {
ginkgo.It("must set status True and reason AllowedForImageUsage", func() {
Context("when VirtualDisk is used by ClusterVirtualImage", func() {
It("must set status True and reason AllowedForImageUsage", func() {
vd := &virtv2.VirtualDisk{
ObjectMeta: metav1.ObjectMeta{
Name: "test-vd",
Expand Down Expand Up @@ -258,18 +258,18 @@ var _ = ginkgo.Describe("InUseHandler", func() {
handler = NewInUseHandler(k8sClient)

result, err := handler.Handle(ctx, vd)
gomega.Expect(err).ToNot(gomega.HaveOccurred())
gomega.Expect(result).To(gomega.Equal(ctrl.Result{}))
Expect(err).ToNot(HaveOccurred())
Expect(result).To(Equal(ctrl.Result{}))

cond, _ := conditions.GetCondition(vdcondition.InUseType, vd.Status.Conditions)
gomega.Expect(cond).ToNot(gomega.BeNil())
gomega.Expect(cond.Status).To(gomega.Equal(metav1.ConditionTrue))
gomega.Expect(cond.Reason).To(gomega.Equal(vdcondition.AllowedForImageUsage.String()))
Expect(cond).ToNot(BeNil())
Expect(cond.Status).To(Equal(metav1.ConditionTrue))
Expect(cond.Reason).To(Equal(vdcondition.AllowedForImageUsage.String()))
})
})

ginkgo.Context("when VirtualDisk is used by VirtualImage and VirtualMachine", func() {
ginkgo.It("must set status True and reason AllowedForVirtualMachineUsage", func() {
Context("when VirtualDisk is used by VirtualImage and VirtualMachine", func() {
It("must set status True and reason AllowedForVirtualMachineUsage", func() {
vd := &virtv2.VirtualDisk{
ObjectMeta: metav1.ObjectMeta{
Name: "test-vd",
Expand Down Expand Up @@ -319,18 +319,18 @@ var _ = ginkgo.Describe("InUseHandler", func() {
handler = NewInUseHandler(k8sClient)

result, err := handler.Handle(ctx, vd)
gomega.Expect(err).ToNot(gomega.HaveOccurred())
gomega.Expect(result).To(gomega.Equal(ctrl.Result{}))
Expect(err).ToNot(HaveOccurred())
Expect(result).To(Equal(ctrl.Result{}))

cond, _ := conditions.GetCondition(vdcondition.InUseType, vd.Status.Conditions)
gomega.Expect(cond).ToNot(gomega.BeNil())
gomega.Expect(cond.Status).To(gomega.Equal(metav1.ConditionTrue))
gomega.Expect(cond.Reason).To(gomega.Equal(vdcondition.AllowedForVirtualMachineUsage.String()))
Expect(cond).ToNot(BeNil())
Expect(cond.Status).To(Equal(metav1.ConditionTrue))
Expect(cond.Reason).To(Equal(vdcondition.AllowedForVirtualMachineUsage.String()))
})
})

ginkgo.Context("when VirtualDisk is used by VirtualMachine after create image", func() {
ginkgo.It("must set status True and reason AllowedForVirtualMachineUsage", func() {
Context("when VirtualDisk is used by VirtualMachine after create image", func() {
It("must set status True and reason AllowedForVirtualMachineUsage", func() {
vd := &virtv2.VirtualDisk{
ObjectMeta: metav1.ObjectMeta{
Name: "test-vd",
Expand Down Expand Up @@ -366,18 +366,18 @@ var _ = ginkgo.Describe("InUseHandler", func() {
handler = NewInUseHandler(k8sClient)

result, err := handler.Handle(ctx, vd)
gomega.Expect(err).ToNot(gomega.HaveOccurred())
gomega.Expect(result).To(gomega.Equal(ctrl.Result{}))
Expect(err).ToNot(HaveOccurred())
Expect(result).To(Equal(ctrl.Result{}))

cond, _ := conditions.GetCondition(vdcondition.InUseType, vd.Status.Conditions)
gomega.Expect(cond).ToNot(gomega.BeNil())
gomega.Expect(cond.Status).To(gomega.Equal(metav1.ConditionTrue))
gomega.Expect(cond.Reason).To(gomega.Equal(vdcondition.AllowedForVirtualMachineUsage.String()))
Expect(cond).ToNot(BeNil())
Expect(cond.Status).To(Equal(metav1.ConditionTrue))
Expect(cond.Reason).To(Equal(vdcondition.AllowedForVirtualMachineUsage.String()))
})
})

ginkgo.Context("when VirtualDisk is used by VirtualImage after running VM", func() {
ginkgo.It("must set status True and reason AllowedForImageUsage", func() {
Context("when VirtualDisk is used by VirtualImage after running VM", func() {
It("must set status True and reason AllowedForImageUsage", func() {
vd := &virtv2.VirtualDisk{
ObjectMeta: metav1.ObjectMeta{
Name: "test-vd",
Expand Down Expand Up @@ -418,18 +418,18 @@ var _ = ginkgo.Describe("InUseHandler", func() {
handler = NewInUseHandler(k8sClient)

result, err := handler.Handle(ctx, vd)
gomega.Expect(err).ToNot(gomega.HaveOccurred())
gomega.Expect(result).To(gomega.Equal(ctrl.Result{}))
Expect(err).ToNot(HaveOccurred())
Expect(result).To(Equal(ctrl.Result{}))

cond, _ := conditions.GetCondition(vdcondition.InUseType, vd.Status.Conditions)
gomega.Expect(cond).ToNot(gomega.BeNil())
gomega.Expect(cond.Status).To(gomega.Equal(metav1.ConditionTrue))
gomega.Expect(cond.Reason).To(gomega.Equal(vdcondition.AllowedForImageUsage.String()))
Expect(cond).ToNot(BeNil())
Expect(cond.Status).To(Equal(metav1.ConditionTrue))
Expect(cond.Reason).To(Equal(vdcondition.AllowedForImageUsage.String()))
})
})

ginkgo.Context("when VirtualDisk is not in use after create image", func() {
ginkgo.It("must set status Unknown and reason Unknown", func() {
Context("when VirtualDisk is not in use after image creation", func() {
It("must set status Unknown and reason Unknown", func() {
vd := &virtv2.VirtualDisk{
ObjectMeta: metav1.ObjectMeta{
Name: "test-vd",
Expand All @@ -450,17 +450,17 @@ var _ = ginkgo.Describe("InUseHandler", func() {
handler = NewInUseHandler(k8sClient)

result, err := handler.Handle(ctx, vd)
gomega.Expect(err).ToNot(gomega.HaveOccurred())
gomega.Expect(result).To(gomega.Equal(ctrl.Result{}))
Expect(err).ToNot(HaveOccurred())
Expect(result).To(Equal(ctrl.Result{}))

cond, _ := conditions.GetCondition(vdcondition.InUseType, vd.Status.Conditions)
gomega.Expect(cond).ToNot(gomega.BeNil())
gomega.Expect(cond.Status).To(gomega.Equal(metav1.ConditionUnknown))
Expect(cond).ToNot(BeNil())
Expect(cond.Status).To(Equal(metav1.ConditionUnknown))
})
})

ginkgo.Context("when VirtualDisk is not in use after running VM", func() {
ginkgo.It("must set status Unknown and reason Unknown", func() {
Context("when VirtualDisk is not in use after VM deletion", func() {
It("must set status Unknown and reason Unknown", func() {
vd := &virtv2.VirtualDisk{
ObjectMeta: metav1.ObjectMeta{
Name: "test-vd",
Expand All @@ -481,12 +481,12 @@ var _ = ginkgo.Describe("InUseHandler", func() {
handler = NewInUseHandler(k8sClient)

result, err := handler.Handle(ctx, vd)
gomega.Expect(err).ToNot(gomega.HaveOccurred())
gomega.Expect(result).To(gomega.Equal(ctrl.Result{}))
Expect(err).ToNot(HaveOccurred())
Expect(result).To(Equal(ctrl.Result{}))

cond, _ := conditions.GetCondition(vdcondition.InUseType, vd.Status.Conditions)
gomega.Expect(cond).ToNot(gomega.BeNil())
gomega.Expect(cond.Status).To(gomega.Equal(metav1.ConditionUnknown))
Expect(cond).ToNot(BeNil())
Expect(cond.Status).To(Equal(metav1.ConditionUnknown))
})
})
})
Loading

0 comments on commit 13b642e

Please sign in to comment.