Skip to content

Commit eadd47f

Browse files
committed
Merge branch 'idesai_dg_bugs' into 'master'
Dataguard Bugs Resolution See merge request rac-docker-dev/oracle-database-operator!249
2 parents 1cf7f53 + 481d608 commit eadd47f

File tree

6 files changed

+154
-26
lines changed

6 files changed

+154
-26
lines changed

commons/database/constants.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ const StandbyDatabasePrerequisitesSQL string = "ALTER SYSTEM SET db_create_file_
104104
"\nALTER SYSTEM SET STANDBY_FILE_MANAGEMENT=AUTO;" +
105105
"\nALTER SYSTEM SET dg_broker_start=TRUE;"
106106

107+
const GetDBOpenMode string = "select open_mode from v\\$database;"
108+
109+
const ModifyStdbyDBOpenMode string = "alter database recover managed standby database disconnect;"
110+
107111
const StandbyTnsnamesEntry string = `
108112
##STANDBYDATABASE_SID## =
109113
(DESCRIPTION =
@@ -208,6 +212,9 @@ const DataguardBrokerAddDBMaxAvailabilityCMD string = "ADD DATABASE ${ORACLE_SID
208212
"(CONNECT_DATA=(SERVICE_NAME=${ORACLE_SID}_DGMGRL)(INSTANCE_NAME=${ORACLE_SID})(SERVER=DEDICATED)))';" +
209213
"\nENABLE CONFIGURATION;"
210214

215+
const RemoveStandbyDBFromDGConfgCMD string = "DISABLE DATABASE ${ORACLE_SID};" +
216+
"\nREMOVE DATABASE ${ORACLE_SID};"
217+
211218
const DBShowConfigCMD string = "SHOW CONFIGURATION;"
212219

213220
const DataguardBrokerGetDatabaseCMD string = "SELECT DATABASE || ':' || DATAGUARD_ROLE AS DATABASE FROM V\\$DG_BROKER_CONFIG;"

commons/database/utils.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,26 @@ func GetDatabaseRole(readyPod corev1.Pod, r client.Reader,
505505
return "", errors.New("database role is nil")
506506
}
507507

508+
func GetDatabaseOpenMode(readyPod corev1.Pod, r client.Reader,
509+
config *rest.Config, ctx context.Context, req ctrl.Request, edition string) (string, error) {
510+
log := ctrllog.FromContext(ctx).WithValues("GetDatabaseOpenMode",req.NamespacedName)
511+
512+
out,err := ExecCommand(r, config, readyPod.Name, readyPod.Namespace, "", ctx, req, false, "bash", "-c",
513+
fmt.Sprintf("echo -e \"%s\" | %s",GetDBOpenMode,SQLPlusCLI))
514+
if err != nil {
515+
return "",err
516+
}
517+
log.Info(out)
518+
if !strings.Contains(out, "no rows selected") && !strings.Contains(out, "ORA-") {
519+
out1 := strings.Replace(out, " ", "_", -1)
520+
// filtering output and storing databse_role in "database_role"
521+
databaseOpenMode := strings.Fields(out1)[2]
522+
// first 2 values in the slice will be column name(DATABASE_ROLE) and a seperator(--------------) .
523+
return databaseOpenMode, nil
524+
}
525+
return "", errors.New("database open mode is nil")
526+
}
527+
508528
// Returns true if any of the pod in 'pods' is with pod.Status.Phase == phase
509529
func IsAnyPodWithStatus(pods []corev1.Pod, phase corev1.PodPhase) (bool, corev1.Pod) {
510530
anyPodWithPhase := false

config/samples/sidb/dataguardbroker.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,5 @@ spec:
2525
## Protection Mode for dg configuration . MaxAvailability or MaxPerformance
2626
protectionMode: MaxAvailability
2727

28-
## Manual Switchover to this database to make it primary(if not already) .
28+
## Manual Switchover to this database to make it primary(if not already), requires target Database SID .
2929
setAsPrimaryDatabase: ""

controllers/database/dataguardbroker_controller.go

Lines changed: 101 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ func (r *DataguardBrokerReconciler) setupDataguardBrokerConfiguration(m *dbapi.D
403403

404404
// Update Databases
405405
r.updateReconcileStatus(m, sidbReadyPod, ctx, req)
406-
}
406+
}
407407

408408
eventReason := "DG Configuration up to date"
409409
eventMsg := ""
@@ -657,26 +657,28 @@ func (r *DataguardBrokerReconciler) setupDataguardBrokerConfigurationForGivenDB(
657657
}
658658

659659
// ## SET PROPERTY FASTSTARTFAILOVERTARGET FOR EACH DATABASE TO ALL OTHER DATABASES IN DG CONFIG .
660-
for i := 0; i < len(databases); i++ {
661-
out, err = dbcommons.ExecCommand(r, r.Config, standbyDatabaseReadyPod.Name, standbyDatabaseReadyPod.Namespace, "", ctx, req, false, "bash", "-c",
662-
fmt.Sprintf("dgmgrl sys@%s \"EDIT DATABASE %s SET PROPERTY FASTSTARTFAILOVERTARGET=%s\"< admin.pwd", primaryConnectString,
663-
strings.Split(databases[i], ":")[0], getFSFOTargets(i, databases)))
664-
if err != nil {
665-
log.Error(err, err.Error())
666-
return requeueY
667-
}
668-
log.Info("SETTING FSFO TARGET OUTPUT")
669-
log.Info(out)
660+
if (m.Spec.FastStartFailOver.Enable == true){
661+
for i := 0; i < len(databases); i++ {
662+
out, err = dbcommons.ExecCommand(r, r.Config, standbyDatabaseReadyPod.Name, standbyDatabaseReadyPod.Namespace, "", ctx, req, false, "bash", "-c",
663+
fmt.Sprintf("dgmgrl sys@%s \"EDIT DATABASE %s SET PROPERTY FASTSTARTFAILOVERTARGET=%s\"< admin.pwd", primaryConnectString,
664+
strings.Split(databases[i], ":")[0], getFSFOTargets(i, databases)))
665+
if err != nil {
666+
log.Error(err, err.Error())
667+
return requeueY
668+
}
669+
log.Info("SETTING FSFO TARGET OUTPUT")
670+
log.Info(out)
670671

671-
out, err = dbcommons.ExecCommand(r, r.Config, standbyDatabaseReadyPod.Name, standbyDatabaseReadyPod.Namespace, "", ctx, req, false, "bash", "-c",
672-
fmt.Sprintf("dgmgrl sys@%s \"SHOW DATABASE %s FASTSTARTFAILOVERTARGET\" < admin.pwd", primaryConnectString, strings.Split(databases[i], ":")[0]))
673-
if err != nil {
674-
log.Error(err, err.Error())
675-
return requeueY
676-
}
677-
log.Info("FSFO TARGETS OF " + databases[i])
678-
log.Info(out)
672+
out, err = dbcommons.ExecCommand(r, r.Config, standbyDatabaseReadyPod.Name, standbyDatabaseReadyPod.Namespace, "", ctx, req, false, "bash", "-c",
673+
fmt.Sprintf("dgmgrl sys@%s \"SHOW DATABASE %s FASTSTARTFAILOVERTARGET\" < admin.pwd", primaryConnectString, strings.Split(databases[i], ":")[0]))
674+
if err != nil {
675+
log.Error(err, err.Error())
676+
return requeueY
677+
}
678+
log.Info("FSFO TARGETS OF " + databases[i])
679+
log.Info(out)
679680

681+
}
680682
}
681683
// Remove admin pwd file
682684
_, err = dbcommons.ExecCommand(r, r.Config, standbyDatabaseReadyPod.Name, standbyDatabaseReadyPod.Namespace, "", ctx, req, true, "bash", "-c",
@@ -694,6 +696,59 @@ func (r *DataguardBrokerReconciler) setupDataguardBrokerConfigurationForGivenDB(
694696
return requeueN
695697
}
696698

699+
// #############################################################################
700+
//
701+
// Remove up DG Configuration for a given StandbyDatabase - To be Tested
702+
//
703+
// #############################################################################
704+
func (r *DataguardBrokerReconciler) removeDataguardBrokerConfigurationForGivenDB( m *dbapi.DataguardBroker,n *dbapi.SingleInstanceDatabase,standbyDatabase *dbapi.SingleInstanceDatabase, standbyDatabaseReadyPod corev1.Pod, sidbReadyPod corev1.Pod, ctx context.Context, req ctrl.Request) ctrl.Result {
705+
log := r.Log.WithValues("removeDataguardBrokerConfigurationForGivenDB", req.NamespacedName)
706+
707+
if standbyDatabaseReadyPod.Name == "" || sidbReadyPod.Name == ""{
708+
return requeueY
709+
}
710+
711+
// ## CHECK IF DG CONFIGURATION IS AVAILABLE IN PRIMARY DATABASE ##
712+
out, err := dbcommons.ExecCommand(r, r.Config, sidbReadyPod.Name, sidbReadyPod.Namespace, "", ctx, req, false, "bash", "-c",
713+
fmt.Sprintf("echo -e \"%s\" | dgmgrl / as sysdba", dbcommons.DBShowConfigCMD))
714+
715+
if err != nil {
716+
log.Error(err, err.Error())
717+
return requeueY
718+
}
719+
log.Info("Showconfiguration Output")
720+
log.Info(out)
721+
722+
if strings.Contains(out, "ORA-16525") {
723+
log.Info("ORA-16525: The Oracle Data Guard broker is not yet available on Primary")
724+
return requeueY
725+
}
726+
727+
// ## REMOVING STANDBY DATABASE FROM DG CONFIGURATION ##
728+
out, err = dbcommons.ExecCommand(r, r.Config, sidbReadyPod.Name, sidbReadyPod.Namespace, "", ctx, req, false, "bash", "-c",
729+
fmt.Sprintf(dbcommons.CreateDGMGRLScriptFile, dbcommons.RemoveStandbyDBFromDGConfgCMD))
730+
731+
if err != nil {
732+
log.Error(err, err.Error())
733+
return requeueY
734+
}
735+
736+
// ## SHOW CONFIGURATION
737+
out, err = dbcommons.ExecCommand(r, r.Config, sidbReadyPod.Name, sidbReadyPod.Namespace, "", ctx, req, false, "bash", "-c",
738+
fmt.Sprintf("echo -e \"%s\" | dgmgrl / as sysdba", dbcommons.DBShowConfigCMD))
739+
if err != nil {
740+
log.Error(err, err.Error())
741+
return requeueY
742+
}
743+
log.Info("Showconfiguration Output")
744+
log.Info(out)
745+
// Set DG Configured status to false for this standbyDatabase. so that in next reconcilation, we dont configure this again
746+
standbyDatabase.Status.DgBrokerConfigured = false
747+
r.Status().Update(ctx, standbyDatabase)
748+
749+
return requeueN
750+
}
751+
697752
// #############################################################################
698753
//
699754
// Return FSFO targets of each StandbyDatabase
@@ -976,6 +1031,33 @@ func (r *DataguardBrokerReconciler) manageDataguardBrokerDeletion(req ctrl.Reque
9761031
// indicated by the deletion timestamp being set.
9771032
isDataguardBrokerMarkedToBeDeleted := m.GetDeletionTimestamp() != nil
9781033
if isDataguardBrokerMarkedToBeDeleted {
1034+
1035+
// Make a singleinstancedatabase with empty
1036+
singleInstanceDatabase := &dbapi.SingleInstanceDatabase{}
1037+
err := r.Get(ctx, types.NamespacedName{Namespace: req.Namespace, Name: m.Spec.PrimaryDatabaseRef}, singleInstanceDatabase)
1038+
if err != nil {
1039+
log.Error(err,err.Error())
1040+
return requeueY,err
1041+
}
1042+
// Get its POD
1043+
// Validate if Primary Database Reference is ready
1044+
result, sidbReadyPod, _ := r.validateSidbReadiness(m, singleInstanceDatabase, ctx, req)
1045+
if result.Requeue {
1046+
log.Info("Reconcile queued")
1047+
return result, nil
1048+
}
1049+
// Get its Role
1050+
out, err := dbcommons.GetDatabaseRole(sidbReadyPod, r, r.Config, ctx, req, singleInstanceDatabase.Spec.Edition)
1051+
// check if its PRIMARY
1052+
if strings.ToUpper(out) != "PRIMARY" {
1053+
eventReason := "Deletion"
1054+
eventMsg := "DataGuard Broker cannot be deleted since primaryDatabaseRef is not in PRIMARY role"
1055+
log.Info("DataGuard Broker cannot be deleted since primaryDatabaseRef is not in PRIMARY role")
1056+
r.Recorder.Eventf(m, corev1.EventTypeWarning, eventReason, eventMsg)
1057+
return requeueN, nil
1058+
}
1059+
// if not PRIMARY throw error and log it
1060+
9791061
if controllerutil.ContainsFinalizer(m, dataguardBrokerFinalizer) {
9801062
// Run finalization logic for dataguardBrokerFinalizer. If the
9811063
// finalization logic fails, don't remove the finalizer so

controllers/database/singleinstancedatabase_controller.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,24 @@ func (r *SingleInstanceDatabaseReconciler) Reconcile(ctx context.Context, req ct
229229
if err != nil {
230230
return requeueY, err
231231
}
232+
233+
databaseOpenMode,err := dbcommons.GetDatabaseOpenMode(readyPod, r, r.Config, ctx, req, singleInstanceDatabase.Spec.Edition)
234+
235+
if err != nil {
236+
r.Log.Error(err, err.Error())
237+
return requeueY, err
238+
}
239+
r.Log.Info("DB openMode Output")
240+
r.Log.Info(databaseOpenMode)
241+
if databaseOpenMode == "READ_ONLY" {
242+
out, err := dbcommons.ExecCommand(r, r.Config, readyPod.Name, readyPod.Namespace, "", ctx, req, false, "bash", "-c",fmt.Sprintf("echo -e \"%s\" | %s",dbcommons.ModifyStdbyDBOpenMode,dbcommons.SQLPlusCLI))
243+
if err != nil {
244+
r.Log.Error(err, err.Error())
245+
return requeueY, err
246+
}
247+
r.Log.Info("Standby DB open mode modified")
248+
r.Log.Info(out)
249+
}
232250

233251
singleInstanceDatabase.Status.PrimaryDatabase = referredPrimaryDatabase.Name
234252
// Store all standbyDatabase sid:name in a map to use it during manual switchover.
@@ -498,6 +516,7 @@ func (r *SingleInstanceDatabaseReconciler) validate(m *dbapi.SingleInstanceDatab
498516
if m.Spec.Sid == rp.Spec.Sid {
499517
r.Log.Info("Standby database SID can not be same as the Primary database SID")
500518
r.Recorder.Eventf(m, corev1.EventTypeWarning, "Spec Error", "Standby and Primary database SID can not be same")
519+
m.Status.Status = dbcommons.StatusError
501520
return requeueY, err
502521
}
503522

docs/sidb/README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -735,16 +735,16 @@ $ kubectl apply -f dataguardbroker.yaml
735735
dataguardbroker.database.oracle.com/dataguardbroker-sample apply
736736
737737
```
738+
Or use the patch command
738739

739-
#### Patching DataGuardBroker Attributes
740+
```sh
741+
$ kubectl --type=merge -p '{"spec":{"setAsPrimaryDatabase":"ORCLS1"}}' patch dataguardbroker dataguardbroker-sample
740742
741-
The following attributes cannot be patched post DataguardBroker resource Creation : `primaryDatabaseRef, standbyDatabaseRefs, loadBalancer`.
743+
dataguardbroker.database.oracle.com/dataguardbroker-sample patched
744+
```
742745

743-
```sh
744-
$ kubectl --type=merge -p '{"spec":{"primaryDatabaseRef":"ORCL"}}' patch dataguardbroker dataguardbroker-sample
746+
**NOTE :** The following attributes cannot be patched post DataguardBroker resource Creation : `primaryDatabaseRef, protectionMode`.
745747

746-
The DataguardBroker "dataguardbroker-sample" is invalid: spec.sid: Forbidden: cannot be changed
747-
```
748748

749749
#### Delete DataguardBroker Resource
750750

0 commit comments

Comments
 (0)