// ElectedNode returns the details of the elected node, as well as answering the question "is this process the elected one"? func ElectedNode() (hostname string, token string, isElected bool, err error) { query := ` select hostname, token from active_node where anchor = 1 ` db, err := db.OpenOrchestrator() if err != nil { goto Cleanup } err = sqlutils.QueryRowsMap(db, query, func(m sqlutils.RowMap) error { hostname = m.GetString("hostname") token = m.GetString("token") return nil }) Cleanup: if err != nil { log.Errore(err) } isElected = (hostname == ThisHostname && token == ProcessToken.Hash) return hostname, token, isElected, err }
// readMissingHostnamesToResolve gets those (unresolved, e.g. VIP) hostnames that *should* be present in // the hostname_resolve table, but aren't. func readMissingKeysToResolve() (result InstanceKeyMap, err error) { query := ` select hostname_unresolve.unresolved_hostname, database_instance.port from database_instance join hostname_unresolve on (database_instance.hostname = hostname_unresolve.hostname) left join hostname_resolve on (database_instance.hostname = hostname_resolve.resolved_hostname) where hostname_resolve.hostname is null ` db, err := db.OpenOrchestrator() if err != nil { goto Cleanup } err = sqlutils.QueryRowsMap(db, query, func(m sqlutils.RowMap) error { instanceKey := InstanceKey{Hostname: m.GetString("unresolved_hostname"), Port: m.GetInt("port")} result.AddKey(instanceKey) return nil }) Cleanup: if err != nil { log.Errore(err) } return result, err }
func GetEquivalentMasterCoordinates(instanceCoordinates *InstanceBinlogCoordinates) (result [](*InstanceBinlogCoordinates), err error) { query := fmt.Sprintf(` select master1_hostname as hostname, master1_port as port, master1_binary_log_file as binlog_file, master1_binary_log_pos as binlog_pos from master_position_equivalence where master2_hostname = '%s' and master2_port = '%d' and master2_binary_log_file = '%s' and master2_binary_log_pos = '%d' union select master2_hostname as hostname, master2_port as port, master2_binary_log_file as binlog_file, master2_binary_log_pos as binlog_pos from master_position_equivalence where master1_hostname = '%s' and master1_port = '%d' and master1_binary_log_file = '%s' and master1_binary_log_pos = '%d' `, instanceCoordinates.Key.Hostname, instanceCoordinates.Key.Port, instanceCoordinates.Coordinates.LogFile, instanceCoordinates.Coordinates.LogPos, instanceCoordinates.Key.Hostname, instanceCoordinates.Key.Port, instanceCoordinates.Coordinates.LogFile, instanceCoordinates.Coordinates.LogPos) db, err := db.OpenOrchestrator() if err != nil { goto Cleanup } err = sqlutils.QueryRowsMap(db, query, func(m sqlutils.RowMap) error { equivalentCoordinates := InstanceBinlogCoordinates{} equivalentCoordinates.Key.Hostname = m.GetString("hostname") equivalentCoordinates.Key.Port = m.GetInt("port") equivalentCoordinates.Coordinates.LogFile = m.GetString("binlog_file") equivalentCoordinates.Coordinates.LogPos = m.GetInt64("binlog_pos") result = append(result, &equivalentCoordinates) return nil }) Cleanup: if err != nil { return nil, err } return result, nil }
// validateTableForeignKeys makes sure no foreign keys exist on the migrated table func (this *Inspector) validateTableForeignKeys() error { query := ` SELECT COUNT(*) AS num_foreign_keys FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE REFERENCED_TABLE_NAME IS NOT NULL AND ((TABLE_SCHEMA=? AND TABLE_NAME=?) OR (REFERENCED_TABLE_SCHEMA=? AND REFERENCED_TABLE_NAME=?) ) ` numForeignKeys := 0 err := sqlutils.QueryRowsMap(this.db, query, func(rowMap sqlutils.RowMap) error { numForeignKeys = rowMap.GetInt("num_foreign_keys") return nil }, this.migrationContext.DatabaseName, this.migrationContext.OriginalTableName, this.migrationContext.DatabaseName, this.migrationContext.OriginalTableName, ) if err != nil { return err } if numForeignKeys > 0 { return log.Errorf("Found %d foreign keys on %s.%s. Foreign keys are not supported. Bailing out", numForeignKeys, sql.EscapeName(this.migrationContext.DatabaseName), sql.EscapeName(this.migrationContext.OriginalTableName)) } log.Debugf("Validated no foreign keys exist on table") return nil }
// ReadClusterDomainName reads the domain name associated with a cluster, if any func ReadClusterDomainName(clusterName string) (string, error) { domainName := "" query := fmt.Sprintf(` select domain_name from cluster_domain_name where cluster_name = '%s' `, clusterName) db, err := db.OpenOrchestrator() if err != nil { goto Cleanup } err = sqlutils.QueryRowsMap(db, query, func(m sqlutils.RowMap) error { domainName = m.GetString("domain_name") return nil }) Cleanup: if err != nil { return "", err } if domainName == "" { err = fmt.Errorf("No domain name found for cluster %s", clusterName) } return domainName, err }
// ReadClusterAliases reads the entrie cluster name aliases mapping func ReadClusterByAlias(alias string) (string, error) { clusterName := "" query := fmt.Sprintf(` select cluster_name from cluster_alias where alias = '%s' `, alias) db, err := db.OpenOrchestrator() if err != nil { goto Cleanup } err = sqlutils.QueryRowsMap(db, query, func(m sqlutils.RowMap) error { clusterName = m.GetString("cluster_name") return nil }) Cleanup: if err != nil { return "", err } if clusterName == "" { err = fmt.Errorf("No cluster found for alias %s", alias) } return clusterName, err }
func readAvailableNodes() ([]string, error) { res := []string{} query := fmt.Sprintf(` select concat(hostname, ';', token) as node from node_health where last_seen_active > now() - interval 5 minute order by hostname `) db, err := db.OpenOrchestrator() if err != nil { goto Cleanup } err = sqlutils.QueryRowsMap(db, query, func(m sqlutils.RowMap) error { res = append(res, m.GetString("node")) return nil }) Cleanup: if err != nil { log.Errore(err) } return res, err }
// ReadResolvedHostname returns the resolved hostname given a hostname, or empty if not exists func ReadResolvedHostname(hostname string) (string, error) { var resolvedHostname string = "" query := fmt.Sprintf(` select resolved_hostname from hostname_resolve where hostname = '%s' `, hostname) db, err := db.OpenOrchestrator() if err != nil { goto Cleanup } err = sqlutils.QueryRowsMap(db, query, func(m sqlutils.RowMap) error { resolvedHostname = m.GetString("resolved_hostname") return nil }) Cleanup: if err != nil { log.Errore(err) } return resolvedHostname, err }
// readAgentBasicInfo returns the basic data for an agent directly from backend table (no agent access) func readAgentBasicInfo(hostname string) (Agent, string, error) { agent := Agent{} token := "" query := fmt.Sprintf(` select hostname, port, token, last_submitted, mysql_port from host_agent where hostname = '%s' `, hostname) db, err := db.OpenOrchestrator() if err != nil { return agent, "", err } err = sqlutils.QueryRowsMap(db, query, func(m sqlutils.RowMap) error { agent.Hostname = m.GetString("hostname") agent.Port = m.GetInt("port") agent.LastSubmitted = m.GetString("last_submitted") agent.MySQLPort = m.GetInt64("mysql_port") token = m.GetString("token") return nil }) if token == "" { return agent, "", log.Errorf("Cannot get agent/token: %s", hostname) } return agent, token, nil }
// ReadClusterAliases reads the entrie cluster name aliases mapping func ReadClusterAliases() error { updatedMap := make(map[string]string) query := fmt.Sprintf(` select cluster_name, alias from cluster_alias `) db, err := db.OpenOrchestrator() if err != nil { goto Cleanup } err = sqlutils.QueryRowsMap(db, query, func(m sqlutils.RowMap) error { updatedMap[m.GetString("cluster_name")] = m.GetString("alias") return err }) Cleanup: if err != nil { log.Errore(err) } clusterAliasMapMutex.Lock() defer clusterAliasMapMutex.Unlock() clusterAliasMap = updatedMap return err }
func readAllHostnameResolves() ([]HostnameResolve, error) { res := []HostnameResolve{} query := fmt.Sprintf(` select hostname, resolved_hostname from hostname_resolve `) db, err := db.OpenOrchestrator() if err != nil { goto Cleanup } err = sqlutils.QueryRowsMap(db, query, func(m sqlutils.RowMap) error { hostnameResolve := HostnameResolve{hostname: m.GetString("hostname"), resolvedHostname: m.GetString("resolved_hostname")} res = append(res, hostnameResolve) return nil }) Cleanup: if err != nil { log.Errore(err) } return res, err }
// ReadOutdatedAgentsHosts returns agents that need to be updated func ReadOutdatedAgentsHosts() ([]string, error) { res := []string{} query := fmt.Sprintf(` select hostname from host_agent where IFNULL(last_checked < now() - interval %d minute, true) `, config.Config.AgentPollMinutes) db, err := db.OpenOrchestrator() if err != nil { goto Cleanup } err = sqlutils.QueryRowsMap(db, query, func(m sqlutils.RowMap) error { hostname := m.GetString("hostname") res = append(res, hostname) return nil }) Cleanup: if err != nil { log.Errore(err) } return res, err }
// ElectedNode returns the hostname of the elected node func ElectedNode() (string, string, bool, error) { hostname := "" token := "" isElected := false query := fmt.Sprintf(` select ifnull(max(hostname), '') as hostname, ifnull(max(token), '') as token, (ifnull(max(hostname), '') = '%s') and (ifnull(max(token), '') = '%s') as is_elected from active_node where anchor = 1 `, ThisHostname, ProcessToken.Hash) db, err := db.OpenOrchestrator() if err != nil { goto Cleanup } err = sqlutils.QueryRowsMap(db, query, func(m sqlutils.RowMap) error { hostname = m.GetString("hostname") token = m.GetString("token") isElected = m.GetBool("is_elected") return nil }) Cleanup: if err != nil { log.Errore(err) } return hostname, token, isElected, err }
// validateTable makes sure the table we need to operate on actually exists func (this *Inspector) validateTable() error { query := fmt.Sprintf(`show /* gh-ost */ table status from %s like '%s'`, sql.EscapeName(this.migrationContext.DatabaseName), this.migrationContext.OriginalTableName) tableFound := false err := sqlutils.QueryRowsMap(this.db, query, func(rowMap sqlutils.RowMap) error { this.migrationContext.TableEngine = rowMap.GetString("Engine") this.migrationContext.RowsEstimate = rowMap.GetInt64("Rows") this.migrationContext.UsedRowsEstimateMethod = base.TableStatusRowsEstimate if rowMap.GetString("Comment") == "VIEW" { return fmt.Errorf("%s.%s is a VIEW, not a real table. Bailing out", sql.EscapeName(this.migrationContext.DatabaseName), sql.EscapeName(this.migrationContext.OriginalTableName)) } tableFound = true return nil }) if err != nil { return err } if !tableFound { return log.Errorf("Cannot find table %s.%s!", sql.EscapeName(this.migrationContext.DatabaseName), sql.EscapeName(this.migrationContext.OriginalTableName)) } log.Infof("Table found. Engine=%s", this.migrationContext.TableEngine) log.Debugf("Estimated number of rows via STATUS: %d", this.migrationContext.RowsEstimate) return nil }
// Read (as much as possible of) a chunk of binary log events starting the given startingCoordinates func readBinlogEventsChunk(instanceKey *InstanceKey, startingCoordinates BinlogCoordinates) ([]BinlogEvent, error) { events := []BinlogEvent{} db, err := db.OpenTopology(instanceKey.Hostname, instanceKey.Port) if err != nil { return events, err } commandToken := math.TernaryString(startingCoordinates.Type == BinaryLog, "binlog", "relaylog") if startingCoordinates.LogFile == "" { return events, log.Errorf("readBinlogEventsChunk: empty binlog file name for %+v.", *instanceKey) } query := fmt.Sprintf("show %s events in '%s' FROM %d LIMIT %d", commandToken, startingCoordinates.LogFile, startingCoordinates.LogPos, config.Config.BinlogEventsChunkSize) err = sqlutils.QueryRowsMap(db, query, func(m sqlutils.RowMap) error { binlogEvent := BinlogEvent{} binlogEvent.Coordinates.LogFile = m.GetString("Log_name") binlogEvent.Coordinates.LogPos = m.GetInt64("Pos") binlogEvent.Coordinates.Type = startingCoordinates.Type binlogEvent.NextEventPos = m.GetInt64("End_log_pos") binlogEvent.EventType = m.GetString("Event_type") binlogEvent.Info = m.GetString("Info") events = append(events, binlogEvent) return nil }) return events, err }
// IsElected checks whether this node is the elected active node func IsElected() (bool, error) { isElected := false query := fmt.Sprintf(` select count(*) as is_elected from active_node where anchor = 1 and hostname = '%s' and token = '%s' `, ThisHostname, ProcessToken.Hash) db, err := db.OpenOrchestrator() if err != nil { goto Cleanup } err = sqlutils.QueryRowsMap(db, query, func(m sqlutils.RowMap) error { isElected = m.GetBool("is_elected") return nil }) Cleanup: if err != nil { log.Errore(err) } return isElected, err }
func main() { flag.BoolVar(&verbose, "verbose", false, "Verbose logging") flag.Parse() dsn := os.Getenv("MYSQL_DSN") // better name ? if dsn == "" { fmt.Println("Using default dsn", defaultDSN) dsn = defaultDSN } else { fmt.Println("Using dsn defined in environment variable MYSQL_DSN") } db, err := sql.Open("mysql", dsn) if err != nil { panic(err.Error()) } defer db.Close() // really connect if err = db.Ping(); err != nil { log.Fatal("Ping failure:", err) } fmt.Println("Connected to database") fmt.Println("show variables like 'maxscale%'") rows, err := db.Query("show variables like 'maxscale%'") if err != nil { log.Fatal(err) } defer rows.Close() for rows.Next() { var variable, value string if err := rows.Scan(&variable, &value); err != nil { log.Fatal(err) } namedCheckForNulls(variable, value) } if err := rows.Err(); err != nil { log.Fatal(err) } // show slave status fmt.Println("show slave status:") err = sqlutils.QueryRowsMap(db, "show slave status", func(m sqlutils.RowMap) error { namedCheckForNulls("Slave_IO_Running", m.GetString("Slave_IO_Running")) namedCheckForNulls("Slave_SQL_Running", m.GetString("Slave_SQL_Running")) namedCheckForNulls("Master_Log_File", m.GetString("Master_Log_File")) namedCheckForNulls("Relay_Master_Log_File", m.GetString("Relay_Master_Log_File")) namedCheckForNulls("Relay_Log_File", m.GetString("Relay_Log_File")) namedCheckForNulls("Executed_Gtid_Set", m.GetString("Executed_Gtid_Set")) namedCheckForNulls("UsingMariaDBGTID", m.GetString("Using_Gtid")) namedCheckForNulls("Master_Host", m.GetString("Master_Host")) return nil }) fmt.Println("other commands:") namedSingleRowQuery(db, "VERSION()", "SELECT VERSION()") namedSingleRowQuery(db, "@@hostname", "SELECT @@hostname") namedSingleRowQuery(db, "@@report_host", "SELECT @@report_host") }
// ReadMaintenanceInstanceKey will return the instanceKey for active maintenance by maintenanceToken func ReadMaintenanceInstanceKey(maintenanceToken int64) (*InstanceKey, error) { var res *InstanceKey query := fmt.Sprintf(` select hostname, port from database_instance_maintenance where database_instance_maintenance_id = %d `, maintenanceToken) db, err := db.OpenOrchestrator() if err != nil { goto Cleanup } err = sqlutils.QueryRowsMap(db, query, func(m sqlutils.RowMap) error { instanceKey, merr := NewInstanceKeyFromStrings(m.GetString("hostname"), m.GetString("port")) if merr != nil { return merr } res = instanceKey return nil }) Cleanup: if err != nil { log.Errore(err) } return res, err }
// readRecoveries reads recovery entry/audit entires from topology_recovery func readFailureDetections(whereCondition string, limit string) ([]TopologyRecovery, error) { res := []TopologyRecovery{} query := fmt.Sprintf(` select detection_id, hostname, port, in_active_period as is_active, start_active_period, end_active_period_unixtime, processing_node_hostname, processcing_node_token, analysis, cluster_name, cluster_alias, count_affected_slaves, slave_hosts from topology_failure_detection %s order by detection_id desc %s `, whereCondition, limit) db, err := db.OpenOrchestrator() if err != nil { goto Cleanup } err = sqlutils.QueryRowsMap(db, query, func(m sqlutils.RowMap) error { failureDetection := TopologyRecovery{} failureDetection.Id = m.GetInt64("detection_id") failureDetection.IsActive = m.GetBool("is_active") failureDetection.RecoveryStartTimestamp = m.GetString("start_active_period") failureDetection.ProcessingNodeHostname = m.GetString("processing_node_hostname") failureDetection.ProcessingNodeToken = m.GetString("processcing_node_token") failureDetection.AnalysisEntry.AnalyzedInstanceKey.Hostname = m.GetString("hostname") failureDetection.AnalysisEntry.AnalyzedInstanceKey.Port = m.GetInt("port") failureDetection.AnalysisEntry.Analysis = inst.AnalysisCode(m.GetString("analysis")) failureDetection.AnalysisEntry.ClusterDetails.ClusterName = m.GetString("cluster_name") failureDetection.AnalysisEntry.ClusterDetails.ClusterAlias = m.GetString("cluster_alias") failureDetection.AnalysisEntry.CountSlaves = m.GetUint("count_affected_slaves") failureDetection.AnalysisEntry.ReadSlaveHostsFromString(m.GetString("slave_hosts")) failureDetection.AnalysisEntry.ClusterDetails.ReadRecoveryInfo() res = append(res, failureDetection) return nil }) Cleanup: if err != nil { log.Errore(err) } return res, err }
// showTableStatus returns the output of `show table status like '...'` command func (this *Applier) showTableStatus(tableName string) (rowMap sqlutils.RowMap) { rowMap = nil query := fmt.Sprintf(`show /* gh-ost */ table status from %s like '%s'`, sql.EscapeName(this.migrationContext.DatabaseName), tableName) sqlutils.QueryRowsMap(this.db, query, func(m sqlutils.RowMap) error { rowMap = m return nil }) return rowMap }
func GetSelfBinlogCoordinates(db *gosql.DB) (selfBinlogCoordinates *BinlogCoordinates, err error) { err = sqlutils.QueryRowsMap(db, `show master status`, func(m sqlutils.RowMap) error { selfBinlogCoordinates = &BinlogCoordinates{ LogFile: m.GetString("File"), LogPos: m.GetInt64("Position"), } return nil }) return selfBinlogCoordinates, err }
// QueryOrchestrator func QueryOrchestrator(query string, argsArray []interface{}, on_row func(sqlutils.RowMap) error) error { if config.Config.DatabaselessMode__experimental { return nil } db, err := OpenOrchestrator() if err != nil { return err } return log.Criticale(sqlutils.QueryRowsMap(db, query, on_row, argsArray...)) }
// QueryRowsMapOrchestrator func QueryOrchestratorRowsMap(query string, on_row func(sqlutils.RowMap) error) error { if config.Config.DatabaselessMode__experimental { return nil } db, err := OpenOrchestrator() if err != nil { return err } return sqlutils.QueryRowsMap(db, query, on_row) }
// readChangelogState reads changelog hints func (this *Inspector) readChangelogState() (map[string]string, error) { query := fmt.Sprintf(` select hint, value from %s.%s where id <= 255 `, sql.EscapeName(this.migrationContext.DatabaseName), sql.EscapeName(this.migrationContext.GetChangelogTableName()), ) result := make(map[string]string) err := sqlutils.QueryRowsMap(this.db, query, func(m sqlutils.RowMap) error { result[m.GetString("hint")] = m.GetString("value") return nil }) return result, err }
func GetReplicationBinlogCoordinates(db *gosql.DB) (readBinlogCoordinates *BinlogCoordinates, executeBinlogCoordinates *BinlogCoordinates, err error) { err = sqlutils.QueryRowsMap(db, `show slave status`, func(m sqlutils.RowMap) error { readBinlogCoordinates = &BinlogCoordinates{ LogFile: m.GetString("Master_Log_File"), LogPos: m.GetInt64("Read_Master_Log_Pos"), } executeBinlogCoordinates = &BinlogCoordinates{ LogFile: m.GetString("Relay_Master_Log_File"), LogPos: m.GetInt64("Exec_Master_Log_Pos"), } return nil }) return readBinlogCoordinates, executeBinlogCoordinates, err }
func GetMasterKeyFromSlaveStatus(connectionConfig *ConnectionConfig) (masterKey *InstanceKey, err error) { currentUri := connectionConfig.GetDBUri("information_schema") db, _, err := sqlutils.GetDB(currentUri) if err != nil { return nil, err } err = sqlutils.QueryRowsMap(db, `show slave status`, func(rowMap sqlutils.RowMap) error { masterKey = &InstanceKey{ Hostname: rowMap.GetString("Master_Host"), Port: rowMap.GetInt("Master_Port"), } return nil }) return masterKey, err }
// ReadRecentAudit returns a list of audit entries order chronologically descending, using page number. func ReadRecentAudit(instanceKey *InstanceKey, page int) ([]Audit, error) { res := []Audit{} var whereCondition string if instanceKey != nil { whereCondition = fmt.Sprintf(`where hostname='%s' and port='%d'`, instanceKey.Hostname, instanceKey.Port) } query := fmt.Sprintf(` select audit_id, audit_timestamp, audit_type, hostname, port, message from audit %s order by audit_timestamp desc limit %d offset %d `, whereCondition, config.Config.AuditPageSize, page*config.Config.AuditPageSize) db, err := db.OpenOrchestrator() if err != nil { goto Cleanup } err = sqlutils.QueryRowsMap(db, query, func(m sqlutils.RowMap) error { audit := Audit{} audit.AuditId = m.GetInt64("audit_id") audit.AuditTimestamp = m.GetString("audit_timestamp") audit.AuditType = m.GetString("audit_type") audit.AuditInstanceKey.Hostname = m.GetString("hostname") audit.AuditInstanceKey.Port = m.GetInt("port") audit.Message = m.GetString("message") res = append(res, audit) return err }) Cleanup: if err != nil { log.Errore(err) } return res, err }
// ReadActiveMaintenance returns the list of currently active maintenance entries func ReadActiveMaintenance() ([]Maintenance, error) { res := []Maintenance{} query := fmt.Sprintf(` select database_instance_maintenance_id, hostname, port, begin_timestamp, timestampdiff(second, begin_timestamp, now()) as seconds_elapsed, maintenance_active, owner, reason from database_instance_maintenance where maintenance_active = 1 order by database_instance_maintenance_id `) db, err := db.OpenOrchestrator() if err != nil { goto Cleanup } err = sqlutils.QueryRowsMap(db, query, func(m sqlutils.RowMap) error { maintenance := Maintenance{} maintenance.MaintenanceId = m.GetUint("database_instance_maintenance_id") maintenance.Key.Hostname = m.GetString("hostname") maintenance.Key.Port = m.GetInt("port") maintenance.BeginTimestamp = m.GetString("begin_timestamp") maintenance.SecondsElapsed = m.GetUint("seconds_elapsed") maintenance.IsActive = m.GetBool("maintenance_active") maintenance.Owner = m.GetString("owner") maintenance.Reason = m.GetString("reason") res = append(res, maintenance) return err }) Cleanup: if err != nil { log.Errore(err) } return res, err }
// validateGrants verifies the user by which we're executing has necessary grants // to do its thang. func (this *Inspector) validateGrants() error { query := `show /* gh-ost */ grants for current_user()` foundAll := false foundSuper := false foundReplicationSlave := false foundDBAll := false err := sqlutils.QueryRowsMap(this.db, query, func(rowMap sqlutils.RowMap) error { for _, grantData := range rowMap { grant := grantData.String if strings.Contains(grant, `GRANT ALL PRIVILEGES ON *.*`) { foundAll = true } if strings.Contains(grant, `SUPER`) && strings.Contains(grant, ` ON *.*`) { foundSuper = true } if strings.Contains(grant, `REPLICATION SLAVE`) && strings.Contains(grant, ` ON *.*`) { foundReplicationSlave = true } if strings.Contains(grant, fmt.Sprintf("GRANT ALL PRIVILEGES ON `%s`.*", this.migrationContext.DatabaseName)) { foundDBAll = true } if base.StringContainsAll(grant, `ALTER`, `CREATE`, `DELETE`, `DROP`, `INDEX`, `INSERT`, `LOCK TABLES`, `SELECT`, `TRIGGER`, `UPDATE`, ` ON *.*`) { foundDBAll = true } if base.StringContainsAll(grant, `ALTER`, `CREATE`, `DELETE`, `DROP`, `INDEX`, `INSERT`, `LOCK TABLES`, `SELECT`, `TRIGGER`, `UPDATE`, fmt.Sprintf(" ON `%s`.*", this.migrationContext.DatabaseName)) { foundDBAll = true } } return nil }) if err != nil { return err } if foundAll { log.Infof("User has ALL privileges") return nil } if foundSuper && foundReplicationSlave && foundDBAll { log.Infof("User has SUPER, REPLICATION SLAVE privileges, and has ALL privileges on `%s`", this.migrationContext.DatabaseName) return nil } return log.Errorf("User has insufficient privileges for migration.") }
// readInternalDeployments reads orchestrator db deployment statements that are known to have been executed func readInternalDeployments() (baseDeployments []string, patchDeployments []string, err error) { if !config.Config.SmartOrchestratorDatabaseUpdate { return baseDeployments, patchDeployments, nil } query := fmt.Sprintf(` select deployment_type, sql_statement from _orchestrator_db_deployment order by deployment_id `) db, err := OpenOrchestrator() if err != nil { log.Fatalf("Cannot initiate orchestrator internal deployment: %+v", err) } err = sqlutils.QueryRowsMap(db, query, func(m sqlutils.RowMap) error { deploymentType := m.GetString("deployment_type") sqlStatement := m.GetString("sql_statement") if deploymentType == "base" { baseDeployments = append(baseDeployments, sqlStatement) } else if deploymentType == "patch" { patchDeployments = append(patchDeployments, sqlStatement) } else { log.Fatalf("Unknown deployment type (%+v) encountered in _orchestrator_db_deployment", deploymentType) } return nil }) if err != nil { log.Debugf("Deploying internal orchestrator tables to fix the above; this is a one time operation") // Table does not exist? Create it for first time for _, query := range internalDBDeploymentSQL { if _, err = execInternal(db, query); err != nil { log.Fatalf("Cannot initiate orchestrator internal deployment: %+v", err) } } } return baseDeployments, patchDeployments, nil }