Checkpoint of removing IDLE and SCRAP states. All unit tests pass,

most integration tests pass too.
This commit is contained in:
Alain Jobart 2015-10-21 14:48:02 -07:00
Родитель 064d932312
Коммит 73497d2a16
45 изменённых файлов: 399 добавлений и 982 удалений

Просмотреть файл

@ -137,35 +137,9 @@ func main() {
return "", wr.TabletManagerClient().RefreshState(ctx, ti)
})
actionRepo.RegisterTabletAction("ScrapTablet", acl.ADMIN,
func(ctx context.Context, wr *wrangler.Wrangler, tabletAlias *pb.TabletAlias, r *http.Request) (string, error) {
// refuse to scrap tablets that are not spare
ti, err := wr.TopoServer().GetTablet(ctx, tabletAlias)
if err != nil {
return "", err
}
if ti.Type != pb.TabletType_SPARE {
return "", fmt.Errorf("Can only scrap spare tablets")
}
return "", wr.Scrap(ctx, tabletAlias, false, false)
})
actionRepo.RegisterTabletAction("ScrapTabletForce", acl.ADMIN,
func(ctx context.Context, wr *wrangler.Wrangler, tabletAlias *pb.TabletAlias, r *http.Request) (string, error) {
// refuse to scrap tablets that are not spare
ti, err := wr.TopoServer().GetTablet(ctx, tabletAlias)
if err != nil {
return "", err
}
if ti.Type != pb.TabletType_SPARE {
return "", fmt.Errorf("Can only scrap spare tablets")
}
return "", wr.Scrap(ctx, tabletAlias, true, false)
})
actionRepo.RegisterTabletAction("DeleteTablet", acl.ADMIN,
func(ctx context.Context, wr *wrangler.Wrangler, tabletAlias *pb.TabletAlias, r *http.Request) (string, error) {
return "", wr.DeleteTablet(ctx, tabletAlias)
return "", wr.DeleteTablet(ctx, tabletAlias, false, false)
})
actionRepo.RegisterTabletAction("ReloadSchema", acl.ADMIN,

Просмотреть файл

@ -32,8 +32,6 @@ It has these top-level messages:
SetReadWriteResponse
ChangeTypeRequest
ChangeTypeResponse
ScrapRequest
ScrapResponse
RefreshStateRequest
RefreshStateResponse
RunHealthCheckRequest
@ -402,20 +400,6 @@ func (m *ChangeTypeResponse) Reset() { *m = ChangeTypeResponse{} }
func (m *ChangeTypeResponse) String() string { return proto.CompactTextString(m) }
func (*ChangeTypeResponse) ProtoMessage() {}
type ScrapRequest struct {
}
func (m *ScrapRequest) Reset() { *m = ScrapRequest{} }
func (m *ScrapRequest) String() string { return proto.CompactTextString(m) }
func (*ScrapRequest) ProtoMessage() {}
type ScrapResponse struct {
}
func (m *ScrapResponse) Reset() { *m = ScrapResponse{} }
func (m *ScrapResponse) String() string { return proto.CompactTextString(m) }
func (*ScrapResponse) ProtoMessage() {}
type RefreshStateRequest struct {
}

Просмотреть файл

@ -48,7 +48,6 @@ type TabletManagerClient interface {
SetReadWrite(ctx context.Context, in *tabletmanagerdata.SetReadWriteRequest, opts ...grpc.CallOption) (*tabletmanagerdata.SetReadWriteResponse, error)
// ChangeType asks the remote tablet to change its type
ChangeType(ctx context.Context, in *tabletmanagerdata.ChangeTypeRequest, opts ...grpc.CallOption) (*tabletmanagerdata.ChangeTypeResponse, error)
Scrap(ctx context.Context, in *tabletmanagerdata.ScrapRequest, opts ...grpc.CallOption) (*tabletmanagerdata.ScrapResponse, error)
RefreshState(ctx context.Context, in *tabletmanagerdata.RefreshStateRequest, opts ...grpc.CallOption) (*tabletmanagerdata.RefreshStateResponse, error)
RunHealthCheck(ctx context.Context, in *tabletmanagerdata.RunHealthCheckRequest, opts ...grpc.CallOption) (*tabletmanagerdata.RunHealthCheckResponse, error)
ReloadSchema(ctx context.Context, in *tabletmanagerdata.ReloadSchemaRequest, opts ...grpc.CallOption) (*tabletmanagerdata.ReloadSchemaResponse, error)
@ -213,15 +212,6 @@ func (c *tabletManagerClient) ChangeType(ctx context.Context, in *tabletmanagerd
return out, nil
}
func (c *tabletManagerClient) Scrap(ctx context.Context, in *tabletmanagerdata.ScrapRequest, opts ...grpc.CallOption) (*tabletmanagerdata.ScrapResponse, error) {
out := new(tabletmanagerdata.ScrapResponse)
err := grpc.Invoke(ctx, "/tabletmanagerservice.TabletManager/Scrap", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *tabletManagerClient) RefreshState(ctx context.Context, in *tabletmanagerdata.RefreshStateRequest, opts ...grpc.CallOption) (*tabletmanagerdata.RefreshStateResponse, error) {
out := new(tabletmanagerdata.RefreshStateResponse)
err := grpc.Invoke(ctx, "/tabletmanagerservice.TabletManager/RefreshState", in, out, c.cc, opts...)
@ -541,7 +531,6 @@ type TabletManagerServer interface {
SetReadWrite(context.Context, *tabletmanagerdata.SetReadWriteRequest) (*tabletmanagerdata.SetReadWriteResponse, error)
// ChangeType asks the remote tablet to change its type
ChangeType(context.Context, *tabletmanagerdata.ChangeTypeRequest) (*tabletmanagerdata.ChangeTypeResponse, error)
Scrap(context.Context, *tabletmanagerdata.ScrapRequest) (*tabletmanagerdata.ScrapResponse, error)
RefreshState(context.Context, *tabletmanagerdata.RefreshStateRequest) (*tabletmanagerdata.RefreshStateResponse, error)
RunHealthCheck(context.Context, *tabletmanagerdata.RunHealthCheckRequest) (*tabletmanagerdata.RunHealthCheckResponse, error)
ReloadSchema(context.Context, *tabletmanagerdata.ReloadSchemaRequest) (*tabletmanagerdata.ReloadSchemaResponse, error)
@ -726,18 +715,6 @@ func _TabletManager_ChangeType_Handler(srv interface{}, ctx context.Context, dec
return out, nil
}
func _TabletManager_Scrap_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(tabletmanagerdata.ScrapRequest)
if err := dec(in); err != nil {
return nil, err
}
out, err := srv.(TabletManagerServer).Scrap(ctx, in)
if err != nil {
return nil, err
}
return out, nil
}
func _TabletManager_RefreshState_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) {
in := new(tabletmanagerdata.RefreshStateRequest)
if err := dec(in); err != nil {
@ -1155,10 +1132,6 @@ var _TabletManager_serviceDesc = grpc.ServiceDesc{
MethodName: "ChangeType",
Handler: _TabletManager_ChangeType_Handler,
},
{
MethodName: "Scrap",
Handler: _TabletManager_Scrap_Handler,
},
{
MethodName: "RefreshState",
Handler: _TabletManager_RefreshState_Handler,

Просмотреть файл

@ -67,7 +67,6 @@ type TabletType int32
const (
TabletType_UNKNOWN TabletType = 0
TabletType_IDLE TabletType = 1
TabletType_MASTER TabletType = 2
TabletType_REPLICA TabletType = 3
TabletType_RDONLY TabletType = 4
@ -78,12 +77,10 @@ const (
TabletType_BACKUP TabletType = 8
TabletType_RESTORE TabletType = 9
TabletType_WORKER TabletType = 10
TabletType_SCRAP TabletType = 11
)
var TabletType_name = map[int32]string{
0: "UNKNOWN",
1: "IDLE",
2: "MASTER",
3: "REPLICA",
4: "RDONLY",
@ -94,11 +91,9 @@ var TabletType_name = map[int32]string{
8: "BACKUP",
9: "RESTORE",
10: "WORKER",
11: "SCRAP",
}
var TabletType_value = map[string]int32{
"UNKNOWN": 0,
"IDLE": 1,
"MASTER": 2,
"REPLICA": 3,
"RDONLY": 4,
@ -109,7 +104,6 @@ var TabletType_value = map[string]int32{
"BACKUP": 8,
"RESTORE": 9,
"WORKER": 10,
"SCRAP": 11,
}
func (x TabletType) String() string {

Просмотреть файл

@ -43,9 +43,6 @@ const (
// TabletActionChangeType changes the type of the tablet
TabletActionChangeType = "ChangeType"
// TabletActionScrap scraps the live running tablet
TabletActionScrap = "Scrap"
// TabletActionResetReplication tells the tablet it should
// reset its replication state
TabletActionResetReplication = "ResetReplication"

Просмотреть файл

@ -17,7 +17,6 @@ type slaveWasRestartedTestArgs struct {
Parent *pb.TabletAlias
ExpectedMasterAddr string
ExpectedMasterIPAddr string
ScrapStragglers bool
}
func TestMissingFieldsJson(t *testing.T) {
@ -28,7 +27,6 @@ func TestMissingFieldsJson(t *testing.T) {
},
ExpectedMasterAddr: "a1",
ExpectedMasterIPAddr: "i1",
ScrapStragglers: true,
}
data, err := json.MarshalIndent(swra, "", " ")
if err != nil {
@ -67,7 +65,6 @@ func TestMissingFieldsBson(t *testing.T) {
},
ExpectedMasterAddr: "a1",
ExpectedMasterIPAddr: "i1",
ScrapStragglers: true,
}
data, err := bson.Marshal(swra)
if err != nil {

Просмотреть файл

@ -9,7 +9,7 @@ update stream, binlog players, ...), and handles tabletmanager RPCs
to update the state.
The agent is responsible for maintaining the tablet record in the
topology server. Only 'ScrapTablet -force' and 'DeleteTablet'
topology server. Only 'vtctl DeleteTablet'
should be run by other processes, everything else should ask
the tablet server to make the change.

Просмотреть файл

@ -45,8 +45,6 @@ type RPCAgent interface {
ChangeType(ctx context.Context, tabletType pb.TabletType) error
Scrap(ctx context.Context) error
Sleep(ctx context.Context, duration time.Duration)
ExecuteHook(ctx context.Context, hk *hook.Hook) *hook.HookResult
@ -160,12 +158,6 @@ func (agent *ActionAgent) ChangeType(ctx context.Context, tabletType pb.TabletTy
return topotools.ChangeType(ctx, agent.TopoServer, agent.TabletAlias, tabletType, nil)
}
// Scrap scraps the live running tablet
// Should be called under RPCWrapLockAction.
func (agent *ActionAgent) Scrap(ctx context.Context) error {
return topotools.Scrap(ctx, agent.TopoServer, agent.TabletAlias, false)
}
// Sleep sleeps for the duration
// Should be called under RPCWrapLockAction.
func (agent *ActionAgent) Sleep(ctx context.Context, duration time.Duration) {
@ -668,7 +660,7 @@ func (agent *ActionAgent) updateReplicationGraphForPromotedSlave(ctx context.Con
}
// NOTE(msolomon) A serving graph update is required, but in
// order for the shard to be consistent the old master must be
// scrapped first. That is externally coordinated by the
// dealt with first. That is externally coordinated by the
// wrangler reparent action.
// Insert the new tablet location in the replication graph now that

Просмотреть файл

@ -293,27 +293,6 @@ func agentRPCTestChangeTypePanic(ctx context.Context, t *testing.T, client tmcli
expectRPCWrapLockActionPanic(t, err)
}
var errTestScrap = fmt.Errorf("Scrap Failed!")
func (fra *fakeRPCAgent) Scrap(ctx context.Context) error {
if fra.panics {
panic(fmt.Errorf("test-triggered panic"))
}
return errTestScrap
}
func agentRPCTestScrap(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, ti *topo.TabletInfo) {
err := client.Scrap(ctx, ti)
if strings.Index(err.Error(), errTestScrap.Error()) == -1 {
t.Errorf("Unexpected Scrap result: got %v expected %v", err, errTestScrap)
}
}
func agentRPCTestScrapPanic(ctx context.Context, t *testing.T, client tmclient.TabletManagerClient, ti *topo.TabletInfo) {
err := client.Scrap(ctx, ti)
expectRPCWrapLockActionPanic(t, err)
}
var testSleepDuration = time.Minute
func (fra *fakeRPCAgent) Sleep(ctx context.Context, duration time.Duration) {
@ -1137,7 +1116,6 @@ func Run(t *testing.T, client tmclient.TabletManagerClient, ti *topo.TabletInfo,
// Various read-write methods
agentRPCTestSetReadOnly(ctx, t, client, ti)
agentRPCTestChangeType(ctx, t, client, ti)
agentRPCTestScrap(ctx, t, client, ti)
agentRPCTestSleep(ctx, t, client, ti)
agentRPCTestExecuteHook(ctx, t, client, ti)
agentRPCTestRefreshState(ctx, t, client, ti)
@ -1189,7 +1167,6 @@ func Run(t *testing.T, client tmclient.TabletManagerClient, ti *topo.TabletInfo,
// Various read-write methods
agentRPCTestSetReadOnlyPanic(ctx, t, client, ti)
agentRPCTestChangeTypePanic(ctx, t, client, ti)
agentRPCTestScrapPanic(ctx, t, client, ti)
agentRPCTestSleepPanic(ctx, t, client, ti)
agentRPCTestExecuteHookPanic(ctx, t, client, ti)
agentRPCTestRefreshStatePanic(ctx, t, client, ti)

Просмотреть файл

@ -104,11 +104,6 @@ func (client *FakeTabletManagerClient) ChangeType(ctx context.Context, tablet *t
return nil
}
// Scrap is part of the tmclient.TabletManagerClient interface
func (client *FakeTabletManagerClient) Scrap(ctx context.Context, tablet *topo.TabletInfo) error {
return nil
}
// RefreshState is part of the tmclient.TabletManagerClient interface
func (client *FakeTabletManagerClient) RefreshState(ctx context.Context, tablet *topo.TabletInfo) error {
return nil

Просмотреть файл

@ -139,11 +139,6 @@ func (client *GoRPCTabletManagerClient) ChangeType(ctx context.Context, tablet *
return client.rpcCallTablet(ctx, tablet, actionnode.TabletActionChangeType, &dbType, &rpc.Unused{})
}
// Scrap is part of the tmclient.TabletManagerClient interface
func (client *GoRPCTabletManagerClient) Scrap(ctx context.Context, tablet *topo.TabletInfo) error {
return client.rpcCallTablet(ctx, tablet, actionnode.TabletActionScrap, &rpc.Unused{}, &rpc.Unused{})
}
// RefreshState is part of the tmclient.TabletManagerClient interface
func (client *GoRPCTabletManagerClient) RefreshState(ctx context.Context, tablet *topo.TabletInfo) error {
return client.rpcCallTablet(ctx, tablet, actionnode.TabletActionRefreshState, &rpc.Unused{}, &rpc.Unused{})

Просмотреть файл

@ -113,14 +113,6 @@ func (tm *TabletManager) ChangeType(ctx context.Context, args *pb.TabletType, re
})
}
// Scrap wraps RPCAgent.Scrap
func (tm *TabletManager) Scrap(ctx context.Context, args *rpc.Unused, reply *rpc.Unused) error {
ctx = callinfo.RPCWrapCallInfo(ctx)
return tm.agent.RPCWrapLockAction(ctx, actionnode.TabletActionScrap, args, reply, true, func() error {
return tm.agent.Scrap(ctx)
})
}
// RefreshState wraps RPCAgent.RefreshState
func (tm *TabletManager) RefreshState(ctx context.Context, args *rpc.Unused, reply *rpc.Unused) error {
ctx = callinfo.RPCWrapCallInfo(ctx)

Просмотреть файл

@ -195,17 +195,6 @@ func (client *Client) ChangeType(ctx context.Context, tablet *topo.TabletInfo, d
return err
}
// Scrap is part of the tmclient.TabletManagerClient interface
func (client *Client) Scrap(ctx context.Context, tablet *topo.TabletInfo) error {
cc, c, err := client.dial(ctx, tablet)
if err != nil {
return err
}
defer cc.Close()
_, err = c.Scrap(ctx, &pb.ScrapRequest{})
return err
}
// RefreshState is part of the tmclient.TabletManagerClient interface
func (client *Client) RefreshState(ctx context.Context, tablet *topo.TabletInfo) error {
cc, c, err := client.dial(ctx, tablet)

Просмотреть файл

@ -118,14 +118,6 @@ func (s *server) ChangeType(ctx context.Context, request *pb.ChangeTypeRequest)
})
}
func (s *server) Scrap(ctx context.Context, request *pb.ScrapRequest) (*pb.ScrapResponse, error) {
ctx = callinfo.GRPCCallInfo(ctx)
response := &pb.ScrapResponse{}
return response, s.agent.RPCWrapLockAction(ctx, actionnode.TabletActionScrap, request, response, true, func() error {
return s.agent.Scrap(ctx)
})
}
func (s *server) RefreshState(ctx context.Context, request *pb.RefreshStateRequest) (*pb.RefreshStateResponse, error) {
ctx = callinfo.GRPCCallInfo(ctx)
response := &pb.RefreshStateResponse{}

Просмотреть файл

@ -61,10 +61,9 @@ func (agent *ActionAgent) InitTablet(port, gRPCPort int32) error {
log.Fatalf("Invalid init tablet type %v: %v", *initTabletType, err)
}
if tabletType == pb.TabletType_MASTER || tabletType == pb.TabletType_SCRAP {
if tabletType == pb.TabletType_MASTER {
// We disallow TYPE_MASTER, so we don't have to change
// shard.MasterAlias, and deal with the corner cases.
// We also disallow TYPE_SCRAP, obviously.
log.Fatalf("init_tablet_type cannot be %v", tabletType)
}
@ -85,60 +84,58 @@ func (agent *ActionAgent) InitTablet(port, gRPCPort int32) error {
ctx, cancel := context.WithTimeout(agent.batchCtx, *initTimeout)
defer cancel()
// if we're assigned to a shard, make sure it exists, see if
// since we're assigned to a shard, make sure it exists, see if
// we are its master, and update its cells list if necessary
if tabletType != pb.TabletType_IDLE {
if *initKeyspace == "" || *initShard == "" {
log.Fatalf("if init tablet is enabled and the target type is not idle, init_keyspace and init_shard also need to be specified")
}
shard, _, err := topo.ValidateShardName(*initShard)
if *initKeyspace == "" || *initShard == "" {
log.Fatalf("if init tablet is enabled and the target type is not idle, init_keyspace and init_shard also need to be specified")
}
shard, _, err := topo.ValidateShardName(*initShard)
if err != nil {
log.Fatalf("cannot validate shard name: %v", err)
}
log.Infof("Reading shard record %v/%v", *initKeyspace, shard)
// read the shard, create it if necessary
si, err := topotools.GetOrCreateShard(ctx, agent.TopoServer, *initKeyspace, shard)
if err != nil {
return fmt.Errorf("InitTablet cannot GetOrCreateShard shard: %v", err)
}
if si.MasterAlias != nil && topoproto.TabletAliasEqual(si.MasterAlias, agent.TabletAlias) {
// we are the current master for this shard (probably
// means the master tablet process was just restarted),
// so InitTablet as master.
tabletType = pb.TabletType_MASTER
}
// See if we need to add the tablet's cell to the shard's cell
// list. If we do, it has to be under the shard lock.
if !si.HasCell(agent.TabletAlias.Cell) {
actionNode := actionnode.UpdateShard()
lockPath, err := actionNode.LockShard(ctx, agent.TopoServer, *initKeyspace, shard)
if err != nil {
log.Fatalf("cannot validate shard name: %v", err)
return fmt.Errorf("LockShard(%v/%v) failed: %v", *initKeyspace, shard, err)
}
log.Infof("Reading shard record %v/%v", *initKeyspace, shard)
// read the shard, create it if necessary
si, err := topotools.GetOrCreateShard(ctx, agent.TopoServer, *initKeyspace, shard)
// re-read the shard with the lock
si, err = agent.TopoServer.GetShard(ctx, *initKeyspace, shard)
if err != nil {
return fmt.Errorf("InitTablet cannot GetOrCreateShard shard: %v", err)
}
if si.MasterAlias != nil && topoproto.TabletAliasEqual(si.MasterAlias, agent.TabletAlias) {
// we are the current master for this shard (probably
// means the master tablet process was just restarted),
// so InitTablet as master.
tabletType = pb.TabletType_MASTER
return actionNode.UnlockShard(ctx, agent.TopoServer, *initKeyspace, shard, lockPath, err)
}
// See if we need to add the tablet's cell to the shard's cell
// list. If we do, it has to be under the shard lock.
// see if we really need to update it now
if !si.HasCell(agent.TabletAlias.Cell) {
actionNode := actionnode.UpdateShard()
lockPath, err := actionNode.LockShard(ctx, agent.TopoServer, *initKeyspace, shard)
if err != nil {
return fmt.Errorf("LockShard(%v/%v) failed: %v", *initKeyspace, shard, err)
}
si.Cells = append(si.Cells, agent.TabletAlias.Cell)
// re-read the shard with the lock
si, err = agent.TopoServer.GetShard(ctx, *initKeyspace, shard)
if err != nil {
// write it back
if err := agent.TopoServer.UpdateShard(ctx, si); err != nil {
return actionNode.UnlockShard(ctx, agent.TopoServer, *initKeyspace, shard, lockPath, err)
}
}
// see if we really need to update it now
if !si.HasCell(agent.TabletAlias.Cell) {
si.Cells = append(si.Cells, agent.TabletAlias.Cell)
// write it back
if err := agent.TopoServer.UpdateShard(ctx, si); err != nil {
return actionNode.UnlockShard(ctx, agent.TopoServer, *initKeyspace, shard, lockPath, err)
}
}
// and unlock
if err := actionNode.UnlockShard(ctx, agent.TopoServer, *initKeyspace, shard, lockPath, nil); err != nil {
return err
}
// and unlock
if err := actionNode.UnlockShard(ctx, agent.TopoServer, *initKeyspace, shard, lockPath, nil); err != nil {
return err
}
}
log.Infof("Initializing the tablet for type %v", tabletType)
@ -177,14 +174,12 @@ func (agent *ActionAgent) InitTablet(port, gRPCPort int32) error {
}
// now try to create the record
err := agent.TopoServer.CreateTablet(ctx, tablet)
err = agent.TopoServer.CreateTablet(ctx, tablet)
switch err {
case nil:
// it worked, we're good, can update the replication graph
if topo.IsInReplicationGraph(tablet.Type) {
if err := topo.UpdateTabletReplicationData(ctx, agent.TopoServer, tablet); err != nil {
return fmt.Errorf("UpdateTabletReplicationData failed: %v", err)
}
if err := topo.UpdateTabletReplicationData(ctx, agent.TopoServer, tablet); err != nil {
return fmt.Errorf("UpdateTabletReplicationData failed: %v", err)
}
case topo.ErrNodeExists:
@ -215,10 +210,8 @@ func (agent *ActionAgent) InitTablet(port, gRPCPort int32) error {
// and now update the serving graph. Note we do that in any case,
// to clean any inaccurate record from any part of the serving graph.
if tabletType != pb.TabletType_IDLE {
if err := topotools.UpdateTabletEndpoints(ctx, agent.TopoServer, tablet); err != nil {
return fmt.Errorf("UpdateTabletEndpoints failed: %v", err)
}
if err := topotools.UpdateTabletEndpoints(ctx, agent.TopoServer, tablet); err != nil {
return fmt.Errorf("UpdateTabletEndpoints failed: %v", err)
}
return nil

Просмотреть файл

@ -6,7 +6,6 @@ package tabletmanager
import (
"fmt"
"strings"
"testing"
"time"
@ -33,7 +32,7 @@ func TestInitTablet(t *testing.T) {
Uid: 1,
}
// start with idle, and a tablet record that doesn't exist
// start with a tablet record that doesn't exist
port := int32(1234)
gRPCPort := int32(3456)
mysqlDaemon := mysqlctl.NewFakeMysqlDaemon(db)
@ -50,55 +49,13 @@ func TestInitTablet(t *testing.T) {
lastHealthMapCount: new(stats.Int),
_healthy: fmt.Errorf("healthcheck not run yet"),
}
*initTabletType = "idle"
// let's use a real tablet in a shard, that will create
// the keyspace and shard.
*tabletHostname = "localhost"
if err := agent.InitTablet(port, gRPCPort); err != nil {
t.Fatalf("NewTestActionAgent(idle) failed: %v", err)
}
ti, err := ts.GetTablet(ctx, tabletAlias)
if err != nil {
t.Fatalf("GetTablet failed: %v", err)
}
if ti.Type != pb.TabletType_IDLE {
t.Errorf("wrong type for tablet: %v", ti.Type)
}
if ti.Hostname != "localhost" {
t.Errorf("wrong hostname for tablet: %v", ti.Hostname)
}
if ti.PortMap["vt"] != port {
t.Errorf("wrong port for tablet: %v", ti.PortMap["vt"])
}
if ti.PortMap["grpc"] != gRPCPort {
t.Errorf("wrong gRPC port for tablet: %v", ti.PortMap["grpc"])
}
// try again now that the node exists
port = 3456
if err := agent.InitTablet(port, gRPCPort); err != nil {
t.Fatalf("NewTestActionAgent(idle again) failed: %v", err)
}
ti, err = ts.GetTablet(ctx, tabletAlias)
if err != nil {
t.Fatalf("GetTablet failed: %v", err)
}
if ti.PortMap["vt"] != port {
t.Errorf("wrong port for tablet: %v", ti.PortMap["vt"])
}
if ti.PortMap["grpc"] != gRPCPort {
t.Errorf("wrong gRPC port for tablet: %v", ti.PortMap["grpc"])
}
// try with a keyspace and shard on the previously idle tablet,
// should fail
*initTabletType = "replica"
*initKeyspace = "test_keyspace"
*initShard = "-80"
if err := agent.InitTablet(port, gRPCPort); err == nil || !strings.Contains(err.Error(), "InitTablet failed because existing tablet keyspace and shard / differ from the provided ones test_keyspace/-80") {
t.Fatalf("InitTablet(type over idle) didn't fail correctly: %v", err)
}
// now let's use a different real tablet in a shard, that will create
// the keyspace and shard.
tabletAlias = &pb.TabletAlias{
Cell: "cell1",
Uid: 2,
@ -114,13 +71,22 @@ func TestInitTablet(t *testing.T) {
if len(si.Cells) != 1 || si.Cells[0] != "cell1" {
t.Errorf("shard.Cells not updated properly: %v", si)
}
ti, err = ts.GetTablet(ctx, tabletAlias)
ti, err := ts.GetTablet(ctx, tabletAlias)
if err != nil {
t.Fatalf("GetTablet failed: %v", err)
}
if ti.Type != pb.TabletType_REPLICA {
t.Errorf("wrong tablet type: %v", ti.Type)
}
if ti.Hostname != "localhost" {
t.Errorf("wrong hostname for tablet: %v", ti.Hostname)
}
if ti.PortMap["vt"] != port {
t.Errorf("wrong port for tablet: %v", ti.PortMap["vt"])
}
if ti.PortMap["grpc"] != gRPCPort {
t.Errorf("wrong gRPC port for tablet: %v", ti.PortMap["grpc"])
}
// try to init again, this time with health check on
*initTabletType = ""

Просмотреть файл

@ -56,9 +56,6 @@ type TabletManagerClient interface {
// ChangeType asks the remote tablet to change its type
ChangeType(ctx context.Context, tablet *topo.TabletInfo, dbType pb.TabletType) error
// Scrap scraps the live running tablet
Scrap(ctx context.Context, tablet *topo.TabletInfo) error
// Sleep will sleep for a duration (used for tests)
Sleep(ctx context.Context, tablet *topo.TabletInfo, duration time.Duration) error

Просмотреть файл

@ -116,7 +116,7 @@ func FixShardReplication(ctx context.Context, ts Server, logger logutil.Logger,
}
for _, node := range sri.Nodes {
ti, err := ts.GetTablet(ctx, node.TabletAlias)
_, err := ts.GetTablet(ctx, node.TabletAlias)
if err == ErrNoNode {
logger.Warningf("Tablet %v is in the replication graph, but does not exist, removing it", node.TabletAlias)
return RemoveShardReplicationRecord(ctx, ts, cell, keyspace, shard, node.TabletAlias)
@ -126,11 +126,6 @@ func FixShardReplication(ctx context.Context, ts Server, logger logutil.Logger,
return err
}
if ti.Type == pb.TabletType_SCRAP {
logger.Warningf("Tablet %v is in the replication graph, but is scrapped, removing it", node.TabletAlias)
return RemoveShardReplicationRecord(ctx, ts, cell, keyspace, shard, node.TabletAlias)
}
logger.Infof("Keeping tablet %v in the replication graph", node.TabletAlias)
}

Просмотреть файл

@ -48,10 +48,7 @@ type TabletType string
//go:generate bsongen -file $GOFILE -type TabletType -o tablet_type_bson.go
const (
// idle - no keyspace, shard or type assigned
TYPE_IDLE = TabletType("idle")
// primary copy of data
// primary copy of data, accepts writes
TYPE_MASTER = TabletType("master")
// a slaved copy of the data ready to be promoted to master
@ -87,9 +84,6 @@ const (
// A tablet that is used by a worker process. It is probably
// lagging in replication.
TYPE_WORKER = TabletType("worker")
// a machine with data that needs to be wiped
TYPE_SCRAP = TabletType("scrap")
)
// IsTrivialTypeChange returns if this db type be trivially reassigned
@ -101,11 +95,9 @@ func IsTrivialTypeChange(oldTabletType, newTabletType pb.TabletType) bool {
case pb.TabletType_REPLICA, pb.TabletType_RDONLY, pb.TabletType_SPARE, pb.TabletType_BACKUP, pb.TabletType_EXPERIMENTAL, pb.TabletType_SCHEMA_UPGRADE, pb.TabletType_WORKER:
return true
}
case pb.TabletType_SCRAP:
return newTabletType == pb.TabletType_IDLE
case pb.TabletType_RESTORE:
switch newTabletType {
case pb.TabletType_SPARE, pb.TabletType_IDLE:
case pb.TabletType_SPARE:
return true
}
}
@ -140,27 +132,13 @@ func IsRunningUpdateStream(tt pb.TabletType) bool {
return false
}
// IsInReplicationGraph returns if this tablet appears in the replication graph
// Only IDLE and SCRAP are not in the replication graph.
// The other non-obvious types are BACKUP, SNAPSHOT_SOURCE, RESTORE:
// these have had a master at some point (or were the master), so they are
// in the graph.
func IsInReplicationGraph(tt pb.TabletType) bool {
switch tt {
case pb.TabletType_IDLE, pb.TabletType_SCRAP:
return false
}
return true
}
// IsSlaveType returns if this type should be connected to a master db
// and actively replicating?
// MASTER is not obviously (only support one level replication graph)
// IDLE and SCRAP are not either
// BACKUP, RESTORE, TYPE_WORKER may or may not be, but we don't know for sure
func IsSlaveType(tt pb.TabletType) bool {
switch tt {
case pb.TabletType_MASTER, pb.TabletType_IDLE, pb.TabletType_SCRAP, pb.TabletType_BACKUP, pb.TabletType_RESTORE, pb.TabletType_WORKER:
case pb.TabletType_MASTER, pb.TabletType_BACKUP, pb.TabletType_RESTORE, pb.TabletType_WORKER:
return false
}
return true
@ -235,13 +213,6 @@ func (ti *TabletInfo) MysqlAddr() string {
return netutil.JoinHostPort(ti.Hostname, int32(ti.PortMap["mysql"]))
}
// IsAssigned returns if this tablet ever assigned data?
// A "scrap" node will show up as assigned even though its data
// cannot be used for serving.
func (ti *TabletInfo) IsAssigned() bool {
return ti.Keyspace != "" && ti.Shard != ""
}
// DbName is usually implied by keyspace. Having the shard information in the
// database name complicates mysql replication.
func (ti *TabletInfo) DbName() string {
@ -259,11 +230,6 @@ func (ti *TabletInfo) IsInServingGraph() bool {
return IsInServingGraph(ti.Type)
}
// IsInReplicationGraph returns if this tablet is in the replication graph.
func (ti *TabletInfo) IsInReplicationGraph() bool {
return IsInReplicationGraph(ti.Type)
}
// IsSlaveType returns if this tablet's type is a slave
func (ti *TabletInfo) IsSlaveType() bool {
return IsSlaveType(ti.Type)
@ -362,43 +328,18 @@ func Validate(ctx context.Context, ts Server, tabletAlias *pb.TabletAlias) error
return fmt.Errorf("bad tablet alias data for tablet %v: %#v", topoproto.TabletAliasString(tabletAlias), tablet.Alias)
}
// Some tablets have no information to generate valid replication paths.
// We have three cases to handle:
// - we are a tablet in the replication graph, and should have
// replication data (first case below)
// - we are in scrap mode but used to be assigned in the graph
// somewhere (second case below)
// Idle tablets are just not in any graph at all, we don't even know
// their keyspace / shard to know where to check.
if tablet.IsInReplicationGraph() {
if err = ts.ValidateShard(ctx, tablet.Keyspace, tablet.Shard); err != nil {
return err
}
// Validate the entry in the shard replication nodes
if err = ts.ValidateShard(ctx, tablet.Keyspace, tablet.Shard); err != nil {
return err
}
si, err := ts.GetShardReplication(ctx, tablet.Alias.Cell, tablet.Keyspace, tablet.Shard)
if err != nil {
return err
}
si, err := ts.GetShardReplication(ctx, tablet.Alias.Cell, tablet.Keyspace, tablet.Shard)
if err != nil {
return err
}
_, err = si.GetShardReplicationNode(tabletAlias)
if err != nil {
return fmt.Errorf("tablet %v not found in cell %v shard replication: %v", tabletAlias, tablet.Alias.Cell, err)
}
} else if tablet.IsAssigned() {
// this case is to make sure a scrap node that used to be in
// a replication graph doesn't leave a node behind.
// However, while an action is running, there is some
// time where this might be inconsistent.
si, err := ts.GetShardReplication(ctx, tablet.Alias.Cell, tablet.Keyspace, tablet.Shard)
if err != nil {
return err
}
node, err := si.GetShardReplicationNode(tabletAlias)
if err != ErrNoNode {
return fmt.Errorf("unexpected replication data found(possible pending action?): %v (%v)", node, tablet.Type)
}
if _, err = si.GetShardReplicationNode(tabletAlias); err != nil {
return fmt.Errorf("tablet %v not found in cell %v shard replication: %v", tabletAlias, tablet.Alias.Cell, err)
}
return nil
@ -413,11 +354,6 @@ func (ts Server) CreateTablet(ctx context.Context, tablet *pb.Tablet) error {
return err
}
// Then add the tablet to the replication graphs
if !IsInReplicationGraph(tablet.Type) {
return nil
}
if err := UpdateTabletReplicationData(ctx, ts, tablet); err != nil {
return err
}

Просмотреть файл

@ -104,7 +104,6 @@ func (tal TabletAliasList) Swap(i, j int) {
// AllTabletTypes lists all the possible tablet types
var AllTabletTypes = []pb.TabletType{
pb.TabletType_IDLE,
pb.TabletType_MASTER,
pb.TabletType_REPLICA,
pb.TabletType_RDONLY,
@ -115,7 +114,6 @@ var AllTabletTypes = []pb.TabletType{
pb.TabletType_BACKUP,
pb.TabletType_RESTORE,
pb.TabletType_WORKER,
pb.TabletType_SCRAP,
}
// SlaveTabletTypes contains all the tablet type that can have replication

Просмотреть файл

@ -87,13 +87,6 @@ func rebuildCellSrvShard(ctx context.Context, log logutil.Logger, ts topo.Server
// Build up the serving graph from scratch.
serving := make(map[pb.TabletType]*pb.EndPoints)
for _, tablet := range tablets {
if !tablet.IsInReplicationGraph() {
// only valid case is a scrapped master in the
// catastrophic reparent case
log.Warningf("Tablet %v should not be in the replication graph, please investigate (it is being ignored in the rebuild)", tablet.Alias)
continue
}
// Only add serving types.
if !tablet.IsInServingGraph() {
continue

Просмотреть файл

@ -43,59 +43,8 @@ func ConfigureTabletHook(hk *hook.Hook, tabletAlias *pb.TabletAlias) {
hk.ExtraEnv["TABLET_ALIAS"] = topoproto.TabletAliasString(tabletAlias)
}
// Scrap will update the tablet type to 'Scrap', and remove it from
// the serving graph.
//
// 'force' means we are not on the tablet being scrapped, so it is
// probably dead. So if 'force' is true, we will also remove pending
// remote actions. And if 'force' is false, we also run an optional
// hook.
func Scrap(ctx context.Context, ts topo.Server, tabletAlias *pb.TabletAlias, force bool) error {
// Update the tablet first, since that is canonical.
var wasAssigned bool
var tablet *pb.Tablet
err := ts.UpdateTabletFields(ctx, tabletAlias, func(t *pb.Tablet) error {
wasAssigned = topoproto.TabletIsAssigned(t)
t.Type = pb.TabletType_SCRAP
tablet = t
return nil
})
if err != nil {
return err
}
// If you are already scrap, skip updating replication data. It won't
// be there anyway.
if wasAssigned {
err = topo.DeleteTabletReplicationData(ctx, ts, tablet)
if err != nil {
if err == topo.ErrNoNode {
log.V(6).Infof("no ShardReplication object for cell %v", tablet.Alias.Cell)
err = nil
}
if err != nil {
log.Warningf("remove replication data for %v failed: %v", tablet.Alias, err)
}
}
}
// run a hook for final cleanup, only in non-force mode.
// (force mode executes on the vtctl side, not on the vttablet side)
if !force {
hk := hook.NewSimpleHook("postflight_scrap")
ConfigureTabletHook(hk, tablet.Alias)
if hookErr := hk.ExecuteOptional(); hookErr != nil {
// we don't want to return an error, the server
// is already in bad shape probably.
log.Warningf("Scrap: postflight_scrap failed: %v", hookErr)
}
}
return nil
}
// ChangeType changes the type of the tablet and possibly also updates
// the health informaton for it. Make this external, since these
// the health information for it. Make this external, since these
// transitions need to be forced from time to time.
//
// - if health is nil, we don't touch the Tablet's Health record.
@ -108,12 +57,6 @@ func ChangeType(ctx context.Context, ts topo.Server, tabletAlias *pb.TabletAlias
}
tablet.Type = newType
if newType == pb.TabletType_IDLE {
tablet.Keyspace = ""
tablet.Shard = ""
tablet.KeyRange = nil
tablet.HealthMap = health
}
if health != nil {
if len(health) == 0 {
tablet.HealthMap = nil
@ -124,3 +67,22 @@ func ChangeType(ctx context.Context, ts topo.Server, tabletAlias *pb.TabletAlias
return nil
})
}
// DeleteTablet removes a tablet record from the topology:
// - the replication data record if any
// - the tablet record
func DeleteTablet(ctx context.Context, ts topo.Server, tablet *pb.Tablet) error {
// try to remove replication data, no fatal if we fail
if err := topo.DeleteTabletReplicationData(ctx, ts, tablet); err != nil {
if err == topo.ErrNoNode {
log.V(6).Infof("no ShardReplication object for cell %v", tablet.Alias.Cell)
err = nil
}
if err != nil {
log.Warningf("remove replication data for %v failed: %v", topoproto.TabletAliasString(tablet.Alias), err)
}
}
// then delete the tablet record
return ts.DeleteTablet(ctx, tablet.Alias)
}

Просмотреть файл

@ -171,8 +171,6 @@ func (ks KeyspaceNodes) HasType(tabletType pb.TabletType) bool {
// Topology is the entire set of tablets in the topology.
type Topology struct {
Assigned map[string]*KeyspaceNodes // indexed by keyspace name
Idle []*TabletNode
Scrap []*TabletNode
Partial bool
}
@ -180,8 +178,6 @@ type Topology struct {
func DbTopology(ctx context.Context, ts topo.Server) (*Topology, error) {
topology := &Topology{
Assigned: make(map[string]*KeyspaceNodes),
Idle: make([]*TabletNode, 0),
Scrap: make([]*TabletNode, 0),
Partial: false,
}
@ -200,30 +196,23 @@ func DbTopology(ctx context.Context, ts topo.Server) (*Topology, error) {
assigned := make(map[string]map[string][]*TabletNodesByType)
for _, ti := range tabletInfos {
tablet := newTabletNodeFromTabletInfo(ti)
switch ti.Type {
case pb.TabletType_IDLE:
topology.Idle = append(topology.Idle, tablet)
case pb.TabletType_SCRAP:
topology.Scrap = append(topology.Scrap, tablet)
default:
if _, ok := assigned[ti.Keyspace]; !ok {
assigned[ti.Keyspace] = make(map[string][]*TabletNodesByType)
}
var tabletNode *TabletNodesByType
for _, tabletNodes := range assigned[ti.Keyspace][ti.Shard] {
if tabletNodes.TabletType == ti.Type {
tabletNode = tabletNodes
break
}
}
if tabletNode == nil {
tabletNode = &TabletNodesByType{
TabletType: ti.Type,
}
assigned[ti.Keyspace][ti.Shard] = append(assigned[ti.Keyspace][ti.Shard], tabletNode)
}
tabletNode.Nodes = append(tabletNode.Nodes, tablet)
if _, ok := assigned[ti.Keyspace]; !ok {
assigned[ti.Keyspace] = make(map[string][]*TabletNodesByType)
}
var tabletNode *TabletNodesByType
for _, tabletNodes := range assigned[ti.Keyspace][ti.Shard] {
if tabletNodes.TabletType == ti.Type {
tabletNode = tabletNodes
break
}
}
if tabletNode == nil {
tabletNode = &TabletNodesByType{
TabletType: ti.Type,
}
assigned[ti.Keyspace][ti.Shard] = append(assigned[ti.Keyspace][ti.Shard], tabletNode)
}
tabletNode.Nodes = append(tabletNode.Nodes, tablet)
}
for keyspace, shardMap := range assigned {

Просмотреть файл

@ -98,10 +98,10 @@ func SortedTabletMap(tabletMap map[pb.TabletAlias]*topo.TabletInfo) (map[pb.Tabl
slaveMap := make(map[pb.TabletAlias]*topo.TabletInfo)
masterMap := make(map[pb.TabletAlias]*topo.TabletInfo)
for alias, ti := range tabletMap {
if ti.Type != pb.TabletType_MASTER && ti.Type != pb.TabletType_SCRAP {
slaveMap[alias] = ti
} else {
if ti.Type == pb.TabletType_MASTER {
masterMap[alias] = ti
} else {
slaveMap[alias] = ti
}
}
return slaveMap, masterMap

Просмотреть файл

@ -54,23 +54,14 @@ COMMAND ARGUMENT DEFINITIONS
the tablet that indicates the tablet should not be
considered a potential master. Vitess also does not
worry about lag for experimental tablets when reparenting.
-- idle: An idle vttablet that does not have a keyspace, shard
or type assigned
-- lag: A slaved copy of data intentionally lagged for pseudo-backup.
-- lag_orphan: A tablet in the midst of a reparenting process. During that
process, the tablet goes into a <code>lag_orphan</code> state
until it is reparented properly.
-- master: A primary copy of data
-- rdonly: A slaved copy of data for OLAP load patterns
-- replica: A slaved copy of data ready to be promoted to master
-- restore: A tablet that has not been in the replication graph and is
restoring from a snapshot. Typically, a tablet progresses from
the <code>idle</code> state to the <code>restore</code> state
and then to the <code>spare</code> state.
-- restore: A tablet that is restoring from a snapshot. Typically, this
happens at tablet startup, then it goes to its right state..
-- schema_apply: A slaved copy of data that had been serving query traffic
but that is not applying a schema change. Following the
change, the tablet will revert to its serving type.
-- scrap: A tablet that contains data that needs to be wiped.
-- snapshot_source: A slaved copy of data where mysqld is <b>not</b>
running and where Vitess is serving data files to
clone slaves. Use this command to enter this mode:
@ -134,7 +125,7 @@ var commands = []commandGroup{
commandGroup{
"Tablets", []command{
command{"InitTablet", commandInitTablet,
"[-force] [-parent] [-update] [-db-name-override=<db name>] [-hostname=<hostname>] [-mysql_port=<port>] [-port=<port>] [-grpc_port=<port>] [-keyspace=<keyspace>] [-shard=<shard>] [-parent_alias=<parent alias>] <tablet alias> <tablet type>",
"[-allow_update] [-allow_different_shard] [-allow_master_override] [-parent] [-db_name_override=<db name>] [-hostname=<hostname>] [-mysql_port=<port>] [-port=<port>] [-grpc_port=<port>] -keyspace=<keyspace> -shard=<shard> <tablet alias> <tablet type>",
"Initializes a tablet in the topology.\n" +
"Valid <tablet type> values are:\n" +
" " + strings.Join(topoproto.MakeStringTypeList(topoproto.AllTabletTypes), " ")},
@ -144,12 +135,9 @@ var commands = []commandGroup{
command{"UpdateTabletAddrs", commandUpdateTabletAddrs,
"[-hostname <hostname>] [-ip-addr <ip addr>] [-mysql-port <mysql port>] [-vt-port <vt port>] [-grpc-port <grpc port>] <tablet alias> ",
"Updates the IP address and port numbers of a tablet."},
command{"ScrapTablet", commandScrapTablet,
"[-force] [-skip-rebuild] <tablet alias>",
"Scraps a tablet."},
command{"DeleteTablet", commandDeleteTablet,
"<tablet alias> ...",
"Deletes scrapped tablet(s) from the topology."},
"[-allow_master] [-skip_rebuild] <tablet alias> ...",
"Deletes tablet(s) from the topology."},
command{"SetReadOnly", commandSetReadOnly,
"<tablet alias>",
"Sets the tablet as read-only."},
@ -587,19 +575,19 @@ func parseServingTabletType3(param string) (pb.TabletType, error) {
}
func commandInitTablet(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {
var (
dbNameOverride = subFlags.String("db-name-override", "", "Overrides the name of the database that the vttablet uses")
force = subFlags.Bool("force", false, "Overwrites the node if the node already exists")
parent = subFlags.Bool("parent", false, "Creates the parent shard and keyspace if they don't yet exist")
update = subFlags.Bool("update", false, "Performs update if a tablet with the provided alias already exists")
hostname = subFlags.String("hostname", "", "The server on which the tablet is running")
mysqlPort = subFlags.Int("mysql_port", 0, "The mysql port for the mysql daemon")
port = subFlags.Int("port", 0, "The main port for the vttablet process")
grpcPort = subFlags.Int("grpc_port", 0, "The gRPC port for the vttablet process")
keyspace = subFlags.String("keyspace", "", "The keyspace to which this tablet belongs")
shard = subFlags.String("shard", "", "The shard to which this tablet belongs")
tags flagutil.StringMapValue
)
dbNameOverride := subFlags.String("db_name_override", "", "Overrides the name of the database that the vttablet uses")
allowUpdate := subFlags.Bool("allow_update", false, "Use this flag to force initialization if a tablet with the same name already exists. Use with caution.")
allowDifferentShard := subFlags.Bool("allow_different_shard", false, "Use this flag to force initialization if a tablet with the same name but a different keyspace/shard already exists. Use with caution.")
allowMasterOverride := subFlags.Bool("allow_master_override", false, "Use this flag to force initialization if a tablet is created as master, and a master for the keyspace/shard already exists. Use with caution.")
createShardAndKeyspace := subFlags.Bool("parent", false, "Creates the parent shard and keyspace if they don't yet exist")
hostname := subFlags.String("hostname", "", "The server on which the tablet is running")
mysqlPort := subFlags.Int("mysql_port", 0, "The mysql port for the mysql daemon")
port := subFlags.Int("port", 0, "The main port for the vttablet process")
grpcPort := subFlags.Int("grpc_port", 0, "The gRPC port for the vttablet process")
keyspace := subFlags.String("keyspace", "", "The keyspace to which this tablet belongs")
shard := subFlags.String("shard", "", "The shard to which this tablet belongs")
var tags flagutil.StringMapValue
subFlags.Var(&tags, "tags", "A comma-separated list of key:value pairs that are used to tag the tablet")
if err := subFlags.Parse(args); err != nil {
return err
@ -638,7 +626,7 @@ func commandInitTablet(ctx context.Context, wr *wrangler.Wrangler, subFlags *fla
tablet.PortMap["grpc"] = int32(*grpcPort)
}
return wr.InitTablet(ctx, tablet, *force, *parent, *update)
return wr.InitTablet(ctx, tablet, *allowMasterOverride, *allowDifferentShard, *createShardAndKeyspace, *allowUpdate)
}
func commandGetTablet(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {
@ -706,24 +694,9 @@ func commandUpdateTabletAddrs(ctx context.Context, wr *wrangler.Wrangler, subFla
})
}
func commandScrapTablet(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {
force := subFlags.Bool("force", false, "Changes the tablet type to <code>scrap</code> in ZooKeeper or etcd if a tablet is offline")
skipRebuild := subFlags.Bool("skip-rebuild", false, "Skips rebuilding the shard graph after scrapping the tablet")
if err := subFlags.Parse(args); err != nil {
return err
}
if subFlags.NArg() != 1 {
return fmt.Errorf("The <tablet alias> argument is required for the ScrapTablet command.")
}
tabletAlias, err := topoproto.ParseTabletAlias(subFlags.Arg(0))
if err != nil {
return err
}
return wr.Scrap(ctx, tabletAlias, *force, *skipRebuild)
}
func commandDeleteTablet(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {
allowMaster := subFlags.Bool("allow_master", false, "Allows for the master tablet of a shard to be deleted. Use with caution.")
skipRebuild := subFlags.Bool("skip_rebuild", false, "Skips rebuilding the shard serving graph after deleting the tablet")
if err := subFlags.Parse(args); err != nil {
return err
}
@ -736,7 +709,7 @@ func commandDeleteTablet(ctx context.Context, wr *wrangler.Wrangler, subFlags *f
return err
}
for _, tabletAlias := range tabletAliases {
if err := wr.DeleteTablet(ctx, tabletAlias); err != nil {
if err := wr.DeleteTablet(ctx, tabletAlias, *allowMaster, *skipRebuild); err != nil {
return err
}
}

Просмотреть файл

@ -256,9 +256,6 @@ func (wr *Wrangler) RebuildReplicationGraph(ctx context.Context, cells []string,
wg.Add(1)
go func(ti *topo.TabletInfo) {
defer wg.Done()
if !ti.IsInReplicationGraph() {
return
}
if !strInList(keyspaces, ti.Keyspace) {
return
}

Просмотреть файл

@ -207,8 +207,8 @@ func (wr *Wrangler) initShardMasterLocked(ctx context.Context, ev *events.Repare
wr.logger.Warningf("master-elect tablet %v is not a master in the shard, proceeding anyway as -force was used", topoproto.TabletAliasString(masterElectTabletAlias))
}
haveOtherMaster := false
for alias, ti := range masterTabletMap {
if !topoproto.TabletAliasEqual(&alias, masterElectTabletAlias) && ti.Type != pb.TabletType_SCRAP {
for alias, _ := range masterTabletMap {
if !topoproto.TabletAliasEqual(&alias, masterElectTabletAlias) {
haveOtherMaster = true
}
}
@ -505,7 +505,7 @@ func (wr *Wrangler) emergencyReparentShardLocked(ctx context.Context, ev *events
// Deal with the old master: try to remote-scrap it, if it's
// truely dead we force-scrap it. Remove it from our map in any case.
if shardInfo.HasMaster() {
scrapOldMaster := true
deleteOldMaster := true
oldMasterTabletInfo, ok := tabletMap[*shardInfo.MasterAlias]
if ok {
delete(tabletMap, *shardInfo.MasterAlias)
@ -513,23 +513,19 @@ func (wr *Wrangler) emergencyReparentShardLocked(ctx context.Context, ev *events
oldMasterTabletInfo, err = wr.ts.GetTablet(ctx, shardInfo.MasterAlias)
if err != nil {
wr.logger.Warningf("cannot read old master tablet %v, won't touch it: %v", topoproto.TabletAliasString(shardInfo.MasterAlias), err)
scrapOldMaster = false
deleteOldMaster = false
}
}
if scrapOldMaster {
if deleteOldMaster {
ev.OldMaster = *oldMasterTabletInfo.Tablet
wr.logger.Infof("scrapping old master %v", topoproto.TabletAliasString(shardInfo.MasterAlias))
wr.logger.Infof("deleting old master %v", topoproto.TabletAliasString(shardInfo.MasterAlias))
ctx, cancel := context.WithTimeout(ctx, waitSlaveTimeout)
defer cancel()
if err := wr.tmc.Scrap(ctx, oldMasterTabletInfo); err != nil {
wr.logger.Warningf("remote scrapping failed master failed, will force the scrap: %v", err)
if err := topotools.Scrap(ctx, wr.ts, shardInfo.MasterAlias, true); err != nil {
wr.logger.Warningf("old master topo scrapping failed, continuing anyway: %v", err)
}
if err := topotools.DeleteTablet(ctx, wr.ts, oldMasterTabletInfo.Tablet); err != nil {
wr.logger.Warningf("failed to delete old master tablet %v: %v", topoproto.TabletAliasString(shardInfo.MasterAlias), err)
}
}
}

Просмотреть файл

@ -378,7 +378,6 @@ func (wr *Wrangler) applySchemaShardComplex(ctx context.Context, statusArray []*
// if newParentTabletAlias is passed in, use that as the new master
if !topoproto.TabletAliasIsZero(newParentTabletAlias) {
log.Infof("Reparenting with new master set to %v", topoproto.TabletAliasString(newParentTabletAlias))
oldMasterAlias := shardInfo.MasterAlias
// Create reusable Reparent event with available info
ev := &events.Reparent{}
@ -387,13 +386,9 @@ func (wr *Wrangler) applySchemaShardComplex(ctx context.Context, statusArray []*
return nil, err
}
// Here we would apply the schema change to the old
// master, but we just scrap it, to be consistent
// with the previous implementation of the reparent.
// (this code will be refactored at some point anyway)
if err := wr.Scrap(ctx, oldMasterAlias, false, false); err != nil {
wr.Logger().Warningf("Scrapping old master %v from shard %v/%v failed: %v", topoproto.TabletAliasString(oldMasterAlias), shardInfo.Keyspace(), shardInfo.ShardName(), err)
}
// FIXME(alainjobart) Here we would apply the schema
// change to the old master, but there is nothign we
// can do now.
}
return &myproto.SchemaChangeResult{BeforeSchema: preflight.BeforeSchema, AfterSchema: preflight.AfterSchema}, nil
}

Просмотреть файл

@ -29,7 +29,7 @@ func (wr *Wrangler) unlockShard(ctx context.Context, keyspace, shard string, act
// updateShardCellsAndMaster will update the 'Cells' and possibly
// MasterAlias records for the shard, if needed.
func (wr *Wrangler) updateShardCellsAndMaster(ctx context.Context, si *topo.ShardInfo, tabletAlias *pb.TabletAlias, tabletType pb.TabletType, force bool) error {
func (wr *Wrangler) updateShardCellsAndMaster(ctx context.Context, si *topo.ShardInfo, tabletAlias *pb.TabletAlias, tabletType pb.TabletType, allowMasterOverride bool) error {
// See if we need to update the Shard:
// - add the tablet's cell to the shard's Cells if needed
// - change the master if needed
@ -65,7 +65,7 @@ func (wr *Wrangler) updateShardCellsAndMaster(ctx context.Context, si *topo.Shar
wasUpdated = true
}
if tabletType == pb.TabletType_MASTER && !topoproto.TabletAliasEqual(si.MasterAlias, tabletAlias) {
if si.HasMaster() && !force {
if si.HasMaster() && !allowMasterOverride {
return wr.unlockShard(ctx, keyspace, shard, actionNode, lockPath, fmt.Errorf("creating this tablet would override old master %v in shard %v/%v", topoproto.TabletAliasString(si.MasterAlias), keyspace, shard))
}
si.MasterAlias = tabletAlias

Просмотреть файл

@ -24,95 +24,78 @@ import (
// in the tablet, and the tablet has a slave type, we will find the
// appropriate parent. If createShardAndKeyspace is true and the
// parent keyspace or shard don't exist, they will be created. If
// update is true, and a tablet with the same ID exists, update it.
// If Force is true, and a tablet with the same ID already exists, it
// will be scrapped and deleted, and then recreated.
func (wr *Wrangler) InitTablet(ctx context.Context, tablet *pb.Tablet, force, createShardAndKeyspace, update bool) error {
// allowUpdate is true, and a tablet with the same ID exists, just update it.
// If a tablet already exists, and has a different keyspace / shard,
// allowDifferentShard must be set to accept the update.
// If a tablet is created as master, and there is already a different
// master in the shard, allowMasterOverride must be set.
func (wr *Wrangler) InitTablet(ctx context.Context, tablet *pb.Tablet, allowMasterOverride, allowDifferentShard, createShardAndKeyspace, allowUpdate bool) error {
if err := topo.TabletComplete(tablet); err != nil {
return err
}
if topo.IsInReplicationGraph(tablet.Type) {
// get the shard, possibly creating it
var err error
var si *topo.ShardInfo
// get the shard, possibly creating it
var err error
var si *topo.ShardInfo
if createShardAndKeyspace {
// create the parent keyspace and shard if needed
si, err = topotools.GetOrCreateShard(ctx, wr.ts, tablet.Keyspace, tablet.Shard)
} else {
si, err = wr.ts.GetShard(ctx, tablet.Keyspace, tablet.Shard)
if err == topo.ErrNoNode {
return fmt.Errorf("missing parent shard, use -parent option to create it, or CreateKeyspace / CreateShard")
}
if createShardAndKeyspace {
// create the parent keyspace and shard if needed
si, err = topotools.GetOrCreateShard(ctx, wr.ts, tablet.Keyspace, tablet.Shard)
} else {
si, err = wr.ts.GetShard(ctx, tablet.Keyspace, tablet.Shard)
if err == topo.ErrNoNode {
return fmt.Errorf("missing parent shard, use -parent option to create it, or CreateKeyspace / CreateShard")
}
}
// get the shard, checks a couple things
// get the shard, checks a couple things
if err != nil {
return fmt.Errorf("cannot get (or create) shard %v/%v: %v", tablet.Keyspace, tablet.Shard, err)
}
if !key.KeyRangeEqual(si.KeyRange, tablet.KeyRange) {
return fmt.Errorf("shard %v/%v has a different KeyRange: %v != %v", tablet.Keyspace, tablet.Shard, si.KeyRange, tablet.KeyRange)
}
if tablet.Type == pb.TabletType_MASTER && si.HasMaster() && !topoproto.TabletAliasEqual(si.MasterAlias, tablet.Alias) && !allowMasterOverride {
return fmt.Errorf("creating this tablet would override old master %v in shard %v/%v, use allow_master_override flag", topoproto.TabletAliasString(si.MasterAlias), tablet.Keyspace, tablet.Shard)
}
// update the shard record if needed
if err := wr.updateShardCellsAndMaster(ctx, si, tablet.Alias, tablet.Type, allowMasterOverride); err != nil {
return err
}
err = wr.ts.CreateTablet(ctx, tablet)
if err == topo.ErrNodeExists && allowUpdate {
// Try to update then
oldTablet, err := wr.ts.GetTablet(ctx, tablet.Alias)
if err != nil {
return fmt.Errorf("cannot get (or create) shard %v/%v: %v", tablet.Keyspace, tablet.Shard, err)
}
if !key.KeyRangeEqual(si.KeyRange, tablet.KeyRange) {
return fmt.Errorf("shard %v/%v has a different KeyRange: %v != %v", tablet.Keyspace, tablet.Shard, si.KeyRange, tablet.KeyRange)
}
if tablet.Type == pb.TabletType_MASTER && si.HasMaster() && !topoproto.TabletAliasEqual(si.MasterAlias, tablet.Alias) && !force {
return fmt.Errorf("creating this tablet would override old master %v in shard %v/%v", topoproto.TabletAliasString(si.MasterAlias), tablet.Keyspace, tablet.Shard)
return fmt.Errorf("failed reading existing tablet %v: %v", topoproto.TabletAliasString(tablet.Alias), err)
}
// update the shard record if needed
if err := wr.updateShardCellsAndMaster(ctx, si, tablet.Alias, tablet.Type, force); err != nil {
return err
// Check we have the same keyspace / shard, and if not,
// require the allowDifferentShard flag.
if (oldTablet.Keyspace != tablet.Keyspace || oldTablet.Shard != tablet.Shard) && !allowDifferentShard {
return fmt.Errorf("old tablet has shard %v/%v, cannot override with shard %v/%v unless allow_different_shard is set", oldTablet.Keyspace, oldTablet.Shard, tablet.Keyspace, tablet.Shard)
}
*(oldTablet.Tablet) = *tablet
if err := wr.ts.UpdateTablet(ctx, oldTablet); err != nil {
return fmt.Errorf("failed updating tablet %v: %v", topoproto.TabletAliasString(tablet.Alias), err)
}
}
err := wr.ts.CreateTablet(ctx, tablet)
if err != nil && err == topo.ErrNodeExists {
// Try to update nicely, but if it fails fall back to force behavior.
if update || force {
oldTablet, err := wr.ts.GetTablet(ctx, tablet.Alias)
if err != nil {
wr.Logger().Warningf("failed reading tablet %v: %v", topoproto.TabletAliasString(tablet.Alias), err)
} else {
if oldTablet.Keyspace == tablet.Keyspace && oldTablet.Shard == tablet.Shard {
*(oldTablet.Tablet) = *tablet
if err := wr.ts.UpdateTablet(ctx, oldTablet); err != nil {
wr.Logger().Warningf("failed updating tablet %v: %v", topoproto.TabletAliasString(tablet.Alias), err)
// now fall through the Scrap case
} else {
if !topo.IsInReplicationGraph(tablet.Type) {
return nil
}
if err := topo.UpdateTabletReplicationData(ctx, wr.ts, tablet); err != nil {
wr.Logger().Warningf("failed updating tablet replication data for %v: %v", topoproto.TabletAliasString(tablet.Alias), err)
// now fall through the Scrap case
} else {
return nil
}
}
}
}
}
if force {
if err = wr.Scrap(ctx, tablet.Alias, force, false); err != nil {
wr.Logger().Errorf("failed scrapping tablet %v: %v", topoproto.TabletAliasString(tablet.Alias), err)
return err
}
if err := wr.ts.DeleteTablet(ctx, tablet.Alias); err != nil {
// we ignore this
wr.Logger().Errorf("failed deleting tablet %v: %v", topoproto.TabletAliasString(tablet.Alias), err)
}
return wr.ts.CreateTablet(ctx, tablet)
}
// now update the replication data
if err := topo.UpdateTabletReplicationData(ctx, wr.ts, tablet); err != nil {
return fmt.Errorf("failed updating tablet replication data for %v: %v", topoproto.TabletAliasString(tablet.Alias), err)
}
return err
return nil
}
// Scrap a tablet. If force is used, we write to topo.Server
// directly and don't remote-execute the command.
//
// If we scrap the master for a shard, we will clear its record
// from the Shard object (only if that was the right master)
func (wr *Wrangler) Scrap(ctx context.Context, tabletAlias *pb.TabletAlias, force, skipRebuild bool) error {
// DeleteTablet removes a tablet from a shard.
// - if allowMaster is set, we can Delete a master tablet (and clear
// its record from the Shard record if it was the master).
// - if skipRebuild is set, we do not rebuild the serving graph.
func (wr *Wrangler) DeleteTablet(ctx context.Context, tabletAlias *pb.TabletAlias, allowMaster, skipRebuild bool) error {
// load the tablet, see if we'll need to rebuild
ti, err := wr.ts.GetTablet(ctx, tabletAlias)
if err != nil {
@ -120,25 +103,15 @@ func (wr *Wrangler) Scrap(ctx context.Context, tabletAlias *pb.TabletAlias, forc
}
rebuildRequired := ti.IsInServingGraph()
wasMaster := ti.Type == pb.TabletType_MASTER
if force {
err = topotools.Scrap(ctx, wr.ts, ti.Alias, force)
} else {
err = wr.tmc.Scrap(ctx, ti)
if wasMaster && !allowMaster {
return fmt.Errorf("cannot delete tablet %v as it is a master, use allow_master flag", topoproto.TabletAliasString(tabletAlias))
}
if err != nil {
// remove the record and its replication graph entry
if err := topotools.DeleteTablet(ctx, wr.ts, ti.Tablet); err != nil {
return err
}
if !rebuildRequired {
wr.Logger().Infof("Rebuild not required")
return nil
}
if skipRebuild {
wr.Logger().Warningf("Rebuild required, but skipping it")
return nil
}
// update the Shard object if the master was scrapped
if wasMaster {
actionNode := actionnode.UpdateShard()
@ -162,7 +135,7 @@ func (wr *Wrangler) Scrap(ctx context.Context, tabletAlias *pb.TabletAlias, forc
return wr.unlockShard(ctx, ti.Keyspace, ti.Shard, actionNode, lockPath, err)
}
} else {
wr.Logger().Warningf("Scrapping master %v from shard %v/%v but master in Shard object was %v", topoproto.TabletAliasString(tabletAlias), ti.Keyspace, ti.Shard, si.MasterAlias)
wr.Logger().Warningf("Deleting master %v from shard %v/%v but master in Shard object was %v", topoproto.TabletAliasString(tabletAlias), ti.Keyspace, ti.Shard, si.MasterAlias)
}
// and unlock
@ -171,7 +144,15 @@ func (wr *Wrangler) Scrap(ctx context.Context, tabletAlias *pb.TabletAlias, forc
}
}
// and rebuild the original shard
// and rebuild the original shard if needed
if !rebuildRequired {
wr.Logger().Infof("Rebuild not required")
return nil
}
if skipRebuild {
wr.Logger().Warningf("Rebuild required, but skipping it")
return nil
}
_, err = wr.RebuildShardGraph(ctx, ti.Keyspace, ti.Shard, []string{ti.Alias.Cell})
return err
}
@ -260,20 +241,6 @@ func (wr *Wrangler) changeTypeInternal(ctx context.Context, tabletAlias *pb.Tabl
return nil
}
// DeleteTablet will get the tablet record, and if it's scrapped, will
// delete the record from the topology.
func (wr *Wrangler) DeleteTablet(ctx context.Context, tabletAlias *pb.TabletAlias) error {
ti, err := wr.ts.GetTablet(ctx, tabletAlias)
if err != nil {
return err
}
// refuse to delete tablets that are not scrapped
if ti.Type != pb.TabletType_SCRAP {
return fmt.Errorf("Can only delete scrapped tablets")
}
return wr.TopoServer().DeleteTablet(ctx, tabletAlias)
}
// ExecuteFetchAsDba executes a query remotely using the DBA pool
func (wr *Wrangler) ExecuteFetchAsDba(ctx context.Context, tabletAlias *pb.TabletAlias, query string, maxRows int, wantFields, disableBinlogs bool, reloadSchema bool) (*mproto.QueryResult, error) {
ti, err := wr.ts.GetTablet(ctx, tabletAlias)

Просмотреть файл

@ -126,7 +126,7 @@ func NewFakeTablet(t *testing.T, wr *wrangler.Wrangler, cell string, uid uint32,
delete(tablet.PortMap, "start_http_server")
_, force := tablet.PortMap["force_init"]
delete(tablet.PortMap, "force_init")
if err := wr.InitTablet(context.Background(), tablet, force, true, false); err != nil {
if err := wr.InitTablet(context.Background(), tablet, force, false, true, false); err != nil {
t.Fatalf("cannot create tablet %v: %v", uid, err)
}

Просмотреть файл

@ -152,12 +152,6 @@ message ChangeTypeRequest {
message ChangeTypeResponse {
}
message ScrapRequest {
}
message ScrapResponse {
}
message RefreshStateRequest {
}

Просмотреть файл

@ -39,8 +39,6 @@ service TabletManager {
// ChangeType asks the remote tablet to change its type
rpc ChangeType(tabletmanagerdata.ChangeTypeRequest) returns (tabletmanagerdata.ChangeTypeResponse) {};
rpc Scrap(tabletmanagerdata.ScrapRequest) returns (tabletmanagerdata.ScrapResponse) {};
rpc RefreshState(tabletmanagerdata.RefreshStateRequest) returns (tabletmanagerdata.RefreshStateResponse) {};
rpc RunHealthCheck(tabletmanagerdata.RunHealthCheckRequest) returns (tabletmanagerdata.RunHealthCheckResponse) {};

Просмотреть файл

@ -45,7 +45,6 @@ message TabletAlias {
enum TabletType {
option allow_alias = true; // so we can have RDONLY and BATCH co-exist
UNKNOWN = 0; // not a valid value
IDLE = 1;
MASTER = 2;
REPLICA = 3;
RDONLY = 4;
@ -56,7 +55,6 @@ enum TabletType {
BACKUP = 8;
RESTORE = 9;
WORKER = 10;
SCRAP = 11;
}
// Tablet represents information about a running instance of vttablet.

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -18,7 +18,7 @@ DESCRIPTOR = _descriptor.FileDescriptor(
name='topodata.proto',
package='topodata',
syntax='proto3',
serialized_pb=b'\n\x0etopodata.proto\x12\x08topodata\"&\n\x08KeyRange\x12\r\n\x05start\x18\x01 \x01(\x0c\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x0c\"(\n\x0bTabletAlias\x12\x0c\n\x04\x63\x65ll\x18\x01 \x01(\t\x12\x0b\n\x03uid\x18\x02 \x01(\r\"\xf1\x03\n\x06Tablet\x12$\n\x05\x61lias\x18\x01 \x01(\x0b\x32\x15.topodata.TabletAlias\x12\x10\n\x08hostname\x18\x02 \x01(\t\x12\n\n\x02ip\x18\x03 \x01(\t\x12/\n\x08port_map\x18\x04 \x03(\x0b\x32\x1d.topodata.Tablet.PortMapEntry\x12\x10\n\x08keyspace\x18\x05 \x01(\t\x12\r\n\x05shard\x18\x06 \x01(\t\x12%\n\tkey_range\x18\x07 \x01(\x0b\x32\x12.topodata.KeyRange\x12\"\n\x04type\x18\x08 \x01(\x0e\x32\x14.topodata.TabletType\x12\x18\n\x10\x64\x62_name_override\x18\t \x01(\t\x12(\n\x04tags\x18\n \x03(\x0b\x32\x1a.topodata.Tablet.TagsEntry\x12\x33\n\nhealth_map\x18\x0b \x03(\x0b\x32\x1f.topodata.Tablet.HealthMapEntry\x1a.\n\x0cPortMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x30\n\x0eHealthMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xcb\x04\n\x05Shard\x12+\n\x0cmaster_alias\x18\x01 \x01(\x0b\x32\x15.topodata.TabletAlias\x12%\n\tkey_range\x18\x02 \x01(\x0b\x32\x12.topodata.KeyRange\x12\x30\n\x0cserved_types\x18\x03 \x03(\x0b\x32\x1a.topodata.Shard.ServedType\x12\x32\n\rsource_shards\x18\x04 \x03(\x0b\x32\x1b.topodata.Shard.SourceShard\x12\r\n\x05\x63\x65lls\x18\x05 \x03(\t\x12\x36\n\x0ftablet_controls\x18\x06 \x03(\x0b\x32\x1d.topodata.Shard.TabletControl\x1a\x46\n\nServedType\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\r\n\x05\x63\x65lls\x18\x02 \x03(\t\x1ar\n\x0bSourceShard\x12\x0b\n\x03uid\x18\x01 \x01(\r\x12\x10\n\x08keyspace\x18\x02 \x01(\t\x12\r\n\x05shard\x18\x03 \x01(\t\x12%\n\tkey_range\x18\x04 \x01(\x0b\x32\x12.topodata.KeyRange\x12\x0e\n\x06tables\x18\x05 \x03(\t\x1a\x84\x01\n\rTabletControl\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\r\n\x05\x63\x65lls\x18\x02 \x03(\t\x12\x1d\n\x15\x64isable_query_service\x18\x03 \x01(\x08\x12\x1a\n\x12\x62lacklisted_tables\x18\x04 \x03(\t\"\x8a\x02\n\x08Keyspace\x12\x1c\n\x14sharding_column_name\x18\x01 \x01(\t\x12\x36\n\x14sharding_column_type\x18\x02 \x01(\x0e\x32\x18.topodata.KeyspaceIdType\x12\x19\n\x11split_shard_count\x18\x03 \x01(\x05\x12\x33\n\x0cserved_froms\x18\x04 \x03(\x0b\x32\x1d.topodata.Keyspace.ServedFrom\x1aX\n\nServedFrom\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\r\n\x05\x63\x65lls\x18\x02 \x03(\t\x12\x10\n\x08keyspace\x18\x03 \x01(\t\"w\n\x10ShardReplication\x12.\n\x05nodes\x18\x01 \x03(\x0b\x32\x1f.topodata.ShardReplication.Node\x1a\x33\n\x04Node\x12+\n\x0ctablet_alias\x18\x01 \x01(\x0b\x32\x15.topodata.TabletAlias\"\xf1\x01\n\x08\x45ndPoint\x12\x0b\n\x03uid\x18\x01 \x01(\r\x12\x0c\n\x04host\x18\x02 \x01(\t\x12\x31\n\x08port_map\x18\x03 \x03(\x0b\x32\x1f.topodata.EndPoint.PortMapEntry\x12\x35\n\nhealth_map\x18\x04 \x03(\x0b\x32!.topodata.EndPoint.HealthMapEntry\x1a.\n\x0cPortMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x30\n\x0eHealthMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"0\n\tEndPoints\x12#\n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x12.topodata.EndPoint\"T\n\x08SrvShard\x12\x0c\n\x04name\x18\x01 \x01(\t\x12%\n\tkey_range\x18\x02 \x01(\x0b\x32\x12.topodata.KeyRange\x12\x13\n\x0bmaster_cell\x18\x03 \x01(\t\"E\n\x0eShardReference\x12\x0c\n\x04name\x18\x01 \x01(\t\x12%\n\tkey_range\x18\x02 \x01(\x0b\x32\x12.topodata.KeyRange\"\xb1\x03\n\x0bSrvKeyspace\x12;\n\npartitions\x18\x01 \x03(\x0b\x32\'.topodata.SrvKeyspace.KeyspacePartition\x12\x1c\n\x14sharding_column_name\x18\x02 \x01(\t\x12\x36\n\x14sharding_column_type\x18\x03 \x01(\x0e\x32\x18.topodata.KeyspaceIdType\x12\x35\n\x0bserved_from\x18\x04 \x03(\x0b\x32 .topodata.SrvKeyspace.ServedFrom\x12\x19\n\x11split_shard_count\x18\x05 \x01(\x05\x1ar\n\x11KeyspacePartition\x12)\n\x0bserved_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\x32\n\x10shard_references\x18\x02 \x03(\x0b\x32\x18.topodata.ShardReference\x1aI\n\nServedFrom\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\x10\n\x08keyspace\x18\x02 \x01(\t*2\n\x0eKeyspaceIdType\x12\t\n\x05UNSET\x10\x00\x12\n\n\x06UINT64\x10\x01\x12\t\n\x05\x42YTES\x10\x02*\xb8\x01\n\nTabletType\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x08\n\x04IDLE\x10\x01\x12\n\n\x06MASTER\x10\x02\x12\x0b\n\x07REPLICA\x10\x03\x12\n\n\x06RDONLY\x10\x04\x12\t\n\x05\x42\x41TCH\x10\x04\x12\t\n\x05SPARE\x10\x05\x12\x10\n\x0c\x45XPERIMENTAL\x10\x06\x12\x12\n\x0eSCHEMA_UPGRADE\x10\x07\x12\n\n\x06\x42\x41\x43KUP\x10\x08\x12\x0b\n\x07RESTORE\x10\t\x12\n\n\x06WORKER\x10\n\x12\t\n\x05SCRAP\x10\x0b\x1a\x02\x10\x01\x42\x1a\n\x18\x63om.youtube.vitess.protob\x06proto3'
serialized_pb=b'\n\x0etopodata.proto\x12\x08topodata\"&\n\x08KeyRange\x12\r\n\x05start\x18\x01 \x01(\x0c\x12\x0b\n\x03\x65nd\x18\x02 \x01(\x0c\"(\n\x0bTabletAlias\x12\x0c\n\x04\x63\x65ll\x18\x01 \x01(\t\x12\x0b\n\x03uid\x18\x02 \x01(\r\"\xf1\x03\n\x06Tablet\x12$\n\x05\x61lias\x18\x01 \x01(\x0b\x32\x15.topodata.TabletAlias\x12\x10\n\x08hostname\x18\x02 \x01(\t\x12\n\n\x02ip\x18\x03 \x01(\t\x12/\n\x08port_map\x18\x04 \x03(\x0b\x32\x1d.topodata.Tablet.PortMapEntry\x12\x10\n\x08keyspace\x18\x05 \x01(\t\x12\r\n\x05shard\x18\x06 \x01(\t\x12%\n\tkey_range\x18\x07 \x01(\x0b\x32\x12.topodata.KeyRange\x12\"\n\x04type\x18\x08 \x01(\x0e\x32\x14.topodata.TabletType\x12\x18\n\x10\x64\x62_name_override\x18\t \x01(\t\x12(\n\x04tags\x18\n \x03(\x0b\x32\x1a.topodata.Tablet.TagsEntry\x12\x33\n\nhealth_map\x18\x0b \x03(\x0b\x32\x1f.topodata.Tablet.HealthMapEntry\x1a.\n\x0cPortMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a+\n\tTagsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x30\n\x0eHealthMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xcb\x04\n\x05Shard\x12+\n\x0cmaster_alias\x18\x01 \x01(\x0b\x32\x15.topodata.TabletAlias\x12%\n\tkey_range\x18\x02 \x01(\x0b\x32\x12.topodata.KeyRange\x12\x30\n\x0cserved_types\x18\x03 \x03(\x0b\x32\x1a.topodata.Shard.ServedType\x12\x32\n\rsource_shards\x18\x04 \x03(\x0b\x32\x1b.topodata.Shard.SourceShard\x12\r\n\x05\x63\x65lls\x18\x05 \x03(\t\x12\x36\n\x0ftablet_controls\x18\x06 \x03(\x0b\x32\x1d.topodata.Shard.TabletControl\x1a\x46\n\nServedType\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\r\n\x05\x63\x65lls\x18\x02 \x03(\t\x1ar\n\x0bSourceShard\x12\x0b\n\x03uid\x18\x01 \x01(\r\x12\x10\n\x08keyspace\x18\x02 \x01(\t\x12\r\n\x05shard\x18\x03 \x01(\t\x12%\n\tkey_range\x18\x04 \x01(\x0b\x32\x12.topodata.KeyRange\x12\x0e\n\x06tables\x18\x05 \x03(\t\x1a\x84\x01\n\rTabletControl\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\r\n\x05\x63\x65lls\x18\x02 \x03(\t\x12\x1d\n\x15\x64isable_query_service\x18\x03 \x01(\x08\x12\x1a\n\x12\x62lacklisted_tables\x18\x04 \x03(\t\"\x8a\x02\n\x08Keyspace\x12\x1c\n\x14sharding_column_name\x18\x01 \x01(\t\x12\x36\n\x14sharding_column_type\x18\x02 \x01(\x0e\x32\x18.topodata.KeyspaceIdType\x12\x19\n\x11split_shard_count\x18\x03 \x01(\x05\x12\x33\n\x0cserved_froms\x18\x04 \x03(\x0b\x32\x1d.topodata.Keyspace.ServedFrom\x1aX\n\nServedFrom\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\r\n\x05\x63\x65lls\x18\x02 \x03(\t\x12\x10\n\x08keyspace\x18\x03 \x01(\t\"w\n\x10ShardReplication\x12.\n\x05nodes\x18\x01 \x03(\x0b\x32\x1f.topodata.ShardReplication.Node\x1a\x33\n\x04Node\x12+\n\x0ctablet_alias\x18\x01 \x01(\x0b\x32\x15.topodata.TabletAlias\"\xf1\x01\n\x08\x45ndPoint\x12\x0b\n\x03uid\x18\x01 \x01(\r\x12\x0c\n\x04host\x18\x02 \x01(\t\x12\x31\n\x08port_map\x18\x03 \x03(\x0b\x32\x1f.topodata.EndPoint.PortMapEntry\x12\x35\n\nhealth_map\x18\x04 \x03(\x0b\x32!.topodata.EndPoint.HealthMapEntry\x1a.\n\x0cPortMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x05:\x02\x38\x01\x1a\x30\n\x0eHealthMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"0\n\tEndPoints\x12#\n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x12.topodata.EndPoint\"T\n\x08SrvShard\x12\x0c\n\x04name\x18\x01 \x01(\t\x12%\n\tkey_range\x18\x02 \x01(\x0b\x32\x12.topodata.KeyRange\x12\x13\n\x0bmaster_cell\x18\x03 \x01(\t\"E\n\x0eShardReference\x12\x0c\n\x04name\x18\x01 \x01(\t\x12%\n\tkey_range\x18\x02 \x01(\x0b\x32\x12.topodata.KeyRange\"\xb1\x03\n\x0bSrvKeyspace\x12;\n\npartitions\x18\x01 \x03(\x0b\x32\'.topodata.SrvKeyspace.KeyspacePartition\x12\x1c\n\x14sharding_column_name\x18\x02 \x01(\t\x12\x36\n\x14sharding_column_type\x18\x03 \x01(\x0e\x32\x18.topodata.KeyspaceIdType\x12\x35\n\x0bserved_from\x18\x04 \x03(\x0b\x32 .topodata.SrvKeyspace.ServedFrom\x12\x19\n\x11split_shard_count\x18\x05 \x01(\x05\x1ar\n\x11KeyspacePartition\x12)\n\x0bserved_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\x32\n\x10shard_references\x18\x02 \x03(\x0b\x32\x18.topodata.ShardReference\x1aI\n\nServedFrom\x12)\n\x0btablet_type\x18\x01 \x01(\x0e\x32\x14.topodata.TabletType\x12\x10\n\x08keyspace\x18\x02 \x01(\t*2\n\x0eKeyspaceIdType\x12\t\n\x05UNSET\x10\x00\x12\n\n\x06UINT64\x10\x01\x12\t\n\x05\x42YTES\x10\x02*\xa3\x01\n\nTabletType\x12\x0b\n\x07UNKNOWN\x10\x00\x12\n\n\x06MASTER\x10\x02\x12\x0b\n\x07REPLICA\x10\x03\x12\n\n\x06RDONLY\x10\x04\x12\t\n\x05\x42\x41TCH\x10\x04\x12\t\n\x05SPARE\x10\x05\x12\x10\n\x0c\x45XPERIMENTAL\x10\x06\x12\x12\n\x0eSCHEMA_UPGRADE\x10\x07\x12\n\n\x06\x42\x41\x43KUP\x10\x08\x12\x0b\n\x07RESTORE\x10\t\x12\n\n\x06WORKER\x10\n\x1a\x02\x10\x01\x42\x1a\n\x18\x63om.youtube.vitess.protob\x06proto3'
)
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
@ -60,58 +60,50 @@ _TABLETTYPE = _descriptor.EnumDescriptor(
options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='IDLE', index=1, number=1,
name='MASTER', index=1, number=2,
options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='MASTER', index=2, number=2,
name='REPLICA', index=2, number=3,
options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='REPLICA', index=3, number=3,
name='RDONLY', index=3, number=4,
options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='RDONLY', index=4, number=4,
name='BATCH', index=4, number=4,
options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='BATCH', index=5, number=4,
name='SPARE', index=5, number=5,
options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='SPARE', index=6, number=5,
name='EXPERIMENTAL', index=6, number=6,
options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='EXPERIMENTAL', index=7, number=6,
name='SCHEMA_UPGRADE', index=7, number=7,
options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='SCHEMA_UPGRADE', index=8, number=7,
name='BACKUP', index=8, number=8,
options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='BACKUP', index=9, number=8,
name='RESTORE', index=9, number=9,
options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='RESTORE', index=10, number=9,
options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='WORKER', index=11, number=10,
options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='SCRAP', index=12, number=11,
name='WORKER', index=10, number=10,
options=None,
type=None),
],
containing_type=None,
options=_descriptor._ParseOptions(descriptor_pb2.EnumOptions(), b'\020\001'),
serialized_start=2530,
serialized_end=2714,
serialized_end=2693,
)
_sym_db.RegisterEnumDescriptor(_TABLETTYPE)
@ -120,7 +112,6 @@ UNSET = 0
UINT64 = 1
BYTES = 2
UNKNOWN = 0
IDLE = 1
MASTER = 2
REPLICA = 3
RDONLY = 4
@ -131,7 +122,6 @@ SCHEMA_UPGRADE = 7
BACKUP = 8
RESTORE = 9
WORKER = 10
SCRAP = 11

Просмотреть файл

@ -11,7 +11,7 @@
# - we clone into 2 instances
# - we enable filtered replication
# - we move all serving types
# - we scrap the source tablets
# - we remove the source tablets
# - we remove the original shard
import base64
@ -472,9 +472,7 @@ index by_msg (msg)
# make sure we can't delete a shard with tablets
utils.run_vtctl(['DeleteShard', 'test_keyspace/0'], expect_fail=True)
# scrap the original tablets in the original shard
for t in [shard_master, shard_replica, shard_rdonly1]:
utils.run_vtctl(['ScrapTablet', t.tablet_alias], auto_log=True)
# remove the original tablets in the original shard
tablet.kill_tablets([shard_master, shard_replica, shard_rdonly1])
for t in [shard_master, shard_replica, shard_rdonly1]:
utils.run_vtctl(['DeleteTablet', t.tablet_alias], auto_log=True)

Просмотреть файл

@ -183,20 +183,7 @@ class TestReparent(unittest.TestCase):
expect_fail=True)
self.assertIn('DemoteMaster failed', stderr)
# Should fail to connect and fail
_, stderr = utils.run_vtctl(['-wait-time', '10s', 'ScrapTablet',
tablet_62344.tablet_alias],
expect_fail=True)
logging.debug('Failed ScrapTablet output:\n' + stderr)
if ('connection refused' not in stderr and
protocols_flavor().rpc_timeout_message() not in stderr):
self.fail("didn't find the right error strings in failed ScrapTablet: " +
stderr)
# Force the scrap action in zk even though tablet is not accessible.
tablet_62344.scrap(force=True)
# Re-run forced reparent operation, this should now proceed unimpeded.
# Run forced reparent operation, this should now proceed unimpeded.
utils.run_vtctl(['EmergencyReparentShard', 'test_keyspace/0',
tablet_62044.tablet_alias], auto_log=True)
@ -208,14 +195,6 @@ class TestReparent(unittest.TestCase):
self._check_vt_insert_test(tablet_41983, 2)
self._check_vt_insert_test(tablet_31981, 2)
utils.run_vtctl(['ChangeSlaveType', '-force', tablet_62344.tablet_alias,
'idle'])
idle_tablets, _ = utils.run_vtctl(['ListAllTablets', 'test_nj'],
trap_output=True)
if '0000062344 <null> <null> idle' not in idle_tablets:
self.fail('idle tablet not found: %s' % idle_tablets)
tablet.kill_tablets([tablet_62044, tablet_41983, tablet_31981])
# so the other tests don't have any surprise
@ -458,7 +437,7 @@ class TestReparent(unittest.TestCase):
and we'll call TabletExternallyReparented.
Args:
brutal: scraps the old master first
brutal: kills the old master first
"""
utils.run_vtctl(['CreateKeyspace', 'test_keyspace'])
@ -511,9 +490,9 @@ class TestReparent(unittest.TestCase):
changeMasterCmds +
['START SLAVE'])
# in brutal mode, we scrap the old master first
# in brutal mode, we kill the old master first
if brutal:
tablet_62344.scrap(force=True)
tablet_62344.kill_vttablet()
base_time = time.time()
@ -529,8 +508,9 @@ class TestReparent(unittest.TestCase):
self._test_reparent_from_outside_check(brutal, base_time)
tablet.kill_tablets([tablet_31981, tablet_62344, tablet_62044,
tablet_41983])
if not brutal:
tablet_62344.kill_vttablet()
tablet.kill_tablets([tablet_31981, tablet_62044, tablet_41983])
def _test_reparent_from_outside_check(self, brutal, base_time):

Просмотреть файл

@ -794,15 +794,14 @@ primary key (name)
self.assertIn('No binlog player is running', shard_2_master_status)
self.assertIn('</html>', shard_2_master_status)
# scrap the original tablets in the original shard
for t in [shard_1_master, shard_1_slave1, shard_1_slave2, shard_1_ny_rdonly,
shard_1_rdonly1]:
utils.run_vtctl(['ScrapTablet', t.tablet_alias], auto_log=True)
# delete the original tablets in the original shard
tablet.kill_tablets([shard_1_master, shard_1_slave1, shard_1_slave2,
shard_1_ny_rdonly, shard_1_rdonly1])
for t in [shard_1_master, shard_1_slave1, shard_1_slave2, shard_1_ny_rdonly,
for t in [shard_1_slave1, shard_1_slave2, shard_1_ny_rdonly,
shard_1_rdonly1]:
utils.run_vtctl(['DeleteTablet', t.tablet_alias], auto_log=True)
utils.run_vtctl(['DeleteTablet', '-allow_master',
shard_1_master.tablet_alias], auto_log=True)
# rebuild the serving graph, all mentions of the old shards shoud be gone
utils.run_vtctl(

Просмотреть файл

@ -123,9 +123,9 @@ class TestSchema(unittest.TestCase):
# them down now.
if shard_2_master in tablets:
for t in tablets_shard2:
t.scrap(force=True, skip_rebuild=True)
utils.run_vtctl(['DeleteTablet', t.tablet_alias], auto_log=True)
t.kill_vttablet()
utils.run_vtctl(['DeleteTablet', '-allow_master', t.tablet_alias],
auto_log=True)
tablets.remove(t)
utils.run_vtctl(['DeleteShard', 'test_keyspace/2'], auto_log=True)

Просмотреть файл

@ -73,7 +73,6 @@ class Tablet(object):
# this will eventually be coming from the proto3
tablet_type_value = {
'UNKNOWN': 0,
'IDLE': 1,
'MASTER': 2,
'REPLICA': 3,
'RDONLY': 4,
@ -84,7 +83,6 @@ class Tablet(object):
'BACKUP': 8,
'RESTORE': 9,
'WORKER': 10,
'SCRAP': 11,
}
def __init__(self, tablet_uid=None, port=None, mysql_port=None, cell=None,
@ -305,38 +303,24 @@ class Tablet(object):
]
return utils.run_vtctl(args)
def scrap(self, force=False, skip_rebuild=False):
args = ['ScrapTablet']
if force:
args.append('-force')
if skip_rebuild:
args.append('-skip-rebuild')
args.append(self.tablet_alias)
utils.run_vtctl(args, auto_log=True)
def init_tablet(self, tablet_type, keyspace=None, shard=None, force=True,
def init_tablet(self, tablet_type, keyspace, shard,
start=False, dbname=None, parent=True, wait_for_start=True,
include_mysql_port=True, **kwargs):
self.tablet_type = tablet_type
self.keyspace = keyspace
self.shard = shard
if dbname is None:
self.dbname = 'vt_' + (self.keyspace or 'database')
else:
self.dbname = dbname
self.dbname = dbname or ('vt_' + self.keyspace)
args = ['InitTablet',
'-hostname', 'localhost',
'-port', str(self.port)]
if include_mysql_port:
args.extend(['-mysql_port', str(self.mysql_port)])
if force:
args.append('-force')
if parent:
args.append('-parent')
if dbname:
args.extend(['-db-name-override', dbname])
args.extend(['-db_name_override', dbname])
if keyspace:
args.extend(['-keyspace', keyspace])
if shard:

Просмотреть файл

@ -138,23 +138,6 @@ class TestTabletManager(unittest.TestCase):
tablet_62344.kill_vttablet()
tablet_62344.init_tablet('idle')
tablet_62344.scrap(force=True)
def test_scrap(self):
# Start up a master mysql and vttablet
utils.run_vtctl(['CreateKeyspace', 'test_keyspace'])
tablet_62344.init_tablet('master', 'test_keyspace', '0')
tablet_62044.init_tablet('replica', 'test_keyspace', '0')
utils.run_vtctl(['RebuildShardGraph', 'test_keyspace/*'])
utils.validate_topology()
self._check_srv_shard()
tablet_62044.scrap(force=True)
utils.validate_topology()
self._check_srv_shard()
_create_vt_select_test = '''create table vt_select_test (
id bigint auto_increment,
msg varchar(64),
@ -326,7 +309,7 @@ class TestTabletManager(unittest.TestCase):
self.fail('proc1 still running')
tablet_62344.kill_vttablet()
def test_scrap_and_reinit(self):
def test_shard_replication_fix(self):
utils.run_vtctl(['CreateKeyspace', 'test_keyspace'])
tablet_62344.create_db('vt_test_keyspace')
@ -337,21 +320,11 @@ class TestTabletManager(unittest.TestCase):
tablet_62044.init_tablet('replica', 'test_keyspace', '0')
# make sure the replica is in the replication graph
before_scrap = utils.run_vtctl_json(['GetShardReplication', 'test_nj',
before_bogus = utils.run_vtctl_json(['GetShardReplication', 'test_nj',
'test_keyspace/0'])
self.assertEqual(2, len(before_scrap['nodes']),
self.assertEqual(2, len(before_bogus['nodes']),
'wrong shard replication nodes before: %s' %
str(before_scrap))
# scrap and re-init
utils.run_vtctl(['ScrapTablet', '-force', tablet_62044.tablet_alias])
tablet_62044.init_tablet('replica', 'test_keyspace', '0')
after_scrap = utils.run_vtctl_json(['GetShardReplication', 'test_nj',
'test_keyspace/0'])
self.assertEqual(2, len(after_scrap['nodes']),
'wrong shard replication nodes after: %s' %
str(after_scrap))
str(before_bogus))
# manually add a bogus entry to the replication graph, and check
# it is removed by ShardReplicationFix
@ -366,7 +339,7 @@ class TestTabletManager(unittest.TestCase):
auto_log=True)
after_fix = utils.run_vtctl_json(['GetShardReplication', 'test_nj',
'test_keyspace/0'])
self.assertEqual(2, len(after_scrap['nodes']),
self.assertEqual(2, len(after_fix['nodes']),
'wrong shard replication nodes after fix: %s' %
str(after_fix))

Просмотреть файл

@ -17,12 +17,9 @@ shard_0_spare = tablet.Tablet()
# range 80 - ''
shard_1_master = tablet.Tablet()
shard_1_replica = tablet.Tablet()
# not assigned
idle = tablet.Tablet()
scrap = tablet.Tablet()
# all tablets
tablets = [shard_0_master, shard_0_replica, shard_1_master, shard_1_replica,
idle, scrap, shard_0_spare]
shard_0_spare]
def setUpModule():
@ -71,8 +68,6 @@ class TestVtctld(unittest.TestCase):
shard_0_spare.init_tablet('spare', 'test_keyspace', '-80')
shard_1_master.init_tablet('master', 'test_keyspace', '80-')
shard_1_replica.init_tablet('replica', 'test_keyspace', '80-')
idle.init_tablet('idle')
scrap.init_tablet('idle')
utils.run_vtctl(['RebuildKeyspaceGraph', 'test_keyspace'], auto_log=True)
utils.run_vtctl(['RebuildKeyspaceGraph', 'redirected_keyspace'],
@ -88,20 +83,17 @@ class TestVtctld(unittest.TestCase):
target_tablet_type='replica',
wait_for_state=None)
for t in scrap, idle, shard_0_spare:
t.start_vttablet(wait_for_state=None,
extra_args=utils.vtctld.process_args())
shard_0_spare.start_vttablet(wait_for_state=None,
extra_args=utils.vtctld.process_args())
# wait for the right states
for t in [shard_0_master, shard_1_master, shard_1_replica]:
t.wait_for_vttablet_state('SERVING')
for t in [scrap, idle, shard_0_replica, shard_0_spare]:
for t in [shard_0_replica, shard_0_spare]:
t.wait_for_vttablet_state('NOT_SERVING')
scrap.scrap()
for t in [shard_0_master, shard_0_replica, shard_0_spare,
shard_1_master, shard_1_replica, idle, scrap]:
shard_1_master, shard_1_replica]:
t.reset_replication()
utils.run_vtctl(['InitShardMaster', 'test_keyspace/-80',
shard_0_master.tablet_alias], auto_log=True)
@ -154,10 +146,6 @@ class TestVtctld(unittest.TestCase):
s1 = self.data['Assigned']['test_keyspace']['ShardNodes'][1]
self.assertItemsEqual(s1['Name'], '80-')
def test_not_assigned(self):
self.assertEqual(len(self.data['Idle']), 1)
self.assertEqual(len(self.data['Scrap']), 1)
def test_partial(self):
utils.pause(
'You can now run a browser and connect to http://%s:%d to '

Просмотреть файл

@ -351,14 +351,22 @@ class TestBaseSplitClone(unittest.TestCase):
When benchmarked, this seemed to take around 30% of the time of
(setupModule + tearDownModule).
FIXME(aaijazi): doing this in parallel greatly reduces the time it takes.
See the kill_tablets method in tablet.py.
"""
utils.run_vtctl(['ListAllTablets', 'test_nj'])
for shard_tablet in [all_shard_tablets, shard_0_tablets, shard_1_tablets]:
for tablet in shard_tablet.all_tablets:
tablet.reset_replication()
tablet.clean_dbs()
tablet.scrap(force=True, skip_rebuild=True)
utils.run_vtctl(['DeleteTablet', tablet.tablet_alias], auto_log=True)
tablet.kill_vttablet()
# we allow failures here as some tablets will be gone sometimes
# (the master tablets after an emergency reparent)
utils.run_vtctl(['DeleteTablet', '-allow_master', tablet.tablet_alias],
auto_log=True, raise_on_error=False)
utils.run_vtctl(['RebuildKeyspaceGraph', 'test_keyspace'], auto_log=True)
for shard in ['0', '-80', '80-']:
utils.run_vtctl(