diff --git a/go/inst/analysis.go b/go/inst/analysis.go index a473b813f..78a3973c8 100644 --- a/go/inst/analysis.go +++ b/go/inst/analysis.go @@ -64,6 +64,7 @@ const ( DifferentGTIDModesStructureWarning = "DifferentGTIDModesStructureWarning" ErrantGTIDStructureWarning = "ErrantGTIDStructureWarning" NoFailoverSupportStructureWarning = "NoFailoverSupportStructureWarning" + NoWriteableMasterStructureWarning = "NoWriteableMasterStructureWarning" ) type InstanceAnalysis struct { @@ -148,6 +149,7 @@ type ReplicationAnalysis struct { MaxReplicaGTIDMode string MaxReplicaGTIDErrant string CommandHint string + IsReadOnly bool } type AnalysisMap map[string](*ReplicationAnalysis) diff --git a/go/inst/analysis_dao.go b/go/inst/analysis_dao.go index ad8467ea0..1a9e3c0ec 100644 --- a/go/inst/analysis_dao.go +++ b/go/inst/analysis_dao.go @@ -57,6 +57,7 @@ func GetReplicationAnalysis(clusterName string, hints *ReplicationAnalysisHints) args := sqlutils.Args(ValidSecondsFromSeenToLastAttemptedCheck(), config.Config.ReasonableReplicationLagSeconds, clusterName) analysisQueryReductionClause := `` + if config.Config.ReduceReplicationAnalysisCount { analysisQueryReductionClause = ` HAVING @@ -90,16 +91,17 @@ func GetReplicationAnalysis(clusterName string, hints *ReplicationAnalysisHints) SELECT master_instance.hostname, master_instance.port, - MIN(master_instance.data_center) AS data_center, - MIN(master_instance.region) AS region, - MIN(master_instance.physical_environment) AS physical_environment, + master_instance.read_only AS read_only, + MIN(master_instance.data_center) AS data_center, + MIN(master_instance.region) AS region, + MIN(master_instance.physical_environment) AS physical_environment, MIN(master_instance.master_host) AS master_host, MIN(master_instance.master_port) AS master_port, MIN(master_instance.cluster_name) AS cluster_name, MIN(IFNULL(cluster_alias.alias, master_instance.cluster_name)) AS cluster_alias, MIN( - master_instance.last_checked <= master_instance.last_seen - and master_instance.last_attempted_check <= master_instance.last_seen + interval ? second + master_instance.last_checked <= master_instance.last_seen + and master_instance.last_attempted_check <= master_instance.last_seen + interval ? second ) = 1 AS is_last_check_valid, MIN(master_instance.last_check_partial_success) as last_check_partial_success, MIN(master_instance.master_host IN ('' , '_') @@ -242,6 +244,7 @@ func GetReplicationAnalysis(clusterName string, hints *ReplicationAnalysisHints) is_cluster_master DESC, count_replicas DESC `, analysisQueryReductionClause) + err := db.QueryOrchestrator(query, args, func(m sqlutils.RowMap) error { a := ReplicationAnalysis{ Analysis: NoProblem, @@ -298,6 +301,8 @@ func GetReplicationAnalysis(clusterName string, hints *ReplicationAnalysisHints) a.CountDelayedReplicas = m.GetUint("count_delayed_replicas") a.CountLaggingReplicas = m.GetUint("count_lagging_replicas") + a.IsReadOnly = m.GetUint("read_only") == 1 + if !a.LastCheckValid { analysisMessage := fmt.Sprintf("analysis: IsMaster: %+v, LastCheckValid: %+v, LastCheckPartialSuccess: %+v, CountReplicas: %+v, CountValidReplicatingReplicas: %+v, CountLaggingReplicas: %+v, CountDelayedReplicas: %+v, ", a.IsMaster, a.LastCheckValid, a.LastCheckPartialSuccess, a.CountReplicas, a.CountValidReplicatingReplicas, a.CountLaggingReplicas, a.CountDelayedReplicas, @@ -479,6 +484,11 @@ func GetReplicationAnalysis(clusterName string, hints *ReplicationAnalysisHints) if a.MaxReplicaGTIDErrant != "" { a.StructureAnalysis = append(a.StructureAnalysis, ErrantGTIDStructureWarning) } + + if a.IsMaster && a.IsReadOnly { + a.StructureAnalysis = append(a.StructureAnalysis, NoWriteableMasterStructureWarning) + } + } appendAnalysis(&a) diff --git a/resources/public/js/orchestrator.js b/resources/public/js/orchestrator.js index 6c0e76651..bbc3a3137 100644 --- a/resources/public/js/orchestrator.js +++ b/resources/public/js/orchestrator.js @@ -663,6 +663,7 @@ function normalizeInstanceProblem(instance) { } instance.problem = null; + instance.Problems = instance.Problems || []; if (instance.Problems.length > 0) { instance.problem = instance.Problems[0]; // highest priority one }