in oracle/controllers/instancecontroller/instance_controller_standby.go [55:293]
func (r *InstanceReconciler) standbyStateMachine(ctx context.Context, inst *v1alpha1.Instance, log logr.Logger) (ctrl.Result, error) {
log.Info("Running standby DR state machine")
// Our initial state is equivalent to StandbyVerifyFailed. See state machine.
state := k8s.StandbyDRVerifyFailed
if standbyCond := k8s.FindCondition(inst.Status.Conditions, k8s.StandbyDRReady); standbyCond != nil {
state = standbyCond.Reason
}
switch state {
case k8s.StandbyDRVerifyFailed:
externalErrMsgs, err := r.verifySettings(ctx, inst)
if err != nil {
log.Error(err, "verify settings failed")
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRVerifyFailed,
"validate replication settings failed", internalErrToMsg(err))
return ctrl.Result{RequeueAfter: standbyErrorRetryInterval}, nil
}
if len(externalErrMsgs) > 0 {
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRVerifyFailed,
"validate replication settings failed", externalErrMsgs...)
return ctrl.Result{RequeueAfter: standbyErrorRetryInterval}, nil
}
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRVerifyCompleted,
"validate replication settings completed")
return ctrl.Result{Requeue: true}, nil
case k8s.StandbyDRVerifyCompleted:
inst.Status.CurrentReplicationSettings = inst.Spec.ReplicationSettings
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRCreateInProgress,
"create standby instance in progress")
return ctrl.Result{Requeue: true}, nil
case k8s.StandbyDRCreateInProgress:
if inst.Spec.ReplicationSettings == nil {
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRCreateInProgress,
replicationSettingsNilErr(inst.Status.CurrentReplicationSettings))
return ctrl.Result{}, nil
}
inst.Status.CurrentReplicationSettings = inst.Spec.ReplicationSettings
operationId := lroOperationID(createStandby, inst)
credentialReq, err := toCredentialReq(inst.Spec.ReplicationSettings.PrimaryUser)
if err != nil {
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRCreateInProgress,
"create standby instance failed", internalErrToMsg(err))
return ctrl.Result{RequeueAfter: standbyErrorRetryInterval}, nil
}
operation, err := controllers.CreateStandby(ctx, r, r.DatabaseClientFactory, inst.Namespace, inst.Name, controllers.CreateStandbyRequest{
PrimaryHost: inst.Spec.ReplicationSettings.PrimaryHost,
PrimaryPort: inst.Spec.ReplicationSettings.PrimaryPort,
PrimaryService: inst.Spec.ReplicationSettings.PrimaryServiceName,
PrimaryUser: inst.Spec.ReplicationSettings.PrimaryUser.Name,
PrimaryCredential: credentialReq,
BackupGcsPath: inst.Spec.ReplicationSettings.BackupURI,
StandbyDbDomain: inst.Spec.DBDomain,
StandbyDbUniqueName: inst.Spec.DBUniqueName,
StandbyLogDiskSize: findLogDiskSize(inst),
LroInput: &controllers.LROInput{OperationId: operationId},
})
if err != nil {
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRCreateFailed,
"create standby instance failed", internalErrToMsg(err))
return ctrl.Result{}, nil
}
if operation.GetError() != nil {
controllers.DeleteLROOperation(ctx, r.DatabaseClientFactory, r, operationId, inst.Namespace, inst.Name)
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRCreateFailed,
"create standby instance failed", operation.GetError().GetMessage())
return ctrl.Result{}, nil
} else if !operation.Done {
log.Info("create standby still in progress")
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRCreateInProgress,
"create standby instance in progress")
return ctrl.Result{RequeueAfter: StandbyReconcileInterval}, nil
}
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRCreateCompleted,
"create standby instance completed")
return ctrl.Result{}, nil
case k8s.StandbyDRCreateFailed:
return ctrl.Result{}, nil
case k8s.StandbyDRCreateCompleted:
if inst.Spec.ReplicationSettings == nil {
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRCreateCompleted,
replicationSettingsNilErr(inst.Status.CurrentReplicationSettings))
return ctrl.Result{}, nil
}
inst.Status.CurrentReplicationSettings = inst.Spec.ReplicationSettings
if err := r.reconcileDataGuard(ctx, inst); err != nil {
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRSetUpDataGuardFailed,
"set up Data Guard failed", internalErrToMsg(err))
return ctrl.Result{RequeueAfter: standbyErrorRetryInterval}, nil
}
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRSetUpDataGuardCompleted,
"set up Data Guard completed")
return ctrl.Result{Requeue: true}, nil
case k8s.StandbyDRSetUpDataGuardFailed:
if inst.Spec.ReplicationSettings == nil {
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRSetUpDataGuardFailed,
replicationSettingsNilErr(inst.Status.CurrentReplicationSettings))
return ctrl.Result{}, nil
}
inst.Status.CurrentReplicationSettings = inst.Spec.ReplicationSettings
if err := r.reconcileDataGuard(ctx, inst); err != nil {
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRSetUpDataGuardFailed,
"set up Data Guard failed", internalErrToMsg(err))
return ctrl.Result{RequeueAfter: standbyErrorRetryInterval}, nil
}
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRSetUpDataGuardCompleted,
"set up Data Guard completed")
return ctrl.Result{Requeue: true}, nil
case k8s.StandbyDRSetUpDataGuardCompleted:
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRDataGuardReplicationInProgress,
"Data Guard data replication in progress")
return ctrl.Result{Requeue: true}, nil
case k8s.StandbyDRDataGuardReplicationInProgress:
if inst.Spec.ReplicationSettings == nil {
if err := r.reconcilePromoteStandby(ctx, inst, log); err != nil {
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRPromoteFailed,
"promote standby failed", internalErrToMsg(err))
return ctrl.Result{}, nil
}
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRPromoteCompleted,
"promote standby completed")
return ctrl.Result{Requeue: true}, nil
}
if err := r.reconcileDataGuard(ctx, inst); err != nil {
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRDataGuardReplicationInProgress,
"Data Guard data replication in progress with errors", internalErrToMsg(err))
r.updateDataGuardStatus(ctx, inst, standbyErrorRetryInterval, log)
return ctrl.Result{RequeueAfter: standbyErrorRetryInterval}, nil
}
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRDataGuardReplicationInProgress,
"Data Guard data replication in progress")
r.updateDataGuardStatus(ctx, inst, StandbyReconcileInterval, log)
return ctrl.Result{RequeueAfter: StandbyReconcileInterval}, nil
case k8s.StandbyDRPromoteFailed:
if err := r.reconcilePromoteStandby(ctx, inst, log); err != nil {
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRPromoteFailed,
"promote standby failed", internalErrToMsg(err))
return ctrl.Result{RequeueAfter: standbyErrorRetryInterval}, nil
}
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRPromoteCompleted,
"promote standby completed")
return ctrl.Result{Requeue: true}, nil
case k8s.StandbyDRPromoteCompleted, k8s.StandbyDRBootstrapFailed:
inst.Status.CurrentReplicationSettings = nil
inst.Status.DataGuardOutput = nil
err := r.bootstrapStandby(ctx, inst)
if err != nil {
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionFalse,
k8s.StandbyDRBootstrapFailed,
"bootstrap standby failed", internalErrToMsg(err))
return ctrl.Result{RequeueAfter: standbyErrorRetryInterval}, nil
}
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionTrue,
k8s.StandbyDRBootstrapCompleted,
"bootstrap standby completed")
k8s.InstanceUpsertCondition(&inst.Status, k8s.Ready,
metav1.ConditionTrue, k8s.CreateComplete,
"bootstrap standby completed")
k8s.InstanceUpsertCondition(&inst.Status, k8s.DatabaseInstanceReady,
metav1.ConditionTrue, k8s.CreateComplete,
"bootstrap standby completed")
return ctrl.Result{Requeue: true}, nil
case k8s.StandbyDRBootstrapCompleted:
r.updateStandbyDataReplicationStatus(ctx,
inst, metav1.ConditionTrue,
k8s.StandbyDRBootstrapCompleted,
"bootstrap standby completed")
k8s.InstanceUpsertCondition(&inst.Status, k8s.Ready,
metav1.ConditionTrue, k8s.CreateComplete,
"bootstrap standby completed")
k8s.InstanceUpsertCondition(&inst.Status, k8s.DatabaseInstanceReady,
metav1.ConditionTrue, k8s.CreateComplete,
"bootstrap standby completed")
return ctrl.Result{Requeue: true}, nil
default:
log.Info("standbyStateMachine: no action needed, proceed with main reconciliation", "unknown state", state)
return ctrl.Result{}, nil
}
}