forked from soarpenguin/redis-trib
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathadd-node.go
130 lines (115 loc) · 3.73 KB
/
add-node.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package main
import (
"errors"
"fmt"
"github.com/Sirupsen/logrus"
"github.com/codegangsta/cli"
)
// add-node new_host:new_port existing_host:existing_port
// --slave
// --master-id <arg>
var addNodeCommand = cli.Command{
Name: "add-node",
Aliases: []string{"add"},
Usage: "add a new redis node to existed cluster.",
Description: `The add-node command add a node to redis cluster.`,
ArgsUsage: `new_host:new_port existing_host:existing_port`,
Flags: []cli.Flag{
cli.BoolFlag{
Name: "slave",
Usage: `Slave flag for node join a existed cluster.
$ redis-trib add-node <--slave> new_host:new_port existing_host:existing_port`,
},
cli.StringFlag{
Name: "master-id",
Value: "",
Usage: `Master id for slave node to meet.
$ redis-trib add-node <--slave --master-id arg> new_host:new_port existing_host:existing_port`,
},
cli.StringFlag{
Name: "password, a",
Value: "",
Usage: `password, the default value is "".`,
},
},
Action: func(context *cli.Context) error {
if context.NArg() < 2 {
fmt.Printf("Incorrect Usage.\n\n")
cli.ShowCommandHelp(context, "add-node")
logrus.Fatalf("Must provide \"new_host:new_port existing_host:existing_port\" for add-node command!")
}
if context.String("password") != "" {
RedisPassword = context.String("password")
}
rt := NewRedisTrib()
if err := rt.AddNodeClusterCmd(context); err != nil {
return err
}
return nil
},
}
func (rt *RedisTrib) AddNodeClusterCmd(context *cli.Context) error {
var newaddr string
var addr string
var masterID string
var master *ClusterNode
if newaddr = context.Args().Get(0); newaddr == "" {
return errors.New("please check new_host:new_port for add-node command")
} else if addr = context.Args().Get(1); addr == "" {
return errors.New("please check existing_host:existing_port for add-node command")
}
logrus.Printf(">>> Adding node %s to cluster %s", newaddr, addr)
// Check the existing cluster
// Load cluster information
if err := rt.LoadClusterInfoFromNode(addr); err != nil {
return err
}
rt.CheckCluster(false)
// If --master-id was specified, try to resolve it now so that we
// abort before starting with the node configuration.
if context.Bool("slave") {
masterID = context.String("master-id")
if masterID != "" {
master = rt.GetNodeByName(masterID)
if master == nil {
logrus.Errorf("No such master ID %s", masterID)
}
} else {
master = rt.GetMasterWithLeastReplicas()
if master == nil {
logrus.Errorf("Can't selected a master node!")
} else {
logrus.Printf("Automatically selected master %s", master.String())
}
}
}
// Add the new node
newNode := NewClusterNode(newaddr)
newNode.Connect(true)
if !newNode.AssertCluster() { // quit if not in cluster mode
logrus.Fatalf("Node %s is not configured as a cluster node.", newNode.String())
}
if err := newNode.LoadInfo(false); err != nil {
logrus.Fatalf("Load new node %s info failed: %s!", newaddr, err.Error())
}
newNode.AssertEmpty()
rt.AddNode(newNode)
// Send CLUSTER FORGET to all the nodes but the node to remove
logrus.Printf(">>> Send CLUSTER MEET to node %s to make it join the cluster", newNode.String())
if _, err := newNode.ClusterAddNode(addr); err != nil {
logrus.Fatalf("Add new node %s failed: %s!", newaddr, err.Error())
}
// Additional configuration is needed if the node is added as
// a slave.
if context.Bool("slave") {
rt.WaitClusterJoin()
if master != nil {
logrus.Printf(">>> Configure node as replica of %s.", master.String())
newNode.ClusterReplicateWithNodeID(master.Name())
} else {
logrus.Fatalf("Master node is nil, can't get master info.")
}
}
logrus.Printf("[OK] New node added correctly.")
return nil
}