Skip to content

Commit 750658f

Browse files
committed
fix(sandbox): skip wsrep post-start gate for non-Galera single sandboxes
wait_wsrep_after_start runs after every single-sandbox deploy, but it only returns success when wsrep_ready=ON — which never happens on a plain MySQL/MariaDB sandbox (no wsrep). It also polls $SBDIR/use (the sandbox user) before post-grants provisions that user, so it hits "Access denied" and loops for its full 60s timeout on every non-Galera deploy. The code already (falsely) labelled it a "no-op on non-Galera". Gate the script on actual wsrep usage (a wsrep option in MyCnfOptions or a wsrep arg in StartArgs), so it runs only for Galera/PXC nodes where it matters. Plain MySQL/MariaDB single deploys no longer pay the 60s delay. - add sandboxUsesWsrep(SandboxDef) helper - gate the concurrent execList append and the non-concurrent RunCmd - TestSandboxUsesWsrep covers wsrep_provider / wsrep_cluster_address / wsrep-on, --wsrep-new-cluster, and negative (plain mysql/mariadb) cases
1 parent 9529d05 commit 750658f

2 files changed

Lines changed: 59 additions & 5 deletions

File tree

sandbox/sandbox.go

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,27 @@ func sbError(reason, format string, args ...interface{}) error {
347347
return fmt.Errorf(reason+" "+format, args...)
348348
}
349349

350+
// sandboxUsesWsrep reports whether the sandbox is configured for Galera/PXC
351+
// (wsrep). The post-start wait_wsrep_after_start gate only matters for wsrep
352+
// nodes: on a plain MySQL/MariaDB single sandbox wsrep is never active, so the
353+
// gate polls the not-yet-provisioned sandbox user for its whole timeout (the
354+
// helper script returns success only when wsrep_ready=ON, which never happens
355+
// without wsrep). Skipping it makes the gate a true no-op on non-Galera, as the
356+
// surrounding log messages already (falsely) claim.
357+
func sandboxUsesWsrep(sd SandboxDef) bool {
358+
for _, opt := range sd.MyCnfOptions {
359+
if strings.Contains(opt, "wsrep") {
360+
return true
361+
}
362+
}
363+
for _, arg := range sd.StartArgs {
364+
if strings.Contains(arg, "wsrep") {
365+
return true
366+
}
367+
}
368+
return false
369+
}
370+
350371
func createSingleSandbox(sandboxDef SandboxDef) (execList []concurrent.ExecutionList, err error) {
351372

352373
var sandboxDir string
@@ -1058,15 +1079,17 @@ func createSingleSandbox(sandboxDef SandboxDef) (execList []concurrent.Execution
10581079
}
10591080
)
10601081
logger.Printf("Adding after start command to execution list\n")
1061-
logger.Printf("Adding wait-wsrep command to execution list (no-op on non-Galera)\n")
10621082
logger.Printf("Adding pre grants command to execution list\n")
10631083
logger.Printf("Adding load grants command to execution list\n")
10641084
logger.Printf("Adding post grants command to execution list\n")
10651085
execList = append(execList, concurrent.ExecutionList{Logger: logger, Priority: 3, Command: eCmdAfterStart})
1066-
execList = append(execList, concurrent.ExecutionList{Logger: logger, Priority: 4, Command: eCmdWaitWsrep})
10671086
execList = append(execList, concurrent.ExecutionList{Logger: logger, Priority: 5, Command: eCmdPreGrants})
10681087
execList = append(execList, concurrent.ExecutionList{Logger: logger, Priority: 6, Command: eCmdLoadGrants})
10691088
execList = append(execList, concurrent.ExecutionList{Logger: logger, Priority: 7, Command: eCmdPostGrants})
1089+
if sandboxUsesWsrep(sandboxDef) {
1090+
logger.Printf("Adding wait-wsrep command to execution list\n")
1091+
execList = append(execList, concurrent.ExecutionList{Logger: logger, Priority: 4, Command: eCmdWaitWsrep})
1092+
}
10701093
}
10711094
} else {
10721095
if !sandboxDef.SkipStart {
@@ -1084,8 +1107,10 @@ func createSingleSandbox(sandboxDef SandboxDef) (execList []concurrent.Execution
10841107
if err != nil {
10851108
return emptyExecutionList, err
10861109
}
1087-
logger.Printf("Running wait-wsrep script (no-op on non-Galera)\n")
1088-
_, _ = common.RunCmd(path.Join(sandboxDir, globals.ScriptWaitWsrepAfterStart))
1110+
if sandboxUsesWsrep(sandboxDef) {
1111+
logger.Printf("Running wait-wsrep script\n")
1112+
_, _ = common.RunCmd(path.Join(sandboxDir, globals.ScriptWaitWsrepAfterStart))
1113+
}
10891114
if sandboxDef.LoadGrants {
10901115
logger.Printf("Running pre grants script\n")
10911116
_, err = common.RunCmdWithArgs(path.Join(sandboxDir, globals.ScriptLoadGrants), []string{globals.ScriptPreGrantsSql})

sandbox/sandbox_test.go

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,7 @@ func testCreateReplicationSandbox(t *testing.T) {
634634
t.Fatalf("expected replica use script at %s", use)
635635
}
636636
// RunCmdWithArgs (RunCmd takes only the cmd string)
637-
out, err := common.RunCmdWithArgs(use, []string{"-BN", "-e", "SELECT 1;"}); // tests #131 fix: replica must be ready immediately (no sleep) after deploy
637+
out, err := common.RunCmdWithArgs(use, []string{"-BN", "-e", "SELECT 1;"}) // tests #131 fix: replica must be ready immediately (no sleep) after deploy
638638
if err != nil {
639639
t.Fatalf("replica n%s not ready immediately after deploy replication: %v\noutput: %s", n, err, out)
640640
}
@@ -713,3 +713,32 @@ func TestCreateSandbox(t *testing.T) {
713713
t.Run("expectedFailures", testFailSandboxConditions)
714714
t.Run("flavors", testDetectFlavor)
715715
}
716+
717+
// TestSandboxUsesWsrep checks that the wsrep gate fires only for Galera/PXC
718+
// (wsrep-enabled) sandboxes. Plain MySQL/MariaDB single sandboxes carry no
719+
// wsrep option, so the post-start wait_wsrep_after_start script must be skipped
720+
// for them — otherwise it polls the not-yet-provisioned sandbox user until its
721+
// timeout (wsrep_ready is never ON without wsrep).
722+
func TestSandboxUsesWsrep(t *testing.T) {
723+
cases := []struct {
724+
name string
725+
sd SandboxDef
726+
want bool
727+
}{
728+
{"plain mysql single", SandboxDef{}, false},
729+
{"mariadb single", SandboxDef{Flavor: common.MariaDbFlavor}, false},
730+
{"non-wsrep my.cnf options only", SandboxDef{MyCnfOptions: []string{"character-set-server=utf8mb4", "port=3306"}}, false},
731+
{"wsrep_provider in MyCnfOptions", SandboxDef{MyCnfOptions: []string{"wsrep_provider=/usr/lib/libgalera_smm.so"}}, true},
732+
{"wsrep_cluster_address in MyCnfOptions", SandboxDef{MyCnfOptions: []string{"wsrep_cluster_address=gcomm://127.0.0.1:4567"}}, true},
733+
{"wsrep-on in MyCnfOptions", SandboxDef{MyCnfOptions: []string{"wsrep-on=ON"}}, true},
734+
{"wsrep mixed with other options", SandboxDef{MyCnfOptions: []string{"character-set-server=utf8mb4", "wsrep_node_address=127.0.0.1"}}, true},
735+
{"wsrep-new-cluster in StartArgs", SandboxDef{StartArgs: []string{"--wsrep-new-cluster"}}, true},
736+
}
737+
for _, c := range cases {
738+
t.Run(c.name, func(t *testing.T) {
739+
if got := sandboxUsesWsrep(c.sd); got != c.want {
740+
t.Errorf("sandboxUsesWsrep() = %v, want %v", got, c.want)
741+
}
742+
})
743+
}
744+
}

0 commit comments

Comments
 (0)