diff --git a/go/cmd/vtcombo/main.go b/go/cmd/vtcombo/main.go index 62afaa640bd..fc6ea0ca227 100644 --- a/go/cmd/vtcombo/main.go +++ b/go/cmd/vtcombo/main.go @@ -23,6 +23,7 @@ package main import ( "flag" + "os" "strings" "time" @@ -53,6 +54,10 @@ var ( schemaDir = flag.String("schema_dir", "", "Schema base directory. Should contain one directory per keyspace, with a vschema.json file if necessary.") + startMysql = flag.Bool("start_mysql", false, "Should vtcombo also start mysql") + + mysqlPort = flag.Int("mysql_port", 3306, "mysql port") + ts *topo.Server resilientServer *srvtopo.ResilientServer healthCheck discovery.LegacyHealthCheck @@ -62,6 +67,44 @@ func init() { servenv.RegisterDefaultFlags() } +func startMysqld(uid uint32) (*mysqlctl.Mysqld, *mysqlctl.Mycnf) { + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + mycnfFile := mysqlctl.MycnfFile(uid) + + var mysqld *mysqlctl.Mysqld + var cnf *mysqlctl.Mycnf + var err error + + if _, statErr := os.Stat(mycnfFile); os.IsNotExist(statErr) { + mysqld, cnf, err = mysqlctl.CreateMysqldAndMycnf(uid, "", int32(*mysqlPort)) + if err != nil { + log.Errorf("failed to initialize mysql config :%v", err) + exit.Return(1) + } + if err := mysqld.Init(ctx, cnf, ""); err != nil { + log.Errorf("failed to initialize mysql :%v", err) + exit.Return(1) + } + } else { + mysqld, cnf, err = mysqlctl.OpenMysqldAndMycnf(uid) + if err != nil { + log.Errorf("failed to find mysql config: %v", err) + exit.Return(1) + } + err = mysqld.RefreshConfig(ctx, cnf) + if err != nil { + log.Errorf("failed to refresh config: %v", err) + exit.Return(1) + } + if err := mysqld.Start(ctx, cnf); err != nil { + log.Errorf("Failed to start mysqld: %v", err) + exit.Return(1) + } + } + cancel() + return mysqld, cnf +} + func main() { defer exit.Recover() @@ -97,14 +140,30 @@ func main() { servenv.Init() tabletenv.Init() - dbconfigs.GlobalDBConfigs.InitWithSocket("") - mysqld := mysqlctl.NewMysqld(&dbconfigs.GlobalDBConfigs) - servenv.OnClose(mysqld.Close) + var mysqld *mysqlctl.Mysqld + var cnf *mysqlctl.Mycnf + if *startMysql { + mysqld, cnf = startMysqld(1) + servenv.OnClose(func() { + mysqld.Shutdown(context.TODO(), cnf, true) + }) + // We want to ensure we can write to this database + mysqld.SetReadOnly(false) + + } else { + dbconfigs.GlobalDBConfigs.InitWithSocket("") + mysqld = mysqlctl.NewMysqld(&dbconfigs.GlobalDBConfigs) + servenv.OnClose(mysqld.Close) + } // tablets configuration and init. // Send mycnf as nil because vtcombo won't do backups and restores. - if err := vtcombo.InitTabletMap(ts, tpb, mysqld, &dbconfigs.GlobalDBConfigs, *schemaDir, nil); err != nil { + if err := vtcombo.InitTabletMap(ts, tpb, mysqld, &dbconfigs.GlobalDBConfigs, *schemaDir, nil, *startMysql); err != nil { log.Errorf("initTabletMapProto failed: %v", err) + // ensure we start mysql in the event we fail here + if *startMysql { + mysqld.Shutdown(context.TODO(), cnf, true) + } exit.Return(1) } @@ -112,6 +171,9 @@ func main() { for _, ks := range tpb.Keyspaces { err := topotools.RebuildKeyspace(context.Background(), logutil.NewConsoleLogger(), ts, ks.GetName(), tpb.Cells) if err != nil { + if *startMysql { + mysqld.Shutdown(context.TODO(), cnf, true) + } log.Fatalf("Couldn't build srv keyspace for (%v: %v). Got error: %v", ks, tpb.Cells, err) } } @@ -138,6 +200,7 @@ func main() { }) servenv.OnTerm(func() { + log.Error("Terminating") // FIXME(alainjobart): stop vtgate }) servenv.OnClose(func() { diff --git a/go/vt/vtcombo/tablet_map.go b/go/vt/vtcombo/tablet_map.go index cb711f5b80a..d8a39117549 100644 --- a/go/vt/vtcombo/tablet_map.go +++ b/go/vt/vtcombo/tablet_map.go @@ -108,7 +108,7 @@ func CreateTablet(ctx context.Context, ts *topo.Server, cell string, uid uint32, // InitTabletMap creates the action agents and associated data structures // for all tablets, based on the vttest proto parameter. -func InitTabletMap(ts *topo.Server, tpb *vttestpb.VTTestTopology, mysqld mysqlctl.MysqlDaemon, dbcfgs *dbconfigs.DBConfigs, schemaDir string, mycnf *mysqlctl.Mycnf) error { +func InitTabletMap(ts *topo.Server, tpb *vttestpb.VTTestTopology, mysqld mysqlctl.MysqlDaemon, dbcfgs *dbconfigs.DBConfigs, schemaDir string, mycnf *mysqlctl.Mycnf, ensureDatabase bool) error { tabletMap = make(map[uint32]*tablet) ctx := context.Background() @@ -190,6 +190,20 @@ func InitTabletMap(ts *topo.Server, tpb *vttestpb.VTTestTopology, mysqld mysqlct rdonlys = 1 } + if ensureDatabase { + // Create Database if not exist + conn, err := mysqld.GetDbaConnection(context.TODO()) + if err != nil { + return fmt.Errorf("GetConnection failed: %v", err) + } + defer conn.Close() + + _, err = conn.ExecuteFetch("CREATE DATABASE IF NOT EXISTS `"+dbname+"`", 1, false) + if err != nil { + return fmt.Errorf("Error ensuring database exists: %v", err) + } + + } if cell == tpb.Cells[0] { replicas--