diff --git a/go/test/endtoend/tabletmanager/tablet_test.go b/go/test/endtoend/tabletmanager/tablet_test.go index 8277ee13aed..8e6a1ad5a5e 100644 --- a/go/test/endtoend/tabletmanager/tablet_test.go +++ b/go/test/endtoend/tabletmanager/tablet_test.go @@ -20,12 +20,40 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "vitess.io/vitess/go/test/endtoend/cluster" "vitess.io/vitess/go/vt/log" ) +// TestEnsureDB tests that vttablet creates the db as needed +func TestEnsureDB(t *testing.T) { + defer cluster.PanicHandler(t) + + // Create new tablet + tablet := clusterInstance.NewVttabletInstance("replica", 0, "") + tablet.MysqlctlProcess = *cluster.MysqlCtlProcessInstance(tablet.TabletUID, tablet.MySQLPort, clusterInstance.TmpDirectory) + err := tablet.MysqlctlProcess.Start() + require.NoError(t, err) + + log.Info(fmt.Sprintf("Started vttablet %v", tablet)) + // Start vttablet process as replica. It won't be able to serve because there's no db. + err = clusterInstance.StartVttablet(tablet, "NOT_SERVING", false, cell, "dbtest", hostname, "0") + require.NoError(t, err) + + // Make it the master. + err = clusterInstance.VtctlclientProcess.ExecuteCommand("TabletExternallyReparented", tablet.Alias) + require.NoError(t, err) + + // It goes SERVING because TER calls ChangeTabletType which will also set the database to read-write + assert.Equal(t, "SERVING", tablet.VttabletProcess.GetTabletStatus()) + status := tablet.VttabletProcess.GetStatusDetails() + assert.Contains(t, status, "Serving") + + killTablets(t, tablet) +} + // TestLocalMetadata tests the contents of local_metadata table after vttablet startup func TestLocalMetadata(t *testing.T) { defer cluster.PanicHandler(t) diff --git a/go/vt/vttablet/tabletmanager/rpc_replication.go b/go/vt/vttablet/tabletmanager/rpc_replication.go index 1db7e7dccde..240f8772232 100644 --- a/go/vt/vttablet/tabletmanager/rpc_replication.go +++ b/go/vt/vttablet/tabletmanager/rpc_replication.go @@ -249,10 +249,6 @@ func (tm *TabletManager) InitMaster(ctx context.Context) (string, error) { // Set the server read-write, from now on we can accept real // client writes. Note that if semi-sync replication is enabled, // we'll still need some replicas to be able to commit transactions. - if err := tm.MysqlDaemon.SetReadOnly(false); err != nil { - return "", err - } - if err := tm.changeTypeLocked(ctx, topodatapb.TabletType_MASTER); err != nil { return "", err } @@ -739,12 +735,6 @@ func (tm *TabletManager) PromoteReplica(ctx context.Context) (string, error) { return "", err } - // We call SetReadOnly only after the topo has been updated to avoid - // situations where two tablets are master at the DB level but not at the vitess level - if err := tm.MysqlDaemon.SetReadOnly(false); err != nil { - return "", err - } - return mysql.EncodePosition(pos), nil } diff --git a/go/vt/vttablet/tabletmanager/tm_state.go b/go/vt/vttablet/tabletmanager/tm_state.go index fad4a8b9048..80a4d5e05b5 100644 --- a/go/vt/vttablet/tabletmanager/tm_state.go +++ b/go/vt/vttablet/tabletmanager/tm_state.go @@ -163,6 +163,11 @@ func (ts *tmState) ChangeTabletType(ctx context.Context, tabletType topodatapb.T if err != nil { return err } + // We call SetReadOnly only after the topo has been updated to avoid + // situations where two tablets are master at the DB level but not at the vitess level + if err := ts.tm.MysqlDaemon.SetReadOnly(false); err != nil { + return err + } ts.tablet.Type = tabletType ts.tablet.MasterTermStartTime = masterTermStartTime