github.com/openebs/node-disk-manager@v1.9.1-0.20230225014141-4531f06ffa1e/pkg/controllers/blockdevice/blockdevice_controller.go (about) 1 /* 2 Copyright 2021. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package blockdevice 18 19 import ( 20 "context" 21 util2 "github.com/openebs/node-disk-manager/pkg/controllers/util" 22 23 "github.com/go-logr/logr" 24 corev1 "k8s.io/api/core/v1" 25 "k8s.io/apimachinery/pkg/api/errors" 26 "k8s.io/apimachinery/pkg/runtime" 27 "k8s.io/client-go/tools/record" 28 "k8s.io/klog/v2" 29 ctrl "sigs.k8s.io/controller-runtime" 30 "sigs.k8s.io/controller-runtime/pkg/client" 31 "sigs.k8s.io/controller-runtime/pkg/reconcile" 32 33 apis "github.com/openebs/node-disk-manager/api/v1alpha1" 34 ndm "github.com/openebs/node-disk-manager/cmd/ndm_daemonset/controller" 35 "github.com/openebs/node-disk-manager/pkg/cleaner" 36 "github.com/openebs/node-disk-manager/pkg/util" 37 ) 38 39 // BlockDeviceReconciler reconciles a BlockDevice object 40 type BlockDeviceReconciler struct { 41 Client client.Client 42 Log logr.Logger 43 Scheme *runtime.Scheme 44 Recorder record.EventRecorder 45 } 46 47 //+kubebuilder:rbac:groups=openebs.io,resources=blockdevices,verbs=get;list;watch;create;update;patch;delete 48 //+kubebuilder:rbac:groups=openebs.io,resources=blockdevices/status,verbs=get;update;patch 49 //+kubebuilder:rbac:groups=openebs.io,resources=blockdevices/finalizers,verbs=update 50 51 // Reconcile is part of the main kubernetes reconciliation loop which aims to 52 // move the current state of the cluster closer to the desired state. 53 // For more details, check Reconcile and its Result here: 54 // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.7.2/pkg/reconcile 55 func (r *BlockDeviceReconciler) Reconcile(ctx context.Context, request ctrl.Request) (ctrl.Result, error) { 56 // Fetch the BlockDevice instance 57 instance := &apis.BlockDevice{} 58 err := r.Client.Get(context.TODO(), request.NamespacedName, instance) 59 if err != nil { 60 if errors.IsNotFound(err) { 61 // Requested object not found, could have been deleted after reconcile request. 62 // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers. 63 // Return and don't requeue 64 return reconcile.Result{}, nil 65 } 66 // Error reading the object - requeue the request. 67 return reconcile.Result{}, err 68 } 69 70 // check if the this block device need to reconciled 71 if IsReconcileDisabled(instance) { 72 return reconcile.Result{}, nil 73 } 74 75 switch instance.Status.ClaimState { 76 case apis.BlockDeviceReleased: 77 klog.V(2).Infof("%s is in Released state", instance.Name) 78 jobController := cleaner.NewJobController(r.Client, request.Namespace) 79 cleanupTracker := &cleaner.CleanupStatusTracker{JobController: jobController} 80 bdCleaner := cleaner.NewCleaner(r.Client, request.Namespace, cleanupTracker) 81 ok, err := bdCleaner.Clean(instance) 82 if err != nil { 83 klog.Errorf("Error while cleaning %s: %v", instance.Name, err) 84 r.Recorder.Eventf(instance, corev1.EventTypeWarning, "BlockDeviceCleanUp", "CleanUp unsuccessful, due to error: %v", err) 85 break 86 } 87 if ok { 88 r.Recorder.Eventf(instance, corev1.EventTypeNormal, "BlockDeviceReleased", "CleanUp Completed") 89 // remove the finalizer string from BlockDevice resource 90 instance.Finalizers = util.RemoveString(instance.Finalizers, util2.BlockDeviceFinalizer) 91 klog.Infof("Cleanup completed for %s", instance.Name) 92 err := r.updateBDStatus(apis.BlockDeviceUnclaimed, instance) 93 if err != nil { 94 klog.Errorf("Failed to mark %s as Unclaimed: %v", instance.Name, err) 95 } 96 r.Recorder.Eventf(instance, corev1.EventTypeNormal, "BlockDeviceUnclaimed", "BD now marked as Unclaimed") 97 } else { 98 r.Recorder.Eventf(instance, corev1.EventTypeNormal, "BlockDeviceCleanUpInProgress", "CleanUp is in progress") 99 } 100 case apis.BlockDeviceClaimed: 101 if !util.Contains(instance.GetFinalizers(), util2.BlockDeviceFinalizer) { 102 // finalizer is not present, may be a BlockDevice claimed from previous release 103 instance.Finalizers = append(instance.Finalizers, util2.BlockDeviceFinalizer) 104 err := r.Client.Update(context.TODO(), instance) 105 if err != nil { 106 klog.Errorf("Error updating finalizer on %s: %v", instance.Name, err) 107 } 108 klog.Infof("%s updated with %s finalizer", instance.Name, util2.BlockDeviceFinalizer) 109 r.Recorder.Eventf(instance, corev1.EventTypeNormal, "BlockDeviceClaimed", "BD Claimed, and finalizer added") 110 } 111 // if finalizer is already present. do nothing 112 } 113 114 return reconcile.Result{}, nil 115 } 116 117 // SetupWithManager sets up the controller with the Manager. 118 func (r *BlockDeviceReconciler) SetupWithManager(mgr ctrl.Manager) error { 119 return ctrl.NewControllerManagedBy(mgr). 120 For(&apis.BlockDevice{}). 121 Owns(&apis.BlockDevice{}). 122 Complete(r) 123 } 124 125 func (r *BlockDeviceReconciler) updateBDStatus(state apis.DeviceClaimState, instance *apis.BlockDevice) error { 126 instance.Status.ClaimState = state 127 err := r.Client.Update(context.TODO(), instance) 128 if err != nil { 129 return err 130 } 131 return nil 132 } 133 134 // IsReconcileDisabled is used to check if reconciliation is disabled for 135 // BlockDevice 136 func IsReconcileDisabled(bd *apis.BlockDevice) bool { 137 return bd.Annotations[ndm.OpenEBSReconcile] == "false" 138 }