diff --git a/images/sds-local-volume-controller/pkg/controller/local_storage_class_watcher.go b/images/sds-local-volume-controller/pkg/controller/local_storage_class_watcher.go index 966e4d20..02a84daf 100644 --- a/images/sds-local-volume-controller/pkg/controller/local_storage_class_watcher.go +++ b/images/sds-local-volume-controller/pkg/controller/local_storage_class_watcher.go @@ -166,7 +166,11 @@ func RunLocalStorageClassWatcherController( func RunEventReconcile(ctx context.Context, cl client.Client, log logger.Logger, scList *v1.StorageClassList, lsc *v1alpha1.LocalStorageClass) (bool, error) { recType, err := identifyReconcileFunc(scList, lsc) if err != nil { - log.Error(err, fmt.Sprintf("[runEventReconcile] unable to identify reconcile func for the LocalStorageClass %s", lsc.Name)) + upError := updateLocalStorageClassPhase(ctx, cl, lsc, FailedStatusPhase, err.Error()) + if upError != nil { + upError = fmt.Errorf("[runEventReconcile] unable to update the LocalStorageClass %s status: %w", lsc.Name, upError) + err = errors.Join(err, upError) + } return true, err } diff --git a/images/sds-local-volume-controller/pkg/controller/local_storage_class_watcher_func.go b/images/sds-local-volume-controller/pkg/controller/local_storage_class_watcher_func.go index 312ac3ce..0db6dd46 100644 --- a/images/sds-local-volume-controller/pkg/controller/local_storage_class_watcher_func.go +++ b/images/sds-local-volume-controller/pkg/controller/local_storage_class_watcher_func.go @@ -228,7 +228,7 @@ func shouldReconcileByUpdateFunc(scList *v1.StorageClassList, lsc *v1alpha1.Loca return false, nil } else { - err := fmt.Errorf("a storage class %s does not belong to %s provisioner", sc.Name, LocalStorageClassProvisioner) + err := fmt.Errorf("a storage class %s already exists and does not belong to %s provisioner", sc.Name, LocalStorageClassProvisioner) return false, err } } @@ -473,6 +473,10 @@ func updateLocalStorageClassPhase( lsc.Status.Phase = phase lsc.Status.Reason = reason + if !slices.Contains(lsc.Finalizers, LocalStorageClassFinalizerName) { + lsc.Finalizers = append(lsc.Finalizers, LocalStorageClassFinalizerName) + } + // TODO: add retry logic err := cl.Update(ctx, lsc) if err != nil { diff --git a/images/sds-local-volume-controller/pkg/controller/local_storage_class_watcher_test.go b/images/sds-local-volume-controller/pkg/controller/local_storage_class_watcher_test.go index 6bd8cae8..a0a2bcd8 100644 --- a/images/sds-local-volume-controller/pkg/controller/local_storage_class_watcher_test.go +++ b/images/sds-local-volume-controller/pkg/controller/local_storage_class_watcher_test.go @@ -29,6 +29,7 @@ import ( corev1 "k8s.io/api/core/v1" v1 "k8s.io/api/storage/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/resource" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -55,29 +56,33 @@ var _ = Describe(controller.LocalStorageClassCtrlName, func() { cl = NewFakeClient() log = logger.Logger{} - reclaimPolicyDelete = string(corev1.PersistentVolumeReclaimDelete) + reclaimPolicyDelete = string(corev1.PersistentVolumeReclaimDelete) + reclaimPolicyRetain = string(corev1.PersistentVolumeReclaimRetain) + volumeBindingModeWFFC = string(v1.VolumeBindingWaitForFirstConsumer) + volumeBindingModeIM = string(v1.VolumeBindingImmediate) existingThickLVG1Template = generateLVMVolumeGroup(existingThickLVG1Name, []string{"dev-1111", "dev-2222"}, []string{}) existingThickLVG2Template = generateLVMVolumeGroup(existingThickLVG2Name, []string{"dev-3333", "dev-4444"}, []string{}) newThickLVGTemplate = generateLVMVolumeGroup(newThickLVGName, []string{"dev-5555", "dev-6666"}, []string{}) - // existingThinLVG1Template = generateLVMVolumeGroup(existingThinLVG1Name, []string{"dev-7777", "dev-8888"}, []string{"thin-pool-1", "thin-pool-2"}) - // existingThinLVG2Template = generateLVMVolumeGroup(existingThinLVG2Name, []string{"dev-9999", "dev-1010"}, []string{"thin-pool-3", "thin-pool-4"}) - // newThinLVGTemplate = generateLVMVolumeGroup(newThinLVGName, []string{"dev-1111", "dev-1212"}, []string{"thin-pool-5", "thin-pool-6"}) + existingThinLVG1Template = generateLVMVolumeGroup(existingThinLVG1Name, []string{"dev-7777", "dev-8888"}, []string{"thin-pool-1", "thin-pool-2"}) + existingThinLVG2Template = generateLVMVolumeGroup(existingThinLVG2Name, []string{"dev-9999", "dev-1010"}, []string{"thin-pool-1", "thin-pool-2"}) + // newThinLVGTemplate = generateLVMVolumeGroup(newThinLVGName, []string{"dev-1111", "dev-1212"}, []string{"thin-pool-1", "thin-pool-2"}) ) It("Create_local_sc_with_existing_lvgs", func() { + lvgSpec := []v1alpha1.LocalStorageClassLVG{ + {Name: existingThickLVG1Name}, + {Name: existingThickLVG2Name}, + } + err := cl.Create(ctx, existingThickLVG1Template) Expect(err).NotTo(HaveOccurred()) err = cl.Create(ctx, existingThickLVG2Template) Expect(err).NotTo(HaveOccurred()) - lvgSpec := []v1alpha1.LocalStorageClassLVG{ - {Name: existingThickLVG1Name}, - {Name: existingThickLVG2Name}, - } lscTemplate := generateLocalStorageClass(nameForLocalStorageClass, reclaimPolicyDelete, volumeBindingModeWFFC, controller.LVMThickType, lvgSpec) err = cl.Create(ctx, lscTemplate) @@ -111,6 +116,12 @@ var _ = Describe(controller.LocalStorageClassCtrlName, func() { }) It("Update_local_sc_add_existing_vg", func() { + lvgSpec := []v1alpha1.LocalStorageClassLVG{ + {Name: existingThickLVG1Name}, + {Name: existingThickLVG2Name}, + {Name: newThickLVGName}, + } + err := cl.Create(ctx, newThickLVGTemplate) Expect(err).NotTo(HaveOccurred()) @@ -118,12 +129,43 @@ var _ = Describe(controller.LocalStorageClassCtrlName, func() { err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, lsc) Expect(err).NotTo(HaveOccurred()) + lsc.Spec.LVM.LVMVolumeGroups = append(lsc.Spec.LVM.LVMVolumeGroups, v1alpha1.LocalStorageClassLVG{Name: newThickLVGName}) + + err = cl.Update(ctx, lsc) + Expect(err).NotTo(HaveOccurred()) + + scList := &v1.StorageClassList{} + err = cl.List(ctx, scList) + Expect(err).NotTo(HaveOccurred()) + + shouldRequeue, err := controller.RunEventReconcile(ctx, cl, log, scList, lsc) + Expect(err).NotTo(HaveOccurred()) + Expect(shouldRequeue).To(BeFalse()) + + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, lsc) + Expect(err).NotTo(HaveOccurred()) + Expect(lsc.Finalizers).To(HaveLen(1)) + Expect(lsc.Finalizers).To(ContainElement(controller.LocalStorageClassFinalizerName)) + Expect(lsc.Spec.LVM.LVMVolumeGroups).To(Equal(lvgSpec)) + Expect(lsc.Status.Phase).To(Equal(controller.CreatedStatusPhase)) + + sc := &v1.StorageClass{} + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, sc) + Expect(err).NotTo(HaveOccurred()) + performStandartChecksForSC(sc, lvgSpec, nameForLocalStorageClass, controller.LocalStorageClassLvmType, controller.LVMThickType, reclaimPolicyDelete, volumeBindingModeWFFC) + }) + + It("Update_local_sc_remove_existing_vg", func() { lvgSpec := []v1alpha1.LocalStorageClassLVG{ {Name: existingThickLVG1Name}, {Name: existingThickLVG2Name}, - {Name: newThickLVGName}, } - lsc.Spec.LVM.LVMVolumeGroups = append(lsc.Spec.LVM.LVMVolumeGroups, v1alpha1.LocalStorageClassLVG{Name: newThickLVGName}) + + lsc := &v1alpha1.LocalStorageClass{} + err := cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, lsc) + Expect(err).NotTo(HaveOccurred()) + + lsc.Spec.LVM.LVMVolumeGroups = delFromSlice(lsc.Spec.LVM.LVMVolumeGroups, newThickLVGName) err = cl.Update(ctx, lsc) Expect(err).NotTo(HaveOccurred()) @@ -149,16 +191,132 @@ var _ = Describe(controller.LocalStorageClassCtrlName, func() { performStandartChecksForSC(sc, lvgSpec, nameForLocalStorageClass, controller.LocalStorageClassLvmType, controller.LVMThickType, reclaimPolicyDelete, volumeBindingModeWFFC) }) - It("Update_local_sc_remove_existing_vg", func() { + It("Update_local_sc_add_non_existing_vg", func() { + lvgSpecOld := []v1alpha1.LocalStorageClassLVG{ + {Name: existingThickLVG1Name}, + {Name: existingThickLVG2Name}, + } + + lvgSpec := []v1alpha1.LocalStorageClassLVG{ + {Name: existingThickLVG1Name}, + {Name: existingThickLVG2Name}, + {Name: nonExistentLVG1Name}, + } + lsc := &v1alpha1.LocalStorageClass{} err := cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, lsc) Expect(err).NotTo(HaveOccurred()) + lsc.Spec.LVM.LVMVolumeGroups = append(lsc.Spec.LVM.LVMVolumeGroups, v1alpha1.LocalStorageClassLVG{Name: nonExistentLVG1Name}) + + err = cl.Update(ctx, lsc) + Expect(err).NotTo(HaveOccurred()) + + scList := &v1.StorageClassList{} + err = cl.List(ctx, scList) + Expect(err).NotTo(HaveOccurred()) + + shouldRequeue, err := controller.RunEventReconcile(ctx, cl, log, scList, lsc) + Expect(err).To(HaveOccurred()) + Expect(shouldRequeue).To(BeTrue()) + + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, lsc) + Expect(err).NotTo(HaveOccurred()) + Expect(lsc.Finalizers).To(HaveLen(1)) + Expect(lsc.Finalizers).To(ContainElement(controller.LocalStorageClassFinalizerName)) + Expect(lsc.Spec.LVM.LVMVolumeGroups).To(Equal(lvgSpec)) + Expect(lsc.Status.Phase).To(Equal(controller.FailedStatusPhase)) + + sc := &v1.StorageClass{} + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, sc) + Expect(err).NotTo(HaveOccurred()) + performStandartChecksForSC(sc, lvgSpecOld, nameForLocalStorageClass, controller.LocalStorageClassLvmType, controller.LVMThickType, reclaimPolicyDelete, volumeBindingModeWFFC) + }) + + It("Remove_local_sc_with_non_existing_vg", func() { + lvgSpec := []v1alpha1.LocalStorageClassLVG{ + {Name: existingThickLVG1Name}, + {Name: existingThickLVG2Name}, + {Name: nonExistentLVG1Name}, + } + + lsc := &v1alpha1.LocalStorageClass{} + err := cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, lsc) + Expect(err).NotTo(HaveOccurred()) + Expect(lsc.Spec.LVM.LVMVolumeGroups).To(Equal(lvgSpec)) + + err = cl.Delete(ctx, lsc) + Expect(err).NotTo(HaveOccurred()) + + lsc = &v1alpha1.LocalStorageClass{} + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, lsc) + Expect(err).NotTo(HaveOccurred()) + Expect(lsc.Finalizers).To(HaveLen(1)) + + scList := &v1.StorageClassList{} + err = cl.List(ctx, scList) + Expect(err).NotTo(HaveOccurred()) + Expect(scList.Items).To(HaveLen(1)) + + shouldRequeue, err := controller.RunEventReconcile(ctx, cl, log, scList, lsc) + Expect(err).NotTo(HaveOccurred()) + Expect(shouldRequeue).To(BeFalse()) + + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, lsc) + Expect(k8serrors.IsNotFound(err)).To(BeTrue()) + + sc := &v1.StorageClass{} + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, sc) + Expect(k8serrors.IsNotFound(err)).To(BeTrue()) + }) + + It("Create_local_sc_with_non_existing_vgs", func() { + lvgSpec := []v1alpha1.LocalStorageClassLVG{ + {Name: nonExistentLVG1Name}, + {Name: nonExistentLVG2Name}, + } + + lscTemplate := generateLocalStorageClass(nameForLocalStorageClass, reclaimPolicyDelete, volumeBindingModeWFFC, controller.LVMThickType, lvgSpec) + + err := cl.Create(ctx, lscTemplate) + Expect(err).NotTo(HaveOccurred()) + + lsc := &v1alpha1.LocalStorageClass{} + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, lsc) + Expect(err).NotTo(HaveOccurred()) + + scList := &v1.StorageClassList{} + err = cl.List(ctx, scList) + Expect(err).NotTo(HaveOccurred()) + Expect(scList.Items).To(HaveLen(0)) + + shouldRequeue, err := controller.RunEventReconcile(ctx, cl, log, scList, lsc) + Expect(err).To(HaveOccurred()) + Expect(shouldRequeue).To(BeTrue()) + + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, lsc) + Expect(err).NotTo(HaveOccurred()) + Expect(lsc.Finalizers).To(HaveLen(1)) + Expect(lsc.Finalizers).To(ContainElement(controller.LocalStorageClassFinalizerName)) + Expect(lsc.Status.Phase).To(Equal(controller.FailedStatusPhase)) + + sc := &v1.StorageClass{} + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, sc) + Expect(k8serrors.IsNotFound(err)).To(BeTrue()) + + }) + + It("Update_local_sc_with_all_existing_vgs", func() { lvgSpec := []v1alpha1.LocalStorageClassLVG{ {Name: existingThickLVG1Name}, {Name: existingThickLVG2Name}, } - lsc.Spec.LVM.LVMVolumeGroups = delFromSlice(lsc.Spec.LVM.LVMVolumeGroups, newThickLVGName) + + lsc := &v1alpha1.LocalStorageClass{} + err := cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, lsc) + Expect(err).NotTo(HaveOccurred()) + + lsc.Spec.LVM.LVMVolumeGroups = lvgSpec err = cl.Update(ctx, lsc) Expect(err).NotTo(HaveOccurred()) @@ -166,6 +324,7 @@ var _ = Describe(controller.LocalStorageClassCtrlName, func() { scList := &v1.StorageClassList{} err = cl.List(ctx, scList) Expect(err).NotTo(HaveOccurred()) + Expect(scList.Items).To(HaveLen(0)) shouldRequeue, err := controller.RunEventReconcile(ctx, cl, log, scList, lsc) Expect(err).NotTo(HaveOccurred()) @@ -184,22 +343,102 @@ var _ = Describe(controller.LocalStorageClassCtrlName, func() { performStandartChecksForSC(sc, lvgSpec, nameForLocalStorageClass, controller.LocalStorageClassLvmType, controller.LVMThickType, reclaimPolicyDelete, volumeBindingModeWFFC) }) - It("Update_local_sc_add_non_existing_vg", func() { + It("Remove_local_sc_with_existing_vgs", func() { + lvgSpec := []v1alpha1.LocalStorageClassLVG{ + {Name: existingThickLVG1Name}, + {Name: existingThickLVG2Name}, + } + lsc := &v1alpha1.LocalStorageClass{} err := cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, lsc) Expect(err).NotTo(HaveOccurred()) - lvgSpecOld := []v1alpha1.LocalStorageClassLVG{ + err = cl.Delete(ctx, lsc) + Expect(err).NotTo(HaveOccurred()) + + lsc = &v1alpha1.LocalStorageClass{} + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, lsc) + Expect(err).NotTo(HaveOccurred()) + Expect(lsc.Finalizers).To(HaveLen(1)) + Expect(lsc.Finalizers).To(ContainElement(controller.LocalStorageClassFinalizerName)) + Expect(lsc.Spec.LVM.LVMVolumeGroups).To(Equal(lvgSpec)) + + scList := &v1.StorageClassList{} + err = cl.List(ctx, scList) + Expect(err).NotTo(HaveOccurred()) + Expect(scList.Items).To(HaveLen(1)) + + shouldRequeue, err := controller.RunEventReconcile(ctx, cl, log, scList, lsc) + Expect(err).NotTo(HaveOccurred()) + Expect(shouldRequeue).To(BeFalse()) + + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, lsc) + Expect(k8serrors.IsNotFound(err)).To(BeTrue()) + + sc := &v1.StorageClass{} + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, sc) + Expect(k8serrors.IsNotFound(err)).To(BeTrue()) + }) + + It("Create_local_sc_when_sc_with_another_provisioner_exists", func() { + sc := &v1.StorageClass{ + ObjectMeta: metav1.ObjectMeta{ + Name: nameForLocalStorageClass, + }, + Provisioner: "test-provisioner", + } + + err := cl.Create(ctx, sc) + Expect(err).NotTo(HaveOccurred()) + + lvgSpec := []v1alpha1.LocalStorageClassLVG{ {Name: existingThickLVG1Name}, {Name: existingThickLVG2Name}, } + lscTemplate := generateLocalStorageClass(nameForLocalStorageClass, reclaimPolicyDelete, volumeBindingModeWFFC, controller.LVMThickType, lvgSpec) + + err = cl.Create(ctx, lscTemplate) + Expect(err).NotTo(HaveOccurred()) + + lsc := &v1alpha1.LocalStorageClass{} + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, lsc) + Expect(err).NotTo(HaveOccurred()) + + scList := &v1.StorageClassList{} + err = cl.List(ctx, scList) + Expect(err).NotTo(HaveOccurred()) + Expect(scList.Items).To(HaveLen(1)) + + shouldRequeue, err := controller.RunEventReconcile(ctx, cl, log, scList, lsc) + Expect(err).To(HaveOccurred()) + Expect(shouldRequeue).To(BeTrue()) + + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, lsc) + Expect(err).NotTo(HaveOccurred()) + Expect(lsc.Finalizers).To(HaveLen(1)) + Expect(lsc.Finalizers).To(ContainElement(controller.LocalStorageClassFinalizerName)) + Expect(lsc.Status.Phase).To(Equal(controller.FailedStatusPhase)) + + sc = &v1.StorageClass{} + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, sc) + Expect(err).NotTo(HaveOccurred()) + Expect(sc.Provisioner).To(Equal("test-provisioner")) + Expect(sc.Finalizers).To(HaveLen(0)) + }) + + It("Update_local_sc_add_existing_vg_when_sc_with_another_provisioner_exists", func() { lvgSpec := []v1alpha1.LocalStorageClassLVG{ {Name: existingThickLVG1Name}, {Name: existingThickLVG2Name}, - {Name: nonExistentLVG1Name}, + {Name: newThickLVGName}, } - lsc.Spec.LVM.LVMVolumeGroups = append(lsc.Spec.LVM.LVMVolumeGroups, v1alpha1.LocalStorageClassLVG{Name: nonExistentLVG1Name}) + + lsc := &v1alpha1.LocalStorageClass{} + err := cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, lsc) + Expect(err).NotTo(HaveOccurred()) + + lsc.Spec.LVM.LVMVolumeGroups = append(lsc.Spec.LVM.LVMVolumeGroups, v1alpha1.LocalStorageClassLVG{Name: newThickLVGName}) err = cl.Update(ctx, lsc) Expect(err).NotTo(HaveOccurred()) @@ -207,6 +446,7 @@ var _ = Describe(controller.LocalStorageClassCtrlName, func() { scList := &v1.StorageClassList{} err = cl.List(ctx, scList) Expect(err).NotTo(HaveOccurred()) + Expect(scList.Items).To(HaveLen(1)) shouldRequeue, err := controller.RunEventReconcile(ctx, cl, log, scList, lsc) Expect(err).To(HaveOccurred()) @@ -222,126 +462,107 @@ var _ = Describe(controller.LocalStorageClassCtrlName, func() { sc := &v1.StorageClass{} err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, sc) Expect(err).NotTo(HaveOccurred()) - performStandartChecksForSC(sc, lvgSpecOld, nameForLocalStorageClass, controller.LocalStorageClassLvmType, controller.LVMThickType, reclaimPolicyDelete, volumeBindingModeWFFC) + Expect(sc.Provisioner).To(Equal("test-provisioner")) + Expect(sc.Finalizers).To(HaveLen(0)) }) - // It("Remove_local_sc_with_non_existing_vg", func() { - // nsc := &v1alpha1.NFSStorageClass{} - // err := cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, nsc) - // Expect(err).NotTo(HaveOccurred()) - - // err = cl.Delete(ctx, nsc) - // Expect(err).NotTo(HaveOccurred()) - - // nsc = &v1alpha1.NFSStorageClass{} - // err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, nsc) - // Expect(err).NotTo(HaveOccurred()) + It("Remove_local_sc_with_existing_vgs_when_sc_with_another_provisioner_exists", func() { + lvgSpec := []v1alpha1.LocalStorageClassLVG{ + {Name: existingThickLVG1Name}, + {Name: existingThickLVG2Name}, + {Name: newThickLVGName}, + } - // scList := &v1.StorageClassList{} - // err = cl.List(ctx, scList) - // Expect(err).NotTo(HaveOccurred()) - - // shouldRequeue, err := controller.RunEventReconcile(ctx, cl, log, scList, nsc, controllerNamespace) - // Expect(err).NotTo(HaveOccurred()) - // Expect(shouldRequeue).To(BeFalse()) + lsc := &v1alpha1.LocalStorageClass{} + err := cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, lsc) + Expect(err).NotTo(HaveOccurred()) - // err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, nsc) - // Expect(k8serrors.IsNotFound(err)).To(BeTrue()) + err = cl.Delete(ctx, lsc) + Expect(err).NotTo(HaveOccurred()) - // sc := &v1.StorageClass{} - // err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, sc) - // Expect(k8serrors.IsNotFound(err)).To(BeTrue()) + lsc = &v1alpha1.LocalStorageClass{} + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, lsc) + Expect(err).NotTo(HaveOccurred()) + Expect(lsc.Finalizers).To(HaveLen(1)) + Expect(lsc.Finalizers).To(ContainElement(controller.LocalStorageClassFinalizerName)) + Expect(lsc.Spec.LVM.LVMVolumeGroups).To(Equal(lvgSpec)) - // secret := &corev1.Secret{} - // err = cl.Get(ctx, client.ObjectKey{Name: controller.SecretForMountOptionsPrefix + nameForLocalStorageClass, Namespace: controllerNamespace}, secret) - // Expect(k8serrors.IsNotFound(err)).To(BeTrue()) + scList := &v1.StorageClassList{} + err = cl.List(ctx, scList) + Expect(err).NotTo(HaveOccurred()) + Expect(scList.Items).To(HaveLen(1)) - // }) + shouldRequeue, err := controller.RunEventReconcile(ctx, cl, log, scList, lsc) + Expect(err).NotTo(HaveOccurred()) + Expect(shouldRequeue).To(BeFalse()) - // It("Create_local_sc_with_non_existing_vgs", func() {}) + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, lsc) + Expect(k8serrors.IsNotFound(err)).To(BeTrue()) - // It("Update_local_sc_with_all_existing_vgs", func() {}) + sc := &v1.StorageClass{} + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, sc) + Expect(err).NotTo(HaveOccurred()) + Expect(sc.Provisioner).To(Equal("test-provisioner")) + Expect(sc.Finalizers).To(HaveLen(0)) - // It("Remove_local_sc_with_existing_vgs", func() {}) + err = cl.Delete(ctx, sc) + Expect(err).NotTo(HaveOccurred()) - // It("Create_local_sc_when_sc_with_another_provisioner_exists", func() { - // sc := &v1.StorageClass{ - // ObjectMeta: metav1.ObjectMeta{ - // Name: nameForLocalStorageClass, - // }, - // Provisioner: "test-provisioner", - // } + sc = &v1.StorageClass{} + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, sc) + Expect(k8serrors.IsNotFound(err)).To(BeTrue()) + }) - // err := cl.Create(ctx, sc) - // Expect(err).NotTo(HaveOccurred()) + It("Create_local_thin_sc_with_existing_thin_lvgs", func() { + lvgSpec := []v1alpha1.LocalStorageClassLVG{ + {Name: existingThinLVG1Name, Thin: &v1alpha1.LocalStorageClassThinPool{PoolName: "thin-pool-1"}}, + {Name: existingThinLVG2Name, Thin: &v1alpha1.LocalStorageClassThinPool{PoolName: "thin-pool-1"}}, + } - // nfsSCtemplate := generateLocalStorageClass(NFSStorageClassConfig{ - // Name: nameForLocalStorageClass, - // Host: server, - // Share: share, - // NFSVersion: nfsVer, - // MountMode: mountMode, - // ReadOnly: &readOnlyFalse, - // ReclaimPolicy: string(corev1.PersistentVolumeReclaimDelete), - // VolumeBindingMode: string(v1.VolumeBindingWaitForFirstConsumer), - // }) + err := cl.Create(ctx, existingThinLVG1Template) + Expect(err).NotTo(HaveOccurred()) - // err = cl.Create(ctx, nfsSCtemplate) - // Expect(err).NotTo(HaveOccurred()) + err = cl.Create(ctx, existingThinLVG2Template) + Expect(err).NotTo(HaveOccurred()) - // nsc := &v1alpha1.NFSStorageClass{} - // err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, nsc) - // Expect(err).NotTo(HaveOccurred()) + existingThinLVG1 := &v1alpha1.LvmVolumeGroup{} + err = cl.Get(ctx, client.ObjectKey{Name: existingThinLVG1Name}, existingThinLVG1) + Expect(err).NotTo(HaveOccurred()) + Expect(existingThinLVG1.Spec.ThinPools).To(HaveLen(2)) + Expect(existingThinLVG1.Spec.ThinPools[0].Name).To(Equal("thin-pool-1")) + Expect(existingThinLVG1.Spec.ThinPools[1].Name).To(Equal("thin-pool-2")) - // scList := &v1.StorageClassList{} - // err = cl.List(ctx, scList) - // Expect(err).NotTo(HaveOccurred()) + lscTemplate := generateLocalStorageClass(nameForLocalStorageClass, reclaimPolicyRetain, volumeBindingModeIM, controller.LVMThinType, lvgSpec) - // shouldRequeue, err := controller.RunEventReconcile(ctx, cl, log, scList, nsc, controllerNamespace) - // Expect(err).To(HaveOccurred()) - // Expect(shouldRequeue).To(BeTrue()) + err = cl.Create(ctx, lscTemplate) + Expect(err).NotTo(HaveOccurred()) - // err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, sc) - // Expect(err).NotTo(HaveOccurred()) - // Expect(sc.Provisioner).To(Equal("test-provisioner")) - // Expect(sc.Finalizers).To(HaveLen(0)) - // Expect(sc.Labels).To(HaveLen(0)) - // }) + lsc := &v1alpha1.LocalStorageClass{} + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, lsc) + Expect(err).NotTo(HaveOccurred()) - // It("Update_local_sc_add_existing_vg_when_sc_with_another_provisioner_exists", func() {}) + Expect(lsc).NotTo(BeNil()) + Expect(lsc.Name).To(Equal(nameForLocalStorageClass)) + Expect(lsc.Finalizers).To(HaveLen(0)) - // It("Remove_local_sc_with_existing_vgs_when_sc_with_another_provisioner_exists", func() { - // nsc := &v1alpha1.NFSStorageClass{} - // err := cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, nsc) - // Expect(err).NotTo(HaveOccurred()) + scList := &v1.StorageClassList{} + err = cl.List(ctx, scList) + Expect(err).NotTo(HaveOccurred()) - // err = cl.Delete(ctx, nsc) - // Expect(err).NotTo(HaveOccurred()) + shouldRequeue, err := controller.RunEventReconcile(ctx, cl, log, scList, lsc) + Expect(err).NotTo(HaveOccurred()) + Expect(shouldRequeue).To(BeFalse()) - // nsc = &v1alpha1.NFSStorageClass{} - // err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, nsc) - // Expect(err).NotTo(HaveOccurred()) - // Expect(nsc.Finalizers).To(HaveLen(1)) - // Expect(nsc.Finalizers).To(ContainElement(controller.NFSStorageClassFinalizerName)) + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, lsc) + Expect(err).NotTo(HaveOccurred()) + Expect(lsc.Finalizers).To(HaveLen(1)) + Expect(lsc.Finalizers).To(ContainElement(controller.LocalStorageClassFinalizerName)) - // scList := &v1.StorageClassList{} - // err = cl.List(ctx, scList) - // Expect(err).NotTo(HaveOccurred()) - - // shouldRequeue, err := controller.RunEventReconcile(ctx, cl, log, scList, nsc, controllerNamespace) - // Expect(err).NotTo(HaveOccurred()) - // Expect(shouldRequeue).To(BeFalse()) - - // err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, nsc) - // Expect(k8serrors.IsNotFound(err)).To(BeTrue()) - - // sc := &v1.StorageClass{} - // err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, sc) - // Expect(err).NotTo(HaveOccurred()) - // Expect(sc.Provisioner).To(Equal("test-provisioner")) - // Expect(sc.Finalizers).To(HaveLen(0)) - // Expect(sc.Labels).To(HaveLen(0)) - // }) + sc := &v1.StorageClass{} + err = cl.Get(ctx, client.ObjectKey{Name: nameForLocalStorageClass}, sc) + Expect(err).NotTo(HaveOccurred()) + performStandartChecksForSC(sc, lvgSpec, nameForLocalStorageClass, controller.LocalStorageClassLvmType, controller.LVMThinType, reclaimPolicyRetain, volumeBindingModeIM) + }) }) @@ -352,12 +573,18 @@ func generateLVMVolumeGroup(name string, devices, thinPoolNames []string) *v1alp lvmType = controller.LVMThinType } - thinPools := make([]v1alpha1.SpecThinPool, 0) - for i := 0; i < len(thinPools); i++ { - thinPools = append(thinPools, v1alpha1.SpecThinPool{ + thinPoolsSpec := make([]v1alpha1.SpecThinPool, 0) + thinPoolsStatus := make([]v1alpha1.StatusThinPool, 0) + for i := 0; i < len(thinPoolNames); i++ { + thinPoolsSpec = append(thinPoolsSpec, v1alpha1.SpecThinPool{ Name: thinPoolNames[i], Size: resource.MustParse("10Gi"), }) + thinPoolsStatus = append(thinPoolsStatus, v1alpha1.StatusThinPool{ + Name: thinPoolNames[i], + ActualSize: resource.MustParse("10Gi"), + UsedSize: resource.MustParse("0Gi"), + }) } return &v1alpha1.LvmVolumeGroup{ @@ -367,9 +594,12 @@ func generateLVMVolumeGroup(name string, devices, thinPoolNames []string) *v1alp Spec: v1alpha1.LvmVolumeGroupSpec{ ActualVGNameOnTheNode: "vg1", BlockDeviceNames: devices, - ThinPools: thinPools, + ThinPools: thinPoolsSpec, Type: lvmType, }, + Status: v1alpha1.LvmVolumeGroupStatus{ + ThinPools: thinPoolsStatus, + }, } } @@ -397,7 +627,11 @@ func performStandartChecksForSC(sc *v1.StorageClass, lvgSpec []v1alpha1.LocalSto if i != 0 { expectString += "\n" } - expectString += "- name: " + lvg.Name + if lvg.Thin != nil { + expectString += "- name: " + lvg.Name + "\n thin:\n poolName: " + lvg.Thin.PoolName + } else { + expectString += "- name: " + lvg.Name + } } expectString += "\n" @@ -420,28 +654,6 @@ func performStandartChecksForSC(sc *v1.StorageClass, lvgSpec []v1alpha1.LocalSto } -// func performStandartChecksForSc(sc *v1.StorageClass, server, share, nameForLocalStorageClass, controllerNamespace string) { -// Expect(sc).NotTo(BeNil()) -// Expect(sc.Name).To(Equal(nameForLocalStorageClass)) -// Expect(sc.Finalizers).To(HaveLen(1)) -// Expect(sc.Finalizers).To(ContainElement(controller.NFSStorageClassFinalizerName)) -// Expect(sc.Provisioner).To(Equal(controller.NFSStorageClassProvisioner)) -// Expect(*sc.ReclaimPolicy).To(Equal(corev1.PersistentVolumeReclaimDelete)) -// Expect(*sc.VolumeBindingMode).To(Equal(v1.VolumeBindingWaitForFirstConsumer)) -// Expect(sc.Parameters).To(HaveKeyWithValue("server", server)) -// Expect(sc.Parameters).To(HaveKeyWithValue("share", share)) -// Expect(sc.Parameters).To(HaveKeyWithValue(controller.StorageClassSecretNameKey, controller.SecretForMountOptionsPrefix+nameForLocalStorageClass)) -// Expect(sc.Parameters).To(HaveKeyWithValue(controller.StorageClassSecretNSKey, controllerNamespace)) -// } - -// func performStandartChecksForSecret(secret *corev1.Secret, nameForLocalStorageClass, controllerNamespace string) { -// Expect(secret).NotTo(BeNil()) -// Expect(secret.Name).To(Equal(controller.SecretForMountOptionsPrefix + nameForLocalStorageClass)) -// Expect(secret.Namespace).To(Equal(controllerNamespace)) -// Expect(secret.Finalizers).To(HaveLen(1)) -// Expect(secret.Finalizers).To(ContainElement(controller.NFSStorageClassFinalizerName)) -// } - func delFromSlice(slice []v1alpha1.LocalStorageClassLVG, name string) []v1alpha1.LocalStorageClassLVG { for i, lvg := range slice { if lvg.Name == name {