Skip to content

Commit

Permalink
controllers: create default storageclaim if not exist
Browse files Browse the repository at this point in the history
check if any other storageclient claimed ownership for creating default
storageclaims, if none exist take ownership and create them if we didn't
create them in previous reconcile already.

Signed-off-by: Leela Venkaiah G <[email protected]>
  • Loading branch information
leelavg committed Mar 26, 2024
1 parent a0f96b6 commit cb2d1e7
Showing 1 changed file with 118 additions and 8 deletions.
126 changes: 118 additions & 8 deletions controllers/storageclient_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ import (
"google.golang.org/grpc/status"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
apierrors "k8s.io/apimachinery/pkg/api/errors"
kerrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/klog/v2"
Expand All @@ -56,14 +55,19 @@ const (
GetStorageConfig = "GetStorageConfig"
AcknowledgeOnboarding = "AcknowledgeOnboarding"

storageClientAnnotationKey = "ocs.openshift.io/storageclient"
storageClientNameLabel = "ocs.openshift.io/storageclient.name"
storageClientNamespaceLabel = "ocs.openshift.io/storageclient.namespace"
storageClientFinalizer = "storageclient.ocs.openshift.io"
storageClientAnnotationKey = "ocs.openshift.io/storageclient"
storageClientNameLabel = "ocs.openshift.io/storageclient.name"
storageClientNamespaceLabel = "ocs.openshift.io/storageclient.namespace"
storageClientFinalizer = "storageclient.ocs.openshift.io"
defaultClaimsOwnerAnnotationKey = "ocs.openshift.io/storageclaim.owner"
defaultClaimsProcessedAnnotationKey = "ocs.openshift.io/storageclaim.processed"
defaultBlockStorageClaim = "ocs-storagecluster-ceph-rbd"
defaultSharedfileStorageClaim = "ocs-storagecluster-cephfs"

// indexes for caching
storageProviderEndpointIndexName = "index:storageProviderEndpoint"
storageClientAnnotationIndexName = "index:storageClientAnnotation"
defaultClaimsOwnerIndexName = "index:defaultClaimsOwner"

csvPrefix = "ocs-client-operator"
)
Expand Down Expand Up @@ -101,6 +105,12 @@ func (s *StorageClientReconciler) SetupWithManager(mgr ctrl.Manager) error {
return fmt.Errorf("unable to set up FieldIndexer for storageclient annotation: %v", err)
}

if err := mgr.GetCache().IndexField(ctx, &v1alpha1.StorageClient{}, defaultClaimsOwnerIndexName, func(obj client.Object) []string {
return []string{obj.GetAnnotations()[defaultClaimsOwnerAnnotationKey]}
}); err != nil {
return fmt.Errorf("unable to set up FieldIndexer for storageclient owner annotation: %v", err)
}

enqueueStorageClientRequest := handler.EnqueueRequestsFromMapFunc(
func(_ context.Context, obj client.Object) []reconcile.Request {
annotations := obj.GetAnnotations()
Expand Down Expand Up @@ -139,7 +149,7 @@ func (s *StorageClientReconciler) Reconcile(ctx context.Context, req ctrl.Reques
instance.Namespace = req.Namespace

if err = s.Client.Get(ctx, types.NamespacedName{Name: instance.Name, Namespace: instance.Namespace}, instance); err != nil {
if apierrors.IsNotFound(err) {
if kerrors.IsNotFound(err) {
s.Log.Info("StorageClient resource not found. Ignoring since object must be deleted.")
return reconcile.Result{}, nil
}
Expand Down Expand Up @@ -217,6 +227,10 @@ func (s *StorageClientReconciler) reconcilePhases(instance *v1alpha1.StorageClie
return res, err
}

if err := s.reconcileDefaultStorageClaims(instance); err != nil {
return reconcile.Result{}, err
}

return reconcile.Result{}, nil
}

Expand Down Expand Up @@ -246,6 +260,10 @@ func (s *StorageClientReconciler) deletionPhase(instance *v1alpha1.StorageClient
return reconcile.Result{}, fmt.Errorf("failed to delete the status reporter job: %v", err)
}

if err := s.deleteDefaultStorageClaims(instance); err != nil {
return reconcile.Result{}, fmt.Errorf("failed to delete default storageclaims: %v", err)
}

s.Log.Info("removing finalizer from StorageClient.", "StorageClient", klog.KRef(instance.Namespace, instance.Name))
// Once all finalizers have been removed, the object will be deleted
instance.ObjectMeta.Finalizers = remove(instance.ObjectMeta.Finalizers, storageClientFinalizer)
Expand Down Expand Up @@ -440,7 +458,7 @@ func getStatusReporterName(namespace, name string) string {
}

func (s *StorageClientReconciler) delete(obj client.Object) error {
if err := s.Client.Delete(s.ctx, obj); err != nil && !errors.IsNotFound(err) {
if err := s.Client.Delete(s.ctx, obj); err != nil && !kerrors.IsNotFound(err) {
return err
}
return nil
Expand Down Expand Up @@ -511,3 +529,95 @@ func (s *StorageClientReconciler) reconcileClientStatusReporterJob(instance *v1a
func (s *StorageClientReconciler) list(obj client.ObjectList, listOptions ...client.ListOption) error {
return s.Client.List(s.ctx, obj, listOptions...)
}

func (s *StorageClientReconciler) reconcileDefaultStorageClaims(instance *v1alpha1.StorageClient) error {

if instance.GetAnnotations()[defaultClaimsProcessedAnnotationKey] == "true" {
// we already processed default claims for this client
return nil
}

// try to list the default client who is the default storage claims owner
claimOwners := &v1alpha1.StorageClientList{}
if err := s.list(claimOwners, client.MatchingFields{defaultClaimsOwnerIndexName: "true"}); err != nil {
return fmt.Errorf("failed to list default storage claims owner: %v", err)
}

if len(claimOwners.Items) == 0 {
// no other storageclient claims as an owner and take responsibility of creating the default claims by becoming owner
if utils.AddAnnotation(instance, defaultClaimsOwnerAnnotationKey, "true") {
if err := s.update(instance); err != nil {
return fmt.Errorf("not able to claim ownership of creating default storageclaims: %v", err)
}
}
}

// we successfully took the ownership to create a default claim from this storageclient, so create default claims if not created
// after claiming as an owner no other storageclient will try to take ownership for creating default storageclaims
annotations := instance.GetAnnotations()
if annotations[defaultClaimsOwnerAnnotationKey] == "true" && annotations[defaultClaimsProcessedAnnotationKey] != "true" {
if err := s.createDefaultBlockStorageClaim(instance); err != nil && !kerrors.IsAlreadyExists(err) {
return fmt.Errorf("failed to create %q storageclaim: %v", defaultBlockStorageClaim, err)
}
if err := s.createDefaultSharedfileStorageClaim(instance); err != nil && !kerrors.IsAlreadyExists(err) {
return fmt.Errorf("failed to create %q storageclaim: %v", defaultSharedfileStorageClaim, err)
}
}

// annotate that we created default storageclaims successfully and will not retry
if utils.AddAnnotation(instance, defaultClaimsProcessedAnnotationKey, "true") {
if err := s.update(instance); err != nil {
return fmt.Errorf("not able to update annotation for creation of default storageclaims: %v", err)
}
}

return nil
}

func (s *StorageClientReconciler) createDefaultBlockStorageClaim(instance *v1alpha1.StorageClient) error {
storageclaim := &v1alpha1.StorageClaim{}
storageclaim.Name = defaultBlockStorageClaim
storageclaim.Spec.Type = "block"
storageclaim.Spec.StorageClient = &v1alpha1.StorageClientNamespacedName{
Name: instance.Name,
Namespace: instance.Namespace,
}
return s.create(storageclaim)
}

func (s *StorageClientReconciler) createDefaultSharedfileStorageClaim(instance *v1alpha1.StorageClient) error {
sharedfileClaim := &v1alpha1.StorageClaim{}
sharedfileClaim.Name = defaultSharedfileStorageClaim
sharedfileClaim.Spec.Type = "sharedfile"
sharedfileClaim.Spec.StorageClient = &v1alpha1.StorageClientNamespacedName{
Name: instance.Name,
Namespace: instance.Namespace,
}
return s.create(sharedfileClaim)
}

func (s *StorageClientReconciler) deleteDefaultStorageClaims(instance *v1alpha1.StorageClient) error {
if instance.GetAnnotations()[defaultClaimsOwnerAnnotationKey] == "true" {
blockClaim := &v1alpha1.StorageClaim{}
blockClaim.Name = defaultBlockStorageClaim
if err := s.delete(blockClaim); err != nil {
return fmt.Errorf("failed to remove default storageclaim %q: %v", blockClaim.Name, err)
}

sharedfsClaim := &v1alpha1.StorageClaim{}
sharedfsClaim.Name = defaultSharedfileStorageClaim
if err := s.delete(sharedfsClaim); err != nil {
return fmt.Errorf("failed to remove default storageclaim %q: %v", blockClaim.Name, err)
}
s.Log.Info("Successfully deleted default storageclaims")
}
return nil
}

func (s *StorageClientReconciler) update(obj client.Object, opts ...client.UpdateOption) error {
return s.Update(s.ctx, obj, opts...)
}

func (s *StorageClientReconciler) create(obj client.Object, opts ...client.CreateOption) error {
return s.Create(s.ctx, obj, opts...)
}

0 comments on commit cb2d1e7

Please sign in to comment.