From 37ca27a73bfbc6f6ce0014081a7992c3ffcb5828 Mon Sep 17 00:00:00 2001 From: Isteb4k Date: Wed, 26 Jun 2024 12:19:43 +0200 Subject: [PATCH] fix(cvi,vi): add attachee handlers Signed-off-by: Isteb4k --- api/core/v1alpha2/finalizers.go | 11 --- .../pkg/controller/cvi/cvi_controller.go | 3 +- .../pkg/controller/cvi/internal/attachee.go | 79 +++++++++++++++++ .../pkg/controller/vd/vd_controller.go | 2 +- .../pkg/controller/vi/internal/attachee.go | 85 +++++++++++++++++++ .../pkg/controller/vi/vi_controller.go | 3 +- 6 files changed, 169 insertions(+), 14 deletions(-) create mode 100644 images/virtualization-artifact/pkg/controller/cvi/internal/attachee.go create mode 100644 images/virtualization-artifact/pkg/controller/vi/internal/attachee.go diff --git a/api/core/v1alpha2/finalizers.go b/api/core/v1alpha2/finalizers.go index d8ba88b84..9aa7c601e 100644 --- a/api/core/v1alpha2/finalizers.go +++ b/api/core/v1alpha2/finalizers.go @@ -17,17 +17,6 @@ limitations under the License. package v1alpha2 const ( - FinalizerClusterVirtualImageProtection = "virtualization.deckhouse.io/cvi-protection" - FinalizerVirtualImageProtection = "virtualization.deckhouse.io/vi-protection" - FinalizerVirtualDiskProtection = "virtualization.deckhouse.io/vd-protection" - FinalizerPodProtection = "virtualization.deckhouse.io/pod-protection" - FinalizerServiceProtection = "virtualization.deckhouse.io/svc-protection" - FinalizerIngressProtection = "virtualization.deckhouse.io/ingress-protection" - FinalizerSecretProtection = "virtualization.deckhouse.io/secret-protection" - FinalizerDVProtection = "virtualization.deckhouse.io/dv-protection" - FinalizerPVCProtection = "virtualization.deckhouse.io/pvc-protection" - FinalizerPVProtection = "virtualization.deckhouse.io/pv-protection" - FinalizerCVIProtection = "virtualization.deckhouse.io/cvi-protection" FinalizerVIProtection = "virtualization.deckhouse.io/vi-protection" FinalizerVDProtection = "virtualization.deckhouse.io/vd-protection" diff --git a/images/virtualization-artifact/pkg/controller/cvi/cvi_controller.go b/images/virtualization-artifact/pkg/controller/cvi/cvi_controller.go index 05d29da2c..a22ff908e 100644 --- a/images/virtualization-artifact/pkg/controller/cvi/cvi_controller.go +++ b/images/virtualization-artifact/pkg/controller/cvi/cvi_controller.go @@ -53,7 +53,7 @@ func NewController( ns string, ) (controller.Controller, error) { stat := service.NewStatService() - protection := service.NewProtectionService(mgr.GetClient(), virtv2.FinalizerClusterVirtualImageProtection) + protection := service.NewProtectionService(mgr.GetClient(), virtv2.FinalizerCVIProtection) importer := service.NewImporterService(dvcr, mgr.GetClient(), importerImage, PodPullPolicy, PodVerbose, ControllerName, protection) uploader := service.NewUploaderService(dvcr, mgr.GetClient(), uploaderImage, PodPullPolicy, PodVerbose, ControllerName, protection) @@ -68,6 +68,7 @@ func NewController( internal.NewDatasourceReadyHandler(sources), internal.NewLifeCycleHandler(sources, mgr.GetClient()), internal.NewDeletionHandler(sources), + internal.NewAttacheeHandler(mgr.GetClient()), ) cviController, err := controller.New(ControllerName, mgr, controller.Options{Reconciler: reconciler}) diff --git a/images/virtualization-artifact/pkg/controller/cvi/internal/attachee.go b/images/virtualization-artifact/pkg/controller/cvi/internal/attachee.go new file mode 100644 index 000000000..d87f8cae6 --- /dev/null +++ b/images/virtualization-artifact/pkg/controller/cvi/internal/attachee.go @@ -0,0 +1,79 @@ +/* +Copyright 2024 Flant JSC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package internal + +import ( + "context" + "fmt" + + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2" +) + +type AttacheeHandler struct { + client client.Client +} + +func NewAttacheeHandler(client client.Client) *AttacheeHandler { + return &AttacheeHandler{ + client: client, + } +} + +func (h AttacheeHandler) Handle(ctx context.Context, cvi *virtv2.ClusterVirtualImage) (reconcile.Result, error) { + hasAttachedVM, err := h.hasAttachedVM(ctx, cvi) + if err != nil { + return reconcile.Result{}, err + } + + if hasAttachedVM { + controllerutil.AddFinalizer(cvi, virtv2.FinalizerCVIProtection) + return reconcile.Result{}, nil + } + + controllerutil.RemoveFinalizer(cvi, virtv2.FinalizerCVIProtection) + return reconcile.Result{}, nil +} + +func (h AttacheeHandler) hasAttachedVM(ctx context.Context, cvi client.Object) (bool, error) { + var vms virtv2.VirtualMachineList + err := h.client.List(ctx, &vms, &client.ListOptions{}) + if err != nil { + return false, fmt.Errorf("error getting virtual machines: %w", err) + } + + for _, vm := range vms.Items { + if h.isCVIAttachedToVM(cvi.GetName(), vm) { + return true, nil + } + } + + return false, nil +} + +func (h AttacheeHandler) isCVIAttachedToVM(cviName string, vm virtv2.VirtualMachine) bool { + for _, bda := range vm.Status.BlockDeviceRefs { + if bda.Kind == virtv2.ClusterImageDevice && bda.Name == cviName { + return true + } + } + + return false +} diff --git a/images/virtualization-artifact/pkg/controller/vd/vd_controller.go b/images/virtualization-artifact/pkg/controller/vd/vd_controller.go index 827002ad8..53f8eab8a 100644 --- a/images/virtualization-artifact/pkg/controller/vd/vd_controller.go +++ b/images/virtualization-artifact/pkg/controller/vd/vd_controller.go @@ -52,7 +52,7 @@ func NewController( dvcr *dvcr.Settings, ) (controller.Controller, error) { stat := service.NewStatService() - protection := service.NewProtectionService(mgr.GetClient(), virtv2.FinalizerVirtualDiskProtection) + protection := service.NewProtectionService(mgr.GetClient(), virtv2.FinalizerVDProtection) importer := service.NewImporterService(dvcr, mgr.GetClient(), importerImage, PodPullPolicy, PodVerbose, ControllerName, protection) uploader := service.NewUploaderService(dvcr, mgr.GetClient(), uploaderImage, PodPullPolicy, PodVerbose, ControllerName, protection) disk := service.NewDiskService(mgr.GetClient(), dvcr, protection) diff --git a/images/virtualization-artifact/pkg/controller/vi/internal/attachee.go b/images/virtualization-artifact/pkg/controller/vi/internal/attachee.go new file mode 100644 index 000000000..6b4f646c9 --- /dev/null +++ b/images/virtualization-artifact/pkg/controller/vi/internal/attachee.go @@ -0,0 +1,85 @@ +/* +Copyright 2024 Flant JSC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package internal + +import ( + "context" + "fmt" + + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2" +) + +type AttacheeHandler struct { + client client.Client +} + +func NewAttacheeHandler(client client.Client) *AttacheeHandler { + return &AttacheeHandler{ + client: client, + } +} + +func (h AttacheeHandler) Handle(ctx context.Context, vi *virtv2.VirtualImage) (reconcile.Result, error) { + hasAttachedVM, err := h.hasAttachedVM(ctx, vi) + if err != nil { + return reconcile.Result{}, err + } + + if hasAttachedVM { + controllerutil.AddFinalizer(vi, virtv2.FinalizerVIProtection) + return reconcile.Result{}, nil + } + + controllerutil.RemoveFinalizer(vi, virtv2.FinalizerVIProtection) + return reconcile.Result{}, nil +} + +func (h AttacheeHandler) Name() string { + return "AttacheeHandler" +} + +func (h AttacheeHandler) hasAttachedVM(ctx context.Context, vi client.Object) (bool, error) { + var vms virtv2.VirtualMachineList + err := h.client.List(ctx, &vms, &client.ListOptions{ + Namespace: vi.GetNamespace(), + }) + if err != nil { + return false, fmt.Errorf("error getting virtual machines: %w", err) + } + + for _, vm := range vms.Items { + if h.isVIAttachedToVM(vi.GetName(), vm) { + return true, nil + } + } + + return false, nil +} + +func (h AttacheeHandler) isVIAttachedToVM(viName string, vm virtv2.VirtualMachine) bool { + for _, bda := range vm.Status.BlockDeviceRefs { + if bda.Kind == virtv2.ImageDevice && bda.Name == viName { + return true + } + } + + return false +} diff --git a/images/virtualization-artifact/pkg/controller/vi/vi_controller.go b/images/virtualization-artifact/pkg/controller/vi/vi_controller.go index 2378ce786..d35c65c8f 100644 --- a/images/virtualization-artifact/pkg/controller/vi/vi_controller.go +++ b/images/virtualization-artifact/pkg/controller/vi/vi_controller.go @@ -52,7 +52,7 @@ func NewController( dvcr *dvcr.Settings, ) (controller.Controller, error) { stat := service.NewStatService() - protection := service.NewProtectionService(mgr.GetClient(), virtv2.FinalizerVirtualImageProtection) + protection := service.NewProtectionService(mgr.GetClient(), virtv2.FinalizerVIProtection) importer := service.NewImporterService(dvcr, mgr.GetClient(), importerImage, PodPullPolicy, PodVerbose, ControllerName, protection) uploader := service.NewUploaderService(dvcr, mgr.GetClient(), uploaderImage, PodPullPolicy, PodVerbose, ControllerName, protection) @@ -67,6 +67,7 @@ func NewController( internal.NewDatasourceReadyHandler(sources), internal.NewLifeCycleHandler(sources, mgr.GetClient()), internal.NewDeletionHandler(sources), + internal.NewAttacheeHandler(mgr.GetClient()), ) viController, err := controller.New(ControllerName, mgr, controller.Options{Reconciler: reconciler})