зеркало из https://github.com/github/vitess-gh.git
Checkpoint of removing IDLE and SCRAP states. All unit tests pass,
most integration tests pass too.
This commit is contained in:
Родитель
064d932312
Коммит
73497d2a16
|
@ -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(
|
||||
|
|
Загрузка…
Ссылка в новой задаче