代码拉取完成,页面将自动刷新
/*
Copyright 2014 Outbrain Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package app
import (
"fmt"
"github.com/outbrain/golib/log"
"github.com/outbrain/golib/util"
"github.com/outbrain/orchestrator/go/config"
"github.com/outbrain/orchestrator/go/db"
"github.com/outbrain/orchestrator/go/inst"
"github.com/outbrain/orchestrator/go/logic"
"net"
"os"
"os/user"
"strings"
)
var thisInstanceKey *inst.InstanceKey
var knownCommands []string
var knownCommandsDescription map[string]string = make(map[string]string)
func cliCommand(command string, description string) string {
knownCommands = append(knownCommands, command)
knownCommandsDescription[command] = description
return command
}
func commandsListing() string {
listing := []string{}
for _, command := range knownCommands {
description := knownCommandsDescription[command]
commandListing := fmt.Sprintf("\t%-40s%s", command, description)
listing = append(listing, commandListing)
}
return strings.Join(listing, "\n")
}
func availableCommandsUsage() string {
return fmt.Sprintf(`Available commands (-c):
%+v
Run 'orchestrator' for full blown documentation
Usage for most commands:
orchestrator -c <command> [-i <instance.fqdn>] [-d <destination.fqdn>] [--verbose|--debug]
`, commandsListing())
}
func getClusterName(clusterAlias string, instanceKey *inst.InstanceKey) (clusterName string) {
var err error
if clusterAlias != "" {
clusterName, err = inst.ReadClusterByAlias(clusterAlias)
if err != nil {
log.Fatale(err)
}
} else {
// deduce cluster by instance
if instanceKey == nil {
instanceKey = thisInstanceKey
}
if instanceKey == nil {
log.Fatalf("Unable to get cluster instances: unresolved instance")
}
instance, _, err := inst.ReadInstance(instanceKey)
if err != nil {
log.Fatale(err)
}
if instance == nil {
log.Fatalf("Instance not found: %+v", *instanceKey)
}
clusterName = instance.ClusterName
}
if clusterName == "" {
log.Fatalf("Unable to determine cluster name")
}
return clusterName
}
func assignThisInstanceKey() *inst.InstanceKey {
log.Debugf("Assuming instance is this machine, %+v", thisInstanceKey)
return thisInstanceKey
}
// Cli initiates a command line interface, executing requested command.
func Cli(command string, strict bool, instance string, destination string, owner string, reason string, duration string, pattern string, clusterAlias string, pool string, hostnameFlag string) {
if instance != "" && !strings.Contains(instance, ":") {
instance = fmt.Sprintf("%s:%d", instance, config.Config.DefaultInstancePort)
}
instanceKey, err := inst.ParseInstanceKey(instance)
if err != nil {
instanceKey = nil
}
rawInstanceKey, err := inst.NewRawInstanceKey(instance)
if err != nil {
rawInstanceKey = nil
}
if destination != "" && !strings.Contains(destination, ":") {
destination = fmt.Sprintf("%s:%d", destination, config.Config.DefaultInstancePort)
}
destinationKey, err := inst.ParseInstanceKey(destination)
if err != nil {
destinationKey = nil
}
if hostname, err := os.Hostname(); err == nil {
thisInstanceKey = &inst.InstanceKey{Hostname: hostname, Port: int(config.Config.DefaultInstancePort)}
}
postponedFunctionsContainer := inst.NewPostponedFunctionsContainer()
if len(owner) == 0 {
// get os username as owner
usr, err := user.Current()
if err != nil {
log.Fatale(err)
}
owner = usr.Username
}
inst.SetMaintenanceOwner(owner)
// begin commands
switch command {
// smart mode
case cliCommand("relocate", `Relocate a slave beneath another instance`), cliCommand("relocate-below", `Relocate a slave beneath another instance`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
if destinationKey == nil {
log.Fatal("Cannot deduce destination:", destination)
}
_, err := inst.RelocateBelow(instanceKey, destinationKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(fmt.Sprintf("%s<%s", instanceKey.DisplayString(), destinationKey.DisplayString()))
}
case cliCommand("relocate-slaves", `Relocates all or part of the slaves of a given instance under another instance`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
if destinationKey == nil {
log.Fatal("Cannot deduce destination:", destination)
}
slaves, _, err, errs := inst.RelocateSlaves(instanceKey, destinationKey, pattern)
if err != nil {
log.Fatale(err)
} else {
for _, e := range errs {
log.Errore(e)
}
for _, slave := range slaves {
fmt.Println(slave.Key.DisplayString())
}
}
}
// move, binlog file:pos
case cliCommand("move-up", `Move a slave one level up the topology`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
instance, err := inst.MoveUp(instanceKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(fmt.Sprintf("%s<%s", instanceKey.DisplayString(), instance.MasterKey.DisplayString()))
}
case cliCommand("move-up-slaves", `Moves slaves of the given instance one level up the topology`):
{
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
movedSlaves, _, err, errs := inst.MoveUpSlaves(instanceKey, pattern)
if err != nil {
log.Fatale(err)
} else {
for _, e := range errs {
log.Errore(e)
}
for _, slave := range movedSlaves {
fmt.Println(slave.Key.DisplayString())
}
}
}
case cliCommand("move-below", `Moves a slave beneath its sibling. Both slaves must be actively replicating from same master.`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
if destinationKey == nil {
log.Fatal("Cannot deduce sibling:", destination)
}
_, err := inst.MoveBelow(instanceKey, destinationKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(fmt.Sprintf("%s<%s", instanceKey.DisplayString(), destinationKey.DisplayString()))
}
case cliCommand("move-equivalent", `Moves a slave beneath another server, based on previously recorded "equivalence coordinates"`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
if destinationKey == nil {
log.Fatal("Cannot deduce sibling:", destination)
}
_, err := inst.MoveEquivalent(instanceKey, destinationKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(fmt.Sprintf("%s<%s", instanceKey.DisplayString(), destinationKey.DisplayString()))
}
case cliCommand("repoint", `Make the given instance replicate from another instance without changing the binglog coordinates. Use with care`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
// destinationKey can be null, in which case the instance repoints to its existing master
instance, err := inst.Repoint(instanceKey, destinationKey, inst.GTIDHintNeutral)
if err != nil {
log.Fatale(err)
}
fmt.Println(fmt.Sprintf("%s<%s", instanceKey.DisplayString(), instance.MasterKey.DisplayString()))
}
case cliCommand("repoint-slaves", `Repoint all slaves of given instance to replicate back from the instance. Use with care`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
repointedSlaves, err, errs := inst.RepointSlavesTo(instanceKey, pattern, destinationKey)
if err != nil {
log.Fatale(err)
} else {
for _, e := range errs {
log.Errore(e)
}
for _, slave := range repointedSlaves {
fmt.Println(fmt.Sprintf("%s<%s", slave.Key.DisplayString(), instanceKey.DisplayString()))
}
}
}
case cliCommand("enslave-siblings", `Turn all siblings of a slave into its sub-slaves.`):
{
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
_, _, err := inst.EnslaveSiblings(instanceKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
case cliCommand("enslave-master", `Turn an instance into a master of its own master; essentially switch the two.`):
{
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
_, err := inst.EnslaveMaster(instanceKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
case cliCommand("make-co-master", `Create a master-master replication. Given instance is a slave which replicates directly from a master.`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
_, err := inst.MakeCoMaster(instanceKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
case cliCommand("get-candidate-slave", `Information command suggesting the most up-to-date slave of a given instance that is good for promotion`):
{
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
instance, _, _, _, err := inst.GetCandidateSlave(instanceKey, false)
if err != nil {
log.Fatale(err)
} else {
fmt.Println(instance.Key.DisplayString())
}
}
case cliCommand("regroup-slaves-bls", `Regroup Binlog Server slaves of a given instance`):
{
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
promotedBinlogServer, err := inst.RegroupSlavesBinlogServers(instanceKey, false)
if promotedBinlogServer == nil {
log.Fatalf("Could not regroup binlog server slaves of %+v; error: %+v", *instanceKey, err)
}
fmt.Println(promotedBinlogServer.Key.DisplayString())
if err != nil {
log.Fatale(err)
}
}
// move, GTID
case cliCommand("move-gtid", `Move a slave beneath another instance.`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
if destinationKey == nil {
log.Fatal("Cannot deduce sibling:", destination)
}
_, err := inst.MoveBelowGTID(instanceKey, destinationKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(fmt.Sprintf("%s<%s", instanceKey.DisplayString(), destinationKey.DisplayString()))
}
case cliCommand("move-slaves-gtid", `Moves all slaves of a given instance under another (destination) instance using GTID`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
if destinationKey == nil {
log.Fatal("Cannot deduce destination:", destination)
}
movedSlaves, _, err, errs := inst.MoveSlavesGTID(instanceKey, destinationKey, pattern)
if err != nil {
log.Fatale(err)
} else {
for _, e := range errs {
log.Errore(e)
}
for _, slave := range movedSlaves {
fmt.Println(slave.Key.DisplayString())
}
}
}
case cliCommand("regroup-slaves-gtid", `Given an instance, pick one of its slave and make it local master of its siblings, using GTID.`):
{
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
lostSlaves, movedSlaves, promotedSlave, err := inst.RegroupSlavesGTID(instanceKey, false, func(candidateSlave *inst.Instance) { fmt.Println(candidateSlave.Key.DisplayString()) })
if promotedSlave == nil {
log.Fatalf("Could not regroup slaves of %+v; error: %+v", *instanceKey, err)
}
fmt.Println(fmt.Sprintf("%s lost: %d, moved: %d",
promotedSlave.Key.DisplayString(), len(lostSlaves), len(movedSlaves)))
if err != nil {
log.Fatale(err)
}
}
// Pseudo-GTID
case cliCommand("match", `Matches a slave beneath another (destination) instance using Pseudo-GTID`),
cliCommand("match-below", `Matches a slave beneath another (destination) instance using Pseudo-GTID`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
if destinationKey == nil {
log.Fatal("Cannot deduce destination:", destination)
}
_, _, err := inst.MatchBelow(instanceKey, destinationKey, true)
if err != nil {
log.Fatale(err)
}
fmt.Println(fmt.Sprintf("%s<%s", instanceKey.DisplayString(), destinationKey.DisplayString()))
}
case cliCommand("match-up", `Transport the slave one level up the hierarchy, making it child of its grandparent, using Pseudo-GTID`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
instance, _, err := inst.MatchUp(instanceKey, true)
if err != nil {
log.Fatale(err)
}
fmt.Println(fmt.Sprintf("%s<%s", instanceKey.DisplayString(), instance.MasterKey.DisplayString()))
}
case cliCommand("rematch", `Reconnect a slave onto its master, via PSeudo-GTID.`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
instance, _, err := inst.RematchSlave(instanceKey, true)
if err != nil {
log.Fatale(err)
}
fmt.Println(fmt.Sprintf("%s<%s", instanceKey.DisplayString(), instance.MasterKey.DisplayString()))
}
case cliCommand("match-slaves", `Matches all slaves of a given instance under another (destination) instance using Pseudo-GTID`),
cliCommand("multi-match-slaves", `Matches all slaves of a given instance under another (destination) instance using Pseudo-GTID`):
{
// Move all slaves of "instance" beneath "destination"
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
if destinationKey == nil {
log.Fatal("Cannot deduce destination:", destination)
}
matchedSlaves, _, err, errs := inst.MultiMatchSlaves(instanceKey, destinationKey, pattern)
if err != nil {
log.Fatale(err)
} else {
for _, e := range errs {
log.Errore(e)
}
for _, slave := range matchedSlaves {
fmt.Println(slave.Key.DisplayString())
}
}
}
case cliCommand("match-up-slaves", `Matches slaves of the given instance one level up the topology, making them siblings of given instance, using Pseudo-GTID`):
{
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
matchedSlaves, _, err, errs := inst.MatchUpSlaves(instanceKey, pattern)
if err != nil {
log.Fatale(err)
} else {
for _, e := range errs {
log.Errore(e)
}
for _, slave := range matchedSlaves {
fmt.Println(slave.Key.DisplayString())
}
}
}
case cliCommand("regroup-slaves", `Given an instance, pick one of its slave and make it local master of its siblings, using Pseudo-GTID.`):
{
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
lostSlaves, equalSlaves, aheadSlaves, promotedSlave, err := inst.RegroupSlaves(instanceKey, false, func(candidateSlave *inst.Instance) { fmt.Println(candidateSlave.Key.DisplayString()) }, postponedFunctionsContainer)
postponedFunctionsContainer.InvokePostponed()
if promotedSlave == nil {
log.Fatalf("Could not regroup slaves of %+v; error: %+v", *instanceKey, err)
}
fmt.Println(fmt.Sprintf("%s lost: %d, trivial: %d, pseudo-gtid: %d",
promotedSlave.Key.DisplayString(), len(lostSlaves), len(equalSlaves), len(aheadSlaves)))
if err != nil {
log.Fatale(err)
}
}
case cliCommand("last-pseudo-gtid", `Find latest Pseudo-GTID entry in instance's binary logs`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatalf("Unresolved instance")
}
instance, err := inst.ReadTopologyInstance(instanceKey)
if err != nil {
log.Fatale(err)
}
if instance == nil {
log.Fatalf("Instance not found: %+v", *instanceKey)
}
coordinates, text, err := inst.FindLastPseudoGTIDEntry(instance, instance.RelaylogCoordinates, strict, nil)
if err != nil {
log.Fatale(err)
}
fmt.Println(fmt.Sprintf("%+v:%s", *coordinates, text))
}
// General replication commands
case cliCommand("enable-gtid", `If possible, turn on GTID replication`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
_, err := inst.EnableGTID(instanceKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
case cliCommand("disable-gtid", `Turn off GTID replication, back to file:pos replication`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
_, err := inst.DisableGTID(instanceKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
case cliCommand("skip-query", `Skip a single statement on a slave; either when running with GTID or without`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
_, err := inst.SkipQuery(instanceKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
case cliCommand("stop-slave", `Issue a STOP SLAVE on an instance`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
_, err := inst.StopSlave(instanceKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
case cliCommand("start-slave", `Issue a START SLAVE on an instance`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
_, err := inst.StartSlave(instanceKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
case cliCommand("restart-slave", `STOP and START SLAVE on an instance`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
_, err := inst.RestartSlave(instanceKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
case cliCommand("reset-slave", `Issues a RESET SLAVE command; use with care`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
_, err := inst.ResetSlaveOperation(instanceKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
case cliCommand("detach-slave", `Stops replication and modified binlog position into an impossible, yet reversible, value.`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
_, err := inst.DetachSlaveOperation(instanceKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
case cliCommand("reattach-slave", `Undo a detach-slave operation`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
_, err := inst.ReattachSlaveOperation(instanceKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
case cliCommand("set-read-only", `Turn an instance read-only, via SET GLOBAL read_only := 1`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
_, err := inst.SetReadOnly(instanceKey, true)
if err != nil {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
case cliCommand("set-writeable", `Turn an instance writeable, via SET GLOBAL read_only := 0`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
_, err := inst.SetReadOnly(instanceKey, false)
if err != nil {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
case cliCommand("flush-binary-logs", `Flush binary logs on an instance`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
var err error
if *config.RuntimeCLIFlags.BinlogFile == "" {
_, err = inst.FlushBinaryLogs(instanceKey, 1)
} else {
_, err = inst.FlushBinaryLogsTo(instanceKey, *config.RuntimeCLIFlags.BinlogFile)
}
if err != nil {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
case cliCommand("purge-binary-logs", `Purge binary logs of an instance`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
var err error
if *config.RuntimeCLIFlags.BinlogFile == "" {
log.Fatal("expecting --binlog value")
}
_, err = inst.PurgeBinaryLogsTo(instanceKey, *config.RuntimeCLIFlags.BinlogFile)
if err != nil {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
// Pool
case cliCommand("submit-pool-instances", `Submit a pool name with a list of instances in that pool`):
{
if pool == "" {
log.Fatal("Please submit --pool")
}
err := inst.ApplyPoolInstances(pool, instance)
if err != nil {
log.Fatale(err)
}
}
case cliCommand("cluster-pool-instances", `List all pools and their associated instances`):
{
clusterPoolInstances, err := inst.ReadAllClusterPoolInstances()
if err != nil {
log.Fatale(err)
}
for _, clusterPoolInstance := range clusterPoolInstances {
fmt.Println(fmt.Sprintf("%s\t%s\t%s\t%s:%d", clusterPoolInstance.ClusterName, clusterPoolInstance.ClusterAlias, clusterPoolInstance.Pool, clusterPoolInstance.Hostname, clusterPoolInstance.Port))
}
}
// Information
case cliCommand("find", `Find instances whose hostname matches given regex pattern`):
{
if pattern == "" {
log.Fatal("No pattern given")
}
instances, err := inst.FindInstances(pattern)
if err != nil {
log.Fatale(err)
} else {
for _, instance := range instances {
fmt.Println(instance.Key.DisplayString())
}
}
}
case cliCommand("clusters", `List all clusters known to orchestrator`):
{
clusters, err := inst.ReadClusters()
if err != nil {
log.Fatale(err)
} else {
fmt.Println(strings.Join(clusters, "\n"))
}
}
case cliCommand("topology", `Show an ascii-graph of a replication topology, given a member of that topology`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
output, err := inst.ASCIITopology(instanceKey, pattern)
if err != nil {
log.Fatale(err)
}
fmt.Println(output)
}
case cliCommand("which-instance", `Output the fully-qualified hostname:port representation of the given instance, or error if unknown`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatalf("Unable to get master: unresolved instance")
}
instance, _, err := inst.ReadInstance(instanceKey)
if err != nil {
log.Fatale(err)
}
if instance == nil {
log.Fatalf("Instance not found: %+v", *instanceKey)
}
fmt.Println(instance.Key.DisplayString())
}
case cliCommand("which-cluster", `Output the name of the cluster an instance belongs to, or error if unknown to orchestrator`):
{
clusterName := getClusterName(clusterAlias, instanceKey)
fmt.Println(clusterName)
}
case cliCommand("which-cluster-instances", `Output the list of instances participating in same cluster as given instance`):
{
clusterName := getClusterName(clusterAlias, instanceKey)
instances, err := inst.ReadClusterInstances(clusterName)
if err != nil {
log.Fatale(err)
}
for _, clusterInstance := range instances {
fmt.Println(clusterInstance.Key.DisplayString())
}
}
case cliCommand("which-cluster-osc-slaves", `Output a list of slaves in same cluster as given instance, that could serve as a pt-online-schema-change operation control slaves`):
{
clusterName := getClusterName(clusterAlias, instanceKey)
instances, err := inst.GetClusterOSCSlaves(clusterName)
if err != nil {
log.Fatale(err)
}
for _, clusterInstance := range instances {
fmt.Println(clusterInstance.Key.DisplayString())
}
}
case cliCommand("which-master", `Output the fully-qualified hostname:port representation of a given instance's master`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatalf("Unable to get master: unresolved instance")
}
instance, _, err := inst.ReadInstance(instanceKey)
if err != nil {
log.Fatale(err)
}
if instance == nil {
log.Fatalf("Instance not found: %+v", *instanceKey)
}
fmt.Println(instance.MasterKey.DisplayString())
}
case cliCommand("which-slaves", `Output the fully-qualified hostname:port list of slaves of a given instance`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatalf("Unable to get slaves: unresolved instance")
}
slaves, err := inst.ReadSlaveInstances(instanceKey)
if err != nil {
log.Fatale(err)
}
for _, slave := range slaves {
fmt.Println(slave.Key.DisplayString())
}
}
case cliCommand("instance-status", `Output short status on a given instance`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatalf("Unable to get status: unresolved instance")
}
instance, _, err := inst.ReadInstance(instanceKey)
if err != nil {
log.Fatale(err)
}
if instance == nil {
log.Fatalf("Instance not found: %+v", *instanceKey)
}
fmt.Println(instance.HumanReadableDescription())
}
case cliCommand("get-cluster-heuristic-lag", `For a given cluster (indicated by an instance or alias), output a heuristic "representative" lag of that cluster`):
{
clusterName := getClusterName(clusterAlias, instanceKey)
lag, err := inst.GetClusterHeuristicLag(clusterName)
if err != nil {
log.Fatale(err)
}
fmt.Println(lag)
}
// Instance management
case cliCommand("discover", `Lookup an instance, investigate it`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
instance, err := inst.ReadTopologyInstance(instanceKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(instance.Key.DisplayString())
}
case cliCommand("forget", `Forget about an instance's existence`):
{
if rawInstanceKey == nil {
rawInstanceKey = assignThisInstanceKey()
}
if rawInstanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
err := inst.ForgetInstance(rawInstanceKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(rawInstanceKey.DisplayString())
}
case cliCommand("begin-maintenance", `Request a maintenance lock on an instance`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
if reason == "" {
log.Fatal("--reason option required")
}
var durationSeconds int = 0
if duration != "" {
durationSeconds, err = util.SimpleTimeToSeconds(duration)
if err != nil {
log.Fatale(err)
}
if durationSeconds < 0 {
log.Fatalf("Duration value must be non-negative. Given value: %d", durationSeconds)
}
}
maintenanceKey, err := inst.BeginBoundedMaintenance(instanceKey, inst.GetMaintenanceOwner(), reason, uint(durationSeconds))
if err == nil {
log.Infof("Maintenance key: %+v", maintenanceKey)
log.Infof("Maintenance duration: %d seconds", durationSeconds)
}
if err != nil {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
case cliCommand("end-maintenance", `Remove maintenance lock from an instance`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
err := inst.EndMaintenanceByInstanceKey(instanceKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
case cliCommand("begin-downtime", `Mark an instance as downtimed`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
if reason == "" {
log.Fatal("--reason option required")
}
var durationSeconds int = 0
if duration != "" {
durationSeconds, err = util.SimpleTimeToSeconds(duration)
if err != nil {
log.Fatale(err)
}
if durationSeconds < 0 {
log.Fatalf("Duration value must be non-negative. Given value: %d", durationSeconds)
}
}
err := inst.BeginDowntime(instanceKey, inst.GetMaintenanceOwner(), reason, uint(durationSeconds))
if err == nil {
log.Infof("Downtime duration: %d seconds", durationSeconds)
} else {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
case cliCommand("end-downtime", `Indicate an instance is no longer downtimed`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
err := inst.EndDowntime(instanceKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
// Recovery & analysis
case cliCommand("recover", `Do auto-recovery given a dead instance`), cliCommand("recover-lite", `Do auto-recovery given a dead instance. Orchestrator chooses the best course of actionwithout executing external processes`):
{
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
recoveryAttempted, promotedInstanceKey, err := logic.CheckAndRecover(instanceKey, destinationKey, true, (command == "recover-lite"))
if err != nil {
log.Fatale(err)
}
if recoveryAttempted {
fmt.Println(promotedInstanceKey.DisplayString())
}
}
case cliCommand("replication-analysis", `Request an analysis of potential crash incidents in all known topologies`):
{
analysis, err := inst.GetReplicationAnalysis(false)
if err != nil {
log.Fatale(err)
}
for _, entry := range analysis {
fmt.Println(fmt.Sprintf("%s (cluster %s): %s", entry.AnalyzedInstanceKey.DisplayString(), entry.ClusterDetails.ClusterName, entry.Analysis))
}
}
// Instance meta
case cliCommand("register-candidate", `Indicate that a specific instance is a preferred candidate for master promotion`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
err := inst.RegisterCandidateInstance(instanceKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
case cliCommand("register-hostname-unresolve", `Assigns the given instance a virtual (aka "unresolved") name`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
err := inst.RegisterHostnameUnresolve(instanceKey, hostnameFlag)
if err != nil {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
case cliCommand("deregister-hostname-unresolve", `Explicitly deregister/dosassociate a hostname with an "unresolved" name`):
{
if instanceKey == nil {
instanceKey = assignThisInstanceKey()
}
if instanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
err := inst.DeregisterHostnameUnresolve(instanceKey)
if err != nil {
log.Fatale(err)
}
fmt.Println(instanceKey.DisplayString())
}
// meta
case cliCommand("snapshot-topologies", `Take a snapshot of existing topologies.`):
{
err := inst.SnapshotTopologies()
if err != nil {
log.Fatale(err)
}
}
case cliCommand("continuous", `Enter continuous mode, and actively poll for instances, diagnose problems, do maintenance`):
{
logic.ContinuousDiscovery()
}
case cliCommand("resolve", `Resolve given hostname`):
{
if rawInstanceKey == nil {
log.Fatal("Cannot deduce instance:", instance)
}
if conn, err := net.Dial("tcp", rawInstanceKey.DisplayString()); err == nil {
log.Debugf("tcp test is good; got connection %+v", conn)
conn.Close()
} else {
log.Fatale(err)
}
if cname, err := inst.GetCNAME(rawInstanceKey.Hostname); err == nil {
log.Debugf("GetCNAME() %+v, %+v", cname, err)
rawInstanceKey.Hostname = cname
fmt.Println(rawInstanceKey.DisplayString())
} else {
log.Fatale(err)
}
}
case cliCommand("reset-hostname-resolve-cache", `Clear the hostname resolve cache`):
{
err := inst.ResetHostnameResolveCache()
if err != nil {
log.Fatale(err)
}
fmt.Println("hostname resolve cache cleared")
}
case cliCommand("reset-internal-db-deployment", `Clear internal db deployment history, use if somehow corrupted internal deployment history`):
{
config.Config.SkipOrchestratorDatabaseUpdate = true
db.ResetInternalDeployment()
fmt.Println("Internal db deployment history reset. Next orchestrator execution will rebuild internal db structure (no data will be lost)")
}
// Help
case "help":
{
fmt.Fprintf(os.Stderr, availableCommandsUsage())
}
default:
log.Fatalf("Unknown command: \"%s\". %s", command, availableCommandsUsage())
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。