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
131
132
extern crate clap;
extern crate redis;

mod add;
mod cluster;
mod conn;
mod create;
mod util;

use add::Add;
use clap::{App, Arg, SubCommand};
use cluster::{Cluster, Node};
use create::Create;
use std::{thread, time};
pub fn run() {
    let matches = App::new("rckit")
        .about("redis cluster tool")
        .subcommand(
            SubCommand::with_name("create")
                .about("create rredis cluster")
                .arg(
                    Arg::with_name("node")
                        .help("cluster nodes")
                        .short("n")
                        .required(true)
                        .takes_value(true),
                )
                .arg(
                    Arg::with_name("replicate")
                        .short("s")
                        .default_value("1")
                        .help("slave replicate number "),
                )
                .arg(
                    Arg::with_name("master")
                        .short("m")
                        .default_value("0")
                        .takes_value(true)
                        .help("mster number"),
                ),
        )
        .subcommand(
            SubCommand::with_name("add")
                .about("Add  node to existing cluster")
                .arg(
                    Arg::with_name("cluster")
                        .required(true)
                        .short("c")
                        .help("-c clusterip:port, spec cluster ip and  port")
                        .takes_value(true),
                )
                .arg(
                    Arg::with_name("node")
                        .required(true)
                        .short("n")
                        .help(
                            "add new node  to cluster,
                        -n <master,slave> <master>",
                        )
                        .takes_value(true),
                ),
        )
        .subcommand(
            SubCommand::with_name("delete")
                .about(
                    "delete node from cluster
                if node is a master,it will migrate slots to other node and delete is's slave too",
                )
                .arg(
                    Arg::with_name("node")
                        .help("-n <node>")
                        .short("n")
                        .required(true)
                        .takes_value(true),
                ),
        )
        .get_matches();
    if let Some(sub_m) = matches.subcommand_matches("create") {
        let slave_count = clap::value_t!(sub_m.value_of("replicate"), usize).unwrap();
        let mut master_count = clap::value_t!(sub_m.value_of("master"), usize).unwrap();
        let node: Vec<&str> = sub_m.values_of("node").unwrap().collect();
        println!(
            "create cluster with replicate {} node{:?}",
            slave_count, &node
        );
        let mut create = Create::new(node, master_count, slave_count).unwrap();
        create.cluster.check().expect("check node err");
        create.init_slots();
        create.add_slots();
        create.set_config_epoch();
        create.join_cluster();
        while !create.consistent() {
            eprintln!("wait consistent fail");
            thread::sleep(time::Duration::from_secs(1));
        }
        create.set_slave().expect("set slave err");
    }
    if let Some(sub_m) = matches.subcommand_matches("add") {
        let cluster = sub_m
            .value_of("cluster")
            .expect("must spec existing cluster node");
        let nodes: Vec<&str> = sub_m
            .values_of("node")
            .expect("must spec at least one node be add to cluster")
            .collect();
        println!("add node {:?} to cluster {}", nodes, cluster);
        let mut add = Add::new(
            cluster.to_string(),
            nodes.iter().map(|x| x.to_string()).collect(),
        )
        .unwrap();
        add.cluster.check().expect("check cluste nodes fail");
        let _: () = add.add_node().expect("add node fail");
        while !add.cluster.consistency() {
            eprintln!("wait consistent fail");
            thread::sleep(time::Duration::from_secs(1));
        }
        add.set_slave();
    }
    if let Some(sub_m) = matches.subcommand_matches("delete") {
        let newnodes: Vec<&str> = sub_m
            .values_of("node")
            .expect("get node to deleted fail")
            .collect();
        let new_node = Node::new(newnodes[0].as_bytes()).expect("new node fail");
        let nodes = new_node.nodes();
        let cluster = Cluster::new(nodes);
        for node in newnodes {
            cluster.delete_node(cluster.node(node).expect("get node from cluster fail"));
        }
    }
}