// change a tablet type to RESTORE and set all the other arguments. // from now on, we can go to: // - back to IDLE if we don't use the tablet at all (after for instance // a successful ReserveForRestore but a failed Snapshot) // - to SCRAP if something in the process on the target host fails // - to SPARE if the clone works func (ta *TabletActor) changeTypeToRestore(tablet, sourceTablet *topo.TabletInfo, parentAlias topo.TabletAlias, keyRange key.KeyRange) error { // run the optional preflight_assigned hook hk := hook.NewSimpleHook("preflight_assigned") configureTabletHook(hk, ta.tabletAlias) if err := hk.ExecuteOptional(); err != nil { return err } // change the type tablet.Parent = parentAlias tablet.Keyspace = sourceTablet.Keyspace tablet.Shard = sourceTablet.Shard tablet.Type = topo.TYPE_RESTORE tablet.KeyRange = keyRange tablet.DbNameOverride = sourceTablet.DbNameOverride if err := topo.UpdateTablet(ta.ts, tablet); err != nil { return err } // and create the replication graph items return topo.CreateTabletReplicationPaths(ta.ts, tablet.Tablet) }
// This is a quick and dirty tool to resurrect the TopologyServer data from the // canonical data stored in the tablet nodes. // // cells: local vt cells to scan for all tablets // keyspaces: list of keyspaces to rebuild func (wr *Wrangler) RebuildReplicationGraph(cells []string, keyspaces []string) error { if cells == nil || len(cells) == 0 { return fmt.Errorf("must specify cells to rebuild replication graph") } if keyspaces == nil || len(keyspaces) == 0 { return fmt.Errorf("must specify keyspaces to rebuild replication graph") } allTablets := make([]*topo.TabletInfo, 0, 1024) for _, cell := range cells { tablets, err := GetAllTablets(wr.ts, cell) if err != nil { return err } allTablets = append(allTablets, tablets...) } for _, keyspace := range keyspaces { relog.Debug("delete keyspace shards: %v", keyspace) if err := wr.ts.DeleteKeyspaceShards(keyspace); err != nil { return err } } keyspacesToRebuild := make(map[string]bool) hasErr := false mu := sync.Mutex{} wg := sync.WaitGroup{} for _, ti := range allTablets { wg.Add(1) go func(ti *topo.TabletInfo) { defer wg.Done() if !ti.IsInReplicationGraph() { return } if !strInList(keyspaces, ti.Keyspace) { return } mu.Lock() keyspacesToRebuild[ti.Keyspace] = true mu.Unlock() err := topo.CreateTabletReplicationPaths(wr.ts, ti.Tablet) if err != nil { mu.Lock() hasErr = true mu.Unlock() relog.Warning("failed creating replication path: %v", err) } }(ti) } wg.Wait() for keyspace, _ := range keyspacesToRebuild { wg.Add(1) go func(keyspace string) { defer wg.Done() if err := wr.RebuildKeyspaceGraph(keyspace, nil); err != nil { mu.Lock() hasErr = true mu.Unlock() relog.Warning("RebuildKeyspaceGraph(%v) failed: %v", keyspace, err) return } }(keyspace) } wg.Wait() if hasErr { return fmt.Errorf("some errors occurred rebuilding replication graph, consult log") } return nil }