From 18e82f6bc2ca803899b34b9c059e31738b2f750b Mon Sep 17 00:00:00 2001 From: Aleksei Kobzev Date: Thu, 25 Apr 2024 12:48:40 +0200 Subject: [PATCH] step Initializing before Provisioning --- docs/storage-state-machine-schema.drawio.png | Bin 29920 -> 34423 bytes e2e/tests/smoke_test.go | 10 ++-- internal/controllers/constants/constants.go | 28 +++++----- internal/controllers/database/init.go | 42 +++++++++------ internal/controllers/database/sync.go | 42 +++++++++------ .../databasenodeset/controller_test.go | 4 +- .../remotedatabasenodeset/controller_test.go | 4 +- .../remotestoragenodeset/controller_test.go | 2 +- internal/controllers/storage/init.go | 31 +++++++---- internal/controllers/storage/sync.go | 50 ++++++++++-------- 10 files changed, 129 insertions(+), 84 deletions(-) diff --git a/docs/storage-state-machine-schema.drawio.png b/docs/storage-state-machine-schema.drawio.png index bb43a5572475c9c3fabb2ef99370157594bc872c..201a990542e153fb58c1009dd20ab8ad263462a1 100644 GIT binary patch literal 34423 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 T))eqBONA`<9>5eBJ74}cbm!@* diff --git a/e2e/tests/smoke_test.go b/e2e/tests/smoke_test.go index 81eafdb2..9b500958 100644 --- a/e2e/tests/smoke_test.go +++ b/e2e/tests/smoke_test.go @@ -102,7 +102,7 @@ func waitUntilDatabaseReady(ctx context.Context, databaseName, databaseNamespace return meta.IsStatusConditionPresentAndEqual( database.Status.Conditions, - DatabaseTenantInitializedCondition, + DatabaseInitializedCondition, metav1.ConditionTrue, ) && database.Status.State == testobjects.ReadyStatus }, Timeout, Interval).Should(BeTrue()) @@ -521,7 +521,7 @@ var _ = Describe("Operator smoke test", func() { checkPodsRunningAndReady(ctx, "ydb-cluster", "kind-storage", storageSample.Spec.Nodes) }) - It("storage.State goes Pending -> Preparing -> Provisioning -> Initializing -> Ready", func() { + It("storage.State goes Pending -> Preparing -> Initializing -> Provisioning -> Ready", func() { Expect(k8sClient.Create(ctx, storageSample)).Should(Succeed()) defer func() { Expect(k8sClient.Delete(ctx, storageSample)).Should(Succeed()) @@ -537,9 +537,9 @@ var _ = Describe("Operator smoke test", func() { allowedChanges := map[ClusterState]ClusterState{ StoragePending: StoragePreparing, - StoragePreparing: StorageProvisioning, - StorageProvisioning: StorageInitializing, - StorageInitializing: StorageReady, + StoragePreparing: StorageInitializing, + StorageInitializing: StorageProvisioning, + StorageProvisioning: StorageReady, } re := regexp.MustCompile(`Storage moved from ([a-zA-Z]+) to ([a-zA-Z]+)`) diff --git a/internal/controllers/constants/constants.go b/internal/controllers/constants/constants.go index 48a73002..819745be 100644 --- a/internal/controllers/constants/constants.go +++ b/internal/controllers/constants/constants.go @@ -15,13 +15,17 @@ const ( DatabaseNodeSetKind = "DatabaseNodeSet" RemoteDatabaseNodeSetKind = "RemoteDatabaseNodeSet" - StoragePausedCondition = "StoragePaused" - StorageInitializedCondition = "StorageReady" - StorageNodeSetReadyCondition = "StorageNodeSetReady" - DatabasePausedCondition = "DatabasePaused" - DatabaseTenantInitializedCondition = "TenantInitialized" - DatabaseNodeSetReadyCondition = "DatabaseNodeSetReady" - RemoteResourceSyncedCondition = "ResourceSynced" + // For backward compatibility + OldStorageInitializedCondition = "StorageReady" + OldDatabaseInitializedCondition = "TenantInitialized" + + StoragePausedCondition = "StoragePaused" + StorageInitializedCondition = "StorageInitialized" + StorageNodeSetReadyCondition = "StorageNodeSetReady" + DatabasePausedCondition = "DatabasePaused" + DatabaseInitializedCondition = "DatabaseInitialized" + DatabaseNodeSetReadyCondition = "DatabaseNodeSetReady" + RemoteResourceSyncedCondition = "ResourceSynced" Stop = true Continue = false @@ -30,10 +34,11 @@ const ( ReasonNotRequired = "NotRequired" ReasonCompleted = "Completed" - DefaultRequeueDelay = 10 * time.Second - StatusUpdateRequeueDelay = 1 * time.Second - SelfCheckRequeueDelay = 30 * time.Second - StorageInitializationRequeueDelay = 5 * time.Second + DefaultRequeueDelay = 10 * time.Second + StatusUpdateRequeueDelay = 1 * time.Second + SelfCheckRequeueDelay = 30 * time.Second + StorageInitializationRequeueDelay = 30 * time.Second + DatabaseInitializationRequeueDelay = 30 * time.Second DatabasePending ClusterState = "Pending" DatabasePreparing ClusterState = "Preparing" @@ -62,7 +67,6 @@ const ( ResourceSyncPending RemoteResourceState = "Pending" ResourceSyncSuccess RemoteResourceState = "Synced" - TenantCreationRequeueDelay = 30 * time.Second StorageAwaitRequeueDelay = 30 * time.Second SharedDatabaseAwaitRequeueDelay = 30 * time.Second diff --git a/internal/controllers/database/init.go b/internal/controllers/database/init.go index 3de92d90..25e91903 100644 --- a/internal/controllers/database/init.go +++ b/internal/controllers/database/init.go @@ -44,21 +44,32 @@ func (r *Reconciler) setInitialStatus( ) (bool, ctrl.Result, error) { r.Log.Info("running step setInitialStatus") + if meta.IsStatusConditionTrue(database.Status.Conditions, OldDatabaseInitializedCondition) { + meta.SetStatusCondition(&database.Status.Conditions, metav1.Condition{ + Type: DatabaseInitializedCondition, + Status: "True", + Reason: ReasonCompleted, + Message: "Database initialized successfully", + }) + database.Status.State = DatabaseReady + return r.updateStatus(ctx, database) + } + if value, ok := database.Annotations[v1alpha1.AnnotationSkipInitialization]; ok && value == v1alpha1.AnnotationValueTrue { - if meta.FindStatusCondition(database.Status.Conditions, DatabaseTenantInitializedCondition) == nil || - meta.IsStatusConditionFalse(database.Status.Conditions, DatabaseTenantInitializedCondition) { + if meta.FindStatusCondition(database.Status.Conditions, DatabaseInitializedCondition) == nil || + meta.IsStatusConditionFalse(database.Status.Conditions, DatabaseInitializedCondition) { return r.processSkipInitPipeline(ctx, database) } return Stop, ctrl.Result{RequeueAfter: DefaultRequeueDelay}, nil } if database.Status.State == DatabasePending || - meta.FindStatusCondition(database.Status.Conditions, DatabaseTenantInitializedCondition) == nil { + meta.FindStatusCondition(database.Status.Conditions, DatabaseInitializedCondition) == nil { meta.SetStatusCondition(&database.Status.Conditions, metav1.Condition{ - Type: DatabaseTenantInitializedCondition, + Type: DatabaseInitializedCondition, Status: "False", Reason: ReasonInProgress, - Message: "Tenant creation in progress", + Message: "Database has not been initialized yet", }) database.Status.State = DatabasePreparing return r.updateStatus(ctx, database) @@ -73,21 +84,26 @@ func (r *Reconciler) setInitDatabaseCompleted( message string, ) (bool, ctrl.Result, error) { meta.SetStatusCondition(&database.Status.Conditions, metav1.Condition{ - Type: DatabaseTenantInitializedCondition, + Type: DatabaseInitializedCondition, Status: "True", Reason: ReasonCompleted, Message: message, }) + database.Status.State = DatabaseProvisioning - database.Status.State = DatabaseReady return r.updateStatus(ctx, database) } -func (r *Reconciler) handleTenantCreation( +func (r *Reconciler) initializeDatabase( ctx context.Context, database *resources.DatabaseBuilder, ) (bool, ctrl.Result, error) { - r.Log.Info("running step handleTenantCreation") + r.Log.Info("running step initializeDatabase") + + if database.Status.State == DatabasePreparing { + database.Status.State = DatabaseInitializing + return r.updateStatus(ctx, database) + } path := database.GetDatabasePath() var storageUnits []v1alpha1.StorageUnit @@ -197,7 +213,7 @@ func (r *Reconciler) handleTenantCreation( "InitializingFailed", fmt.Sprintf("Error creating tenant %s: %s", tenant.Path, err), ) - return Stop, ctrl.Result{RequeueAfter: TenantCreationRequeueDelay}, err + return Stop, ctrl.Result{RequeueAfter: DatabaseInitializationRequeueDelay}, err } r.Recorder.Event( database, @@ -213,9 +229,5 @@ func (r *Reconciler) handleTenantCreation( "Database is initialized", ) - return r.setInitDatabaseCompleted( - ctx, - database, - "Database initialization is completed", - ) + return r.setInitDatabaseCompleted(ctx, database, "Database initialized successfully") } diff --git a/internal/controllers/database/sync.go b/internal/controllers/database/sync.go index 60cb1ef7..e2524229 100644 --- a/internal/controllers/database/sync.go +++ b/internal/controllers/database/sync.go @@ -62,8 +62,28 @@ func (r *Reconciler) Sync(ctx context.Context, ydbCr *v1alpha1.Database) (ctrl.R return result, err } - if !meta.IsStatusConditionTrue(database.Status.Conditions, DatabaseTenantInitializedCondition) { - return r.handleFirstStart(ctx, &database) + if !meta.IsStatusConditionTrue(database.Status.Conditions, DatabaseInitializedCondition) { + return r.handleTenantCreation(ctx, &database) + } + + if database.Spec.NodeSets != nil { + stop, result, err = r.waitForDatabaseNodeSetsToReady(ctx, &database) + if stop { + return result, err + } + } else { + stop, result, err = r.waitForStatefulSetToScale(ctx, &database) + if stop { + return result, err + } + } + + if database.Status.State != DatabaseReady { + database.Status.State = DatabaseReady + stop, result, err = r.updateStatus(ctx, &database) + if stop { + return result, err + } } return ctrl.Result{}, nil @@ -130,7 +150,7 @@ func (r *Reconciler) waitForDatabaseNodeSetsToReady( ) (bool, ctrl.Result, error) { r.Log.Info("running step waitForDatabaseNodeSetToReady") - if database.Status.State == DatabasePreparing { + if database.Status.State == DatabaseInitializing { r.Recorder.Event( database, corev1.EventTypeNormal, @@ -552,7 +572,7 @@ func (r *Reconciler) handlePauseResume( return Continue, ctrl.Result{}, nil } -func (r *Reconciler) handleFirstStart( +func (r *Reconciler) handleTenantCreation( ctx context.Context, database *resources.DatabaseBuilder, ) (ctrl.Result, error) { @@ -561,19 +581,7 @@ func (r *Reconciler) handleFirstStart( return result, err } - if database.Spec.NodeSets != nil { - stop, result, err = r.waitForDatabaseNodeSetsToReady(ctx, database) - if stop { - return result, err - } - } else { - stop, result, err = r.waitForStatefulSetToScale(ctx, database) - if stop { - return result, err - } - } - - stop, result, err = r.handleTenantCreation(ctx, database) + stop, result, err = r.initializeDatabase(ctx, database) if stop { return result, err } diff --git a/internal/controllers/databasenodeset/controller_test.go b/internal/controllers/databasenodeset/controller_test.go index 1c732243..2bfe3b11 100644 --- a/internal/controllers/databasenodeset/controller_test.go +++ b/internal/controllers/databasenodeset/controller_test.go @@ -80,7 +80,7 @@ var _ = Describe("DatabaseNodeSet controller medium tests", func() { Name: storageSample.Name, Namespace: testobjects.YdbNamespace, }, &foundStorage)) - return foundStorage.Status.State == StorageProvisioning + return foundStorage.Status.State == StorageInitializing }, test.Timeout, test.Interval).Should(BeTrue()) By("set status Ready to Storage...") @@ -111,7 +111,7 @@ var _ = Describe("DatabaseNodeSet controller medium tests", func() { Name: databaseSample.Name, Namespace: testobjects.YdbNamespace, }, &foundDatabase)) - return foundDatabase.Status.State == DatabaseProvisioning + return foundDatabase.Status.State == DatabaseInitializing }, test.Timeout, test.Interval).Should(BeTrue()) By("checking that DatabaseNodeSet created on local cluster...") diff --git a/internal/controllers/remotedatabasenodeset/controller_test.go b/internal/controllers/remotedatabasenodeset/controller_test.go index eb1064fb..d67f9371 100644 --- a/internal/controllers/remotedatabasenodeset/controller_test.go +++ b/internal/controllers/remotedatabasenodeset/controller_test.go @@ -247,7 +247,7 @@ var _ = Describe("RemoteDatabaseNodeSet controller tests", func() { Name: storageSample.Name, Namespace: testobjects.YdbNamespace, }, &foundStorage)) - return foundStorage.Status.State == StorageProvisioning + return foundStorage.Status.State == StorageInitializing }, test.Timeout, test.Interval).Should(BeTrue()) By("set status Ready to Storage...") @@ -270,7 +270,7 @@ var _ = Describe("RemoteDatabaseNodeSet controller tests", func() { Name: databaseSample.Name, Namespace: testobjects.YdbNamespace, }, &foundDatabase)) - return foundDatabase.Status.State == DatabaseProvisioning + return foundDatabase.Status.State == DatabaseInitializing }, test.Timeout, test.Interval).Should(BeTrue()) By("checking that DatabaseNodeSet created on local cluster...") diff --git a/internal/controllers/remotestoragenodeset/controller_test.go b/internal/controllers/remotestoragenodeset/controller_test.go index 87d94a83..71d6faa5 100644 --- a/internal/controllers/remotestoragenodeset/controller_test.go +++ b/internal/controllers/remotestoragenodeset/controller_test.go @@ -234,7 +234,7 @@ var _ = Describe("RemoteStorageNodeSet controller tests", func() { Name: storageSample.Name, Namespace: testobjects.YdbNamespace, }, &foundStorage)) - return foundStorage.Status.State == StorageProvisioning + return foundStorage.Status.State == StorageInitializing }, test.Timeout, test.Interval).Should(BeTrue()) By("checking that StorageNodeSet created on local cluster...") diff --git a/internal/controllers/storage/init.go b/internal/controllers/storage/init.go index 4b85a222..b20628cb 100644 --- a/internal/controllers/storage/init.go +++ b/internal/controllers/storage/init.go @@ -42,11 +42,14 @@ func (r *Reconciler) processSkipInitPipeline( "Skipping initialization due to skip annotation present, be careful!", ) - return r.setInitStorageCompleted( - ctx, - storage, - "Storage initialization not performed because initialization is skipped", - ) + meta.SetStatusCondition(&storage.Status.Conditions, metav1.Condition{ + Type: StorageInitializedCondition, + Status: "True", + Reason: ReasonCompleted, + Message: "Storage initialization not performed because initialization is skipped", + }) + storage.Status.State = StorageReady + return r.updateStatus(ctx, storage) } func (r *Reconciler) setInitialStatus( @@ -55,6 +58,17 @@ func (r *Reconciler) setInitialStatus( ) (bool, ctrl.Result, error) { r.Log.Info("running step setInitialStatus") + if meta.IsStatusConditionTrue(storage.Status.Conditions, OldStorageInitializedCondition) { + meta.SetStatusCondition(&storage.Status.Conditions, metav1.Condition{ + Type: StorageInitializedCondition, + Status: "True", + Reason: ReasonCompleted, + Message: "Storage initialized successfully", + }) + storage.Status.State = StorageReady + return r.updateStatus(ctx, storage) + } + // This block is special internal logic that skips all Storage initialization. // It is needed when large clusters are migrated where `waitForStatefulSetToScale` // does not make sense, since some nodes can be down for a long time (and it is okay, since @@ -73,7 +87,7 @@ func (r *Reconciler) setInitialStatus( Type: StorageInitializedCondition, Status: "False", Reason: ReasonInProgress, - Message: "Storage is not ready yet", + Message: "Storage has not been initialized yet", }) storage.Status.State = StoragePreparing return r.updateStatus(ctx, storage) @@ -92,8 +106,7 @@ func (r *Reconciler) setInitStorageCompleted( Reason: ReasonCompleted, Message: message, }) - - storage.Status.State = StorageReady + storage.Status.State = StorageProvisioning return r.updateStatus(ctx, storage) } @@ -103,7 +116,7 @@ func (r *Reconciler) initializeStorage( ) (bool, ctrl.Result, error) { r.Log.Info("running step initializeStorage") - if storage.Status.State == StorageProvisioning { + if storage.Status.State == StoragePreparing { storage.Status.State = StorageInitializing return r.updateStatus(ctx, storage) } diff --git a/internal/controllers/storage/sync.go b/internal/controllers/storage/sync.go index 2147a4fa..79d69466 100644 --- a/internal/controllers/storage/sync.go +++ b/internal/controllers/storage/sync.go @@ -56,7 +56,32 @@ func (r *Reconciler) Sync(ctx context.Context, cr *v1alpha1.Storage) (ctrl.Resul } if !meta.IsStatusConditionTrue(storage.Status.Conditions, StorageInitializedCondition) { - return r.handleFirstStart(ctx, &storage) + return r.handleBlobstorageInit(ctx, &storage) + } + + if storage.Spec.NodeSets != nil { + stop, result, err = r.waitForStorageNodeSetsToReady(ctx, &storage) + if stop { + return result, err + } + } else { + stop, result, err = r.waitForStatefulSetToScale(ctx, &storage) + if stop { + return result, err + } + } + + stop, result, err = r.runSelfCheck(ctx, &storage, false) + if stop { + return result, err + } + + if storage.Status.State != StorageReady { + storage.Status.State = StorageReady + stop, result, err = r.updateStatus(ctx, &storage) + if stop { + return result, err + } } return ctrl.Result{}, nil @@ -68,7 +93,7 @@ func (r *Reconciler) waitForStatefulSetToScale( ) (bool, ctrl.Result, error) { r.Log.Info("running step waitForStatefulSetToScale") - if storage.Status.State == StoragePreparing { + if storage.Status.State == StorageInitializing { r.Recorder.Event( storage, corev1.EventTypeNormal, @@ -156,7 +181,7 @@ func (r *Reconciler) waitForStorageNodeSetsToReady( ) (bool, ctrl.Result, error) { r.Log.Info("running step waitForStorageNodeSetToReady") - if storage.Status.State == StoragePreparing { + if storage.Status.State == StorageInitializing { r.Recorder.Event( storage, corev1.EventTypeNormal, @@ -541,7 +566,7 @@ func (r *Reconciler) handlePauseResume( return Continue, ctrl.Result{}, nil } -func (r *Reconciler) handleFirstStart( +func (r *Reconciler) handleBlobstorageInit( ctx context.Context, storage *resources.StorageClusterBuilder, ) (ctrl.Result, error) { @@ -550,28 +575,11 @@ func (r *Reconciler) handleFirstStart( return result, err } - if storage.Spec.NodeSets != nil { - stop, result, err = r.waitForStorageNodeSetsToReady(ctx, storage) - if stop { - return result, err - } - } else { - stop, result, err = r.waitForStatefulSetToScale(ctx, storage) - if stop { - return result, err - } - } - stop, result, err = r.initializeStorage(ctx, storage) if stop { return result, err } - stop, result, err = r.runSelfCheck(ctx, storage, false) - if stop { - return result, err - } - return ctrl.Result{}, nil }