etcdserver/server.go
func (s *EtcdServer) MoveLeader(ctx context.Context, lead, transferee uint64) error {
	now := time.Now()
	interval := time.Duration(s.Cfg.TickMs) * time.Millisecond

	if lg := s.getLogger(); lg != nil {
		lg.Info(
			"leadership transfer starting",
			zap.String("local-member-id", s.ID().String()),
			zap.String("current-leader-member-id", types.ID(lead).String()),
			zap.String("transferee-member-id", types.ID(transferee).String()),
		)
	} else {
		plog.Infof("%s starts leadership transfer from %s to %s", s.ID(), types.ID(lead), types.ID(transferee))
	}

	s.r.TransferLeadership(ctx, lead, transferee)
	for s.Lead() != transferee {
		select {
		case <-ctx.Done(): // time out
			return ErrTimeoutLeaderTransfer
		case <-time.After(interval):
		}
	}

	// TODO: drain all requests, or drop all messages to the old leader
	if lg := s.getLogger(); lg != nil {
		lg.Info(
			"leadership transfer finished",
			zap.String("local-member-id", s.ID().String()),
			zap.String("old-leader-member-id", types.ID(lead).String()),
			zap.String("new-leader-member-id", types.ID(transferee).String()),
			zap.Duration("took", time.Since(now)),
		)
	} else {
		plog.Infof("%s finished leadership transfer from %s to %s (took %v)", s.ID(), types.ID(lead), types.ID(transferee), time.Since(now))
	}
	return nil
}
func (s *EtcdServer) MoveLeader(ctx context.Context, lead, transferee uint64) error {
	now := time.Now()
	interval := time.Duration(s.Cfg.TickMs) * time.Millisecond

	if lg := s.getLogger(); lg != nil {
		lg.Info(
			"leadership transfer starting",
			zap.String("local-member-id", s.ID().String()),
			zap.String("current-leader-member-id", types.ID(lead).String()),
			zap.String("transferee-member-id", types.ID(transferee).String()),
		)
	} else {
		plog.Infof("%s starts leadership transfer from %s to %s", s.ID(), types.ID(lead), types.ID(transferee))
	}

	s.r.TransferLeadership(ctx, lead, transferee)
	for s.Lead() != transferee {
		select {
		case <-ctx.Done(): // time out
			return ErrTimeoutLeaderTransfer
		case <-time.After(interval):
		}
	}

	// TODO: drain all requests, or drop all messages to the old leader
	if lg := s.getLogger(); lg != nil {
		lg.Info(
			"leadership transfer finished",
			zap.String("local-member-id", s.ID().String()),
			zap.String("old-leader-member-id", types.ID(lead).String()),
			zap.String("new-leader-member-id", types.ID(transferee).String()),
			zap.Duration("took", time.Since(now)),
		)
	} else {
		plog.Infof("%s finished leadership transfer from %s to %s (took %v)", s.ID(), types.ID(lead), types.ID(transferee), time.Since(now))
	}
	return nil
}
// MoveLeader transfers the leader to the given transferee.