-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6849 from tinyspeck/am_mysqld_shutdown_timeout
Add timeout for mysqld_shutdown Signed-off-by: Andrew Mason <[email protected]>
- Loading branch information
Showing
6 changed files
with
264 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package hook | ||
|
||
import ( | ||
"context" | ||
"os" | ||
"os/exec" | ||
"path" | ||
"testing" | ||
"time" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
vtenv "vitess.io/vitess/go/vt/env" | ||
) | ||
|
||
func TestExecuteContext(t *testing.T) { | ||
vtroot, err := vtenv.VtRoot() | ||
require.NoError(t, err) | ||
|
||
sleep, err := exec.LookPath("sleep") | ||
require.NoError(t, err) | ||
|
||
sleepHookPath := path.Join(vtroot, "vthook", "sleep") | ||
require.NoError(t, os.Symlink(sleep, sleepHookPath)) | ||
defer func() { | ||
require.NoError(t, os.Remove(sleepHookPath)) | ||
}() | ||
|
||
h := NewHook("sleep", []string{"5"}) | ||
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*10) | ||
defer cancel() | ||
|
||
hr := h.ExecuteContext(ctx) | ||
assert.Equal(t, HOOK_TIMEOUT_ERROR, hr.ExitStatus) | ||
|
||
h.Parameters = []string{"0.1"} | ||
hr = h.Execute() | ||
assert.Equal(t, HOOK_SUCCESS, hr.ExitStatus) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
// Package mysqlctl_test is the blackbox tests for package mysqlctl. | ||
// Tests that need to use fakemysqldaemon must be written as blackbox tests; | ||
// since fakemysqldaemon imports mysqlctl, importing fakemysqldaemon in | ||
// a `package mysqlctl` test would cause a circular import. | ||
package mysqlctl_test | ||
|
||
import ( | ||
"context" | ||
"os" | ||
"path" | ||
"testing" | ||
"time" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
"vitess.io/vitess/go/mysql/fakesqldb" | ||
"vitess.io/vitess/go/vt/logutil" | ||
"vitess.io/vitess/go/vt/mysqlctl" | ||
"vitess.io/vitess/go/vt/mysqlctl/fakemysqldaemon" | ||
"vitess.io/vitess/go/vt/mysqlctl/filebackupstorage" | ||
"vitess.io/vitess/go/vt/proto/topodata" | ||
"vitess.io/vitess/go/vt/proto/vttime" | ||
"vitess.io/vitess/go/vt/topo" | ||
"vitess.io/vitess/go/vt/topo/memorytopo" | ||
"vitess.io/vitess/go/vt/vttablet/faketmclient" | ||
"vitess.io/vitess/go/vt/vttablet/tmclient" | ||
) | ||
|
||
func setBuiltinBackupMysqldDeadline(t time.Duration) time.Duration { | ||
old := *mysqlctl.BuiltinBackupMysqldTimeout | ||
mysqlctl.BuiltinBackupMysqldTimeout = &t | ||
|
||
return old | ||
} | ||
|
||
func createBackupDir(root string, dirs ...string) error { | ||
for _, dir := range dirs { | ||
if err := os.MkdirAll(path.Join(root, dir), 0755); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func TestExecuteBackup(t *testing.T) { | ||
// Set up local backup directory | ||
backupRoot := "testdata/builtinbackup_test" | ||
*filebackupstorage.FileBackupStorageRoot = backupRoot | ||
require.NoError(t, createBackupDir(backupRoot, "innodb", "log", "datadir")) | ||
defer os.RemoveAll(backupRoot) | ||
|
||
ctx := context.Background() | ||
|
||
// Set up topo | ||
keyspace, shard := "mykeyspace", "-80" | ||
ts := memorytopo.NewServer("cell1") | ||
defer ts.Close() | ||
|
||
require.NoError(t, ts.CreateKeyspace(ctx, keyspace, &topodata.Keyspace{})) | ||
require.NoError(t, ts.CreateShard(ctx, keyspace, shard)) | ||
|
||
tablet := topo.NewTablet(100, "cell1", "mykeyspace-00-80-0100") | ||
tablet.Keyspace = keyspace | ||
tablet.Shard = shard | ||
|
||
require.NoError(t, ts.CreateTablet(ctx, tablet)) | ||
|
||
_, err := ts.UpdateShardFields(ctx, keyspace, shard, func(si *topo.ShardInfo) error { | ||
si.MasterAlias = &topodata.TabletAlias{Uid: 100, Cell: "cell1"} | ||
|
||
now := time.Now() | ||
si.MasterTermStartTime = &vttime.Time{Seconds: int64(now.Second()), Nanoseconds: int32(now.Nanosecond())} | ||
|
||
return nil | ||
}) | ||
require.NoError(t, err) | ||
|
||
// Set up tm client | ||
// Note that using faketmclient.NewFakeTabletManagerClient will cause infinite recursion :shrug: | ||
tmclient.RegisterTabletManagerClientFactory("grpc", | ||
func() tmclient.TabletManagerClient { return &faketmclient.FakeTabletManagerClient{} }, | ||
) | ||
|
||
be := &mysqlctl.BuiltinBackupEngine{} | ||
|
||
// Configure a tight deadline to force a timeout | ||
oldDeadline := setBuiltinBackupMysqldDeadline(time.Second) | ||
defer setBuiltinBackupMysqldDeadline(oldDeadline) | ||
|
||
bh := filebackupstorage.FileBackupHandle{} | ||
|
||
// Spin up a fake daemon to be used in backups. It needs to be allowed to receive: | ||
// "STOP SLAVE", "START SLAVE", in that order. | ||
mysqld := fakemysqldaemon.NewFakeMysqlDaemon(fakesqldb.New(t)) | ||
mysqld.ExpectedExecuteSuperQueryList = []string{"STOP SLAVE", "START SLAVE"} | ||
// mysqld.ShutdownTime = time.Minute | ||
|
||
ok, err := be.ExecuteBackup(ctx, mysqlctl.BackupParams{ | ||
Logger: logutil.NewConsoleLogger(), | ||
Mysqld: mysqld, | ||
Cnf: &mysqlctl.Mycnf{ | ||
InnodbDataHomeDir: path.Join(backupRoot, "innodb"), | ||
InnodbLogGroupHomeDir: path.Join(backupRoot, "log"), | ||
DataDir: path.Join(backupRoot, "datadir"), | ||
}, | ||
HookExtraEnv: map[string]string{}, | ||
TopoServer: ts, | ||
Keyspace: keyspace, | ||
Shard: shard, | ||
}, &bh) | ||
|
||
require.NoError(t, err) | ||
assert.True(t, ok) | ||
|
||
mysqld.ExpectedExecuteSuperQueryCurrent = 0 // resest the index of what queries we've run | ||
mysqld.ShutdownTime = time.Minute // reminder that shutdownDeadline is 1s | ||
|
||
ok, err = be.ExecuteBackup(ctx, mysqlctl.BackupParams{ | ||
Logger: logutil.NewConsoleLogger(), | ||
Mysqld: mysqld, | ||
Cnf: &mysqlctl.Mycnf{ | ||
InnodbDataHomeDir: path.Join(backupRoot, "innodb"), | ||
InnodbLogGroupHomeDir: path.Join(backupRoot, "log"), | ||
DataDir: path.Join(backupRoot, "datadir"), | ||
}, | ||
HookExtraEnv: map[string]string{}, | ||
TopoServer: ts, | ||
Keyspace: keyspace, | ||
Shard: shard, | ||
}, &bh) | ||
|
||
assert.Error(t, err) | ||
assert.False(t, ok) | ||
} |
Oops, something went wrong.