summaryrefslogtreecommitdiff
path: root/jstests/multiVersion/libs/multi_rs.js
blob: 4e943f39531924816f42b8cd5fbc1bd51d3f11e1 (plain)
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
//
// Utility functions for multi-version replica sets
//

/**
 * @param options {Object} see ReplSetTest.start & MongoRunner.runMongod.
 * @param user {string} optional, user name for authentication.
 * @param pwd {string} optional, password for authentication. Must be set if user is set.
 */
ReplSetTest.prototype.upgradeSet = function(options, user, pwd) {
    options = options || {};

    var primary = this.getPrimary();

    // Upgrade secondaries first
    var nodesToUpgrade = this.getSecondaries();

    // Then upgrade primaries
    nodesToUpgrade.push(primary);

    // We can upgrade with no primary downtime if we have enough nodes
    var noDowntimePossible = this.nodes.length > 2;

    for (var i = 0; i < nodesToUpgrade.length; i++) {
        var node = nodesToUpgrade[ i ];
        if (node == primary) {
            node = this.stepdown(node);
            primary = this.getPrimary();
        }

        var prevPrimaryId = this.getNodeId(primary);
        //merge new options into node settings...
        for (var nodeName in this.nodeOptions) {
            this.nodeOptions[nodeName] = Object.merge(this.nodeOptions[nodeName], options);
        }

        this.upgradeNode(node, options, user, pwd);

        if (noDowntimePossible)
            assert.eq(this.getNodeId(primary), prevPrimaryId);
    }
};

ReplSetTest.prototype.upgradeNode = function(node, opts, user, pwd) {
    if (user != undefined) {
        assert.eq(1, node.getDB("admin").auth(user, pwd));
    }

    var isMaster = node.getDB('admin').runCommand({ isMaster: 1 });

    if (!isMaster.arbiterOnly) {
        assert.commandWorked(node.adminCommand("replSetMaintenance"));
        this.waitForState(node, ReplSetTest.State.RECOVERING);
    }

    var newNode = this.restart(node, opts);
    if (user != undefined) {
        newNode.getDB("admin").auth(user, pwd);
    }

    var waitForStates = [ ReplSetTest.State.PRIMARY,
                          ReplSetTest.State.SECONDARY,
                          ReplSetTest.State.ARBITER ];
    this.waitForState(newNode, waitForStates);

    return newNode;
};

ReplSetTest.prototype.stepdown = function(nodeId) {
    nodeId = this.getNodeId(nodeId);
    assert.eq(this.getNodeId(this.getPrimary()), nodeId);
    var node = this.nodes[nodeId];

    try {
        node.getDB("admin").runCommand({ replSetStepDown: 50, force: true });
        assert(false);
    }
    catch (ex) {
        print('Caught exception after stepDown cmd: ' + tojson(ex));
    }

    return this.reconnect(node);
};

ReplSetTest.prototype.reconnect = function(node) {
    var nodeId = this.getNodeId(node);
    this.nodes[nodeId] = new Mongo(node.host);
    var except = {};
    for (var i in node) {
        if (typeof(node[i]) == "function") continue;
        this.nodes[nodeId][i] = node[i];
    }

    return this.nodes[nodeId];
};

ReplSetTest.prototype.conf = function () {
    var admin = this.getPrimary().getDB('admin');

    var resp = admin.runCommand({replSetGetConfig:1});

    if (resp.ok && !(resp.errmsg) && resp.config)
        return resp.config;

    else if (resp.errmsg && resp.errmsg.startsWith("no such cmd"))
        return admin.getSisterDB("local").system.replset.findOne();

    throw new Error("Could not retrieve replica set config: " + tojson(resp));
};