diff --git a/internal/controller/datamovementmanager_controller.go b/internal/controller/datamovementmanager_controller.go index 2871bb16..0c145712 100644 --- a/internal/controller/datamovementmanager_controller.go +++ b/internal/controller/datamovementmanager_controller.go @@ -130,6 +130,50 @@ func (r *NnfDataMovementManagerReconciler) Reconcile(ctx context.Context, req ct return ctrl.Result{}, err } + if !manager.GetDeletionTimestamp().IsZero() { + log.Info("Deleting DataMovementManager...") + + if !controllerutil.ContainsFinalizer(manager, finalizer) { + return ctrl.Result{}, nil + } + + // Need to remove the namespace from lustrefilesystem resources + if err := r.removeLustreFileSystemsNamespace(ctx, manager); err != nil { + return errorHandler(err, "remove all LustreFileSystems namespace spec") + } + + // And the finalizer + if err := r.removeAllLustreFileSystemsFinalizers(ctx, manager); err != nil { + return errorHandler(err, "remove all LustreFileSystems finalizers") + } + + // Now it's safe to proceed + controllerutil.RemoveFinalizer(manager, finalizer) + if err := r.Update(ctx, manager); err != nil { + if !apierrors.IsConflict(err) { + return ctrl.Result{}, err + } + + return ctrl.Result{Requeue: true}, nil + } + + return ctrl.Result{}, nil + } + + // Add the finalizer if it doesn't exist + if !controllerutil.ContainsFinalizer(manager, finalizer) { + controllerutil.AddFinalizer(manager, finalizer) + if err := r.Update(ctx, manager); err != nil { + if !apierrors.IsConflict(err) { + return ctrl.Result{}, err + } + + return ctrl.Result{Requeue: true}, nil + } + + return ctrl.Result{}, nil + } + if err := r.createSecretIfNecessary(ctx, manager); err != nil { return errorHandler(err, "create Secret") } @@ -341,8 +385,7 @@ func (r *NnfDataMovementManagerReconciler) updateLustreFileSystemsIfNecessary(ct } for _, lustre := range filesystems.Items { - _, found := lustre.Spec.Namespaces[manager.Namespace] - if !found { + if _, found := lustre.Spec.Namespaces[manager.Namespace]; !found { if lustre.Spec.Namespaces == nil { lustre.Spec.Namespaces = make(map[string]lusv1beta1.LustreFileSystemNamespaceSpec) } @@ -366,6 +409,51 @@ func (r *NnfDataMovementManagerReconciler) updateLustreFileSystemsIfNecessary(ct return nil } +// Remove nnf-dm namespaces from the spec in all LustreFileSystem resources +func (r *NnfDataMovementManagerReconciler) removeLustreFileSystemsNamespace(ctx context.Context, manager *nnfv1alpha1.NnfDataMovementManager) error { + filesystems := &lusv1beta1.LustreFileSystemList{} + if err := r.List(ctx, filesystems); err != nil && !meta.IsNoMatchError(err) { + return fmt.Errorf("list lustre file systems failed: %w", err) + } + + for _, lustre := range filesystems.Items { + if _, found := lustre.Spec.Namespaces[manager.Namespace]; found { + delete(lustre.Spec.Namespaces, manager.Namespace) + + if err := r.Update(ctx, &lustre); err != nil { + return err + } + log.FromContext(ctx).Info("Removed LustreFileSystem namespace from the spec", "object", client.ObjectKeyFromObject(&lustre).String(), "namespace", manager.Namespace) + } + } + + return nil +} + +// Remove nnf-dm finalizers from all LustreFileSystem resources +func (r *NnfDataMovementManagerReconciler) removeAllLustreFileSystemsFinalizers(ctx context.Context, manager *nnfv1alpha1.NnfDataMovementManager) error { + filesystems := &lusv1beta1.LustreFileSystemList{} + if err := r.List(ctx, filesystems); err != nil && !meta.IsNoMatchError(err) { + return fmt.Errorf("list lustre file systems failed: %w", err) + } + + for _, lustre := range filesystems.Items { + if controllerutil.ContainsFinalizer(&lustre, finalizer) { + controllerutil.RemoveFinalizer(&lustre, finalizer) + if err := r.Update(ctx, &lustre); err != nil { + return err + } + log.FromContext(ctx).Info("Removed LustreFileSystem finalizer", "object", client.ObjectKeyFromObject(&lustre).String(), "namespace", manager.Namespace) + } + } + + return nil +} + +// Check if any LustreFileSystem resources are in the process of being deleted. If they are, that +// means the DaemonSet is going to restart all the pods to unmount that LustreFileSystem. Wait until +// the DaemonSet has done that, and then finally remove the finalizer from the LustreFileSystem +// resource to signal that it's ok to clean up the PV/PVC (since the worker pods are done with it). func (r *NnfDataMovementManagerReconciler) removeLustreFileSystemsFinalizersIfNecessary(ctx context.Context, manager *nnfv1alpha1.NnfDataMovementManager) error { log := log.FromContext(ctx)