summaryrefslogtreecommitdiff
path: root/jstests/sharding/shard_aware_init.js
blob: 199eb3695579dd5b0c8df341dca25821fa9347a5 (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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/**
 * Tests for shard aware initialization during process startup (for standalone) and transition
 * to primary (for replica set nodes).
 * Note: test will deliberately cause a mongod instance to terminate abruptly and mongod instance
 * without journaling will complain about unclean shutdown.
 * @tags: [requires_persistence, requires_journaling]
 */

(function() {
    "use strict";

    var waitForMaster = function(conn) {
        assert.soon(function() {
            var res = conn.getDB('admin').runCommand({isMaster: 1});
            return res.ismaster;
        });
    };

    /**
     * Runs a series of test on the mongod instance mongodConn is pointing to. Notes that the
     * test can restart the mongod instance several times so mongodConn can end up with a broken
     * connection after.
     */
    var runTest = function(mongodConn, configConnStr) {
        var shardIdentityDoc = {
            _id: 'shardIdentity',
            configsvrConnectionString: configConnStr,
            shardName: 'newShard',
            clusterId: ObjectId()
        };

        /**
         * Restarts the server without --shardsvr and replace the shardIdentity doc with a valid
         * document. Then, restarts the server again with --shardsvr. This also returns a
         * connection to the server after the last restart.
         */
        var restartAndFixShardIdentityDoc = function(startOptions) {
            var options = Object.extend({}, startOptions);
            delete options.shardsvr;
            mongodConn = MongoRunner.runMongod(options);
            waitForMaster(mongodConn);

            var res = mongodConn.getDB('admin')
                          .system.version.update({_id: 'shardIdentity'}, shardIdentityDoc);
            assert.eq(1, res.nModified);

            MongoRunner.stopMongod(mongodConn.port);

            newMongodOptions.shardsvr = '';
            mongodConn = MongoRunner.runMongod(newMongodOptions);
            waitForMaster(mongodConn);

            res = mongodConn.getDB('admin').runCommand({shardingState: 1});

            assert(res.enabled);
            assert.eq(shardIdentityDoc.configsvrConnectionString, res.configServer);
            assert.eq(shardIdentityDoc.shardName, res.shardName);
            assert.eq(shardIdentityDoc.clusterId, res.clusterId);

            return mongodConn;
        };

        assert.writeOK(mongodConn.getDB('admin')
                           .system.version.update({_id: 'shardIdentity'}, shardIdentityDoc, true));

        var res = mongodConn.getDB('admin').runCommand({shardingState: 1});

        assert(res.enabled);
        assert.eq(shardIdentityDoc.configsvrConnectionString, res.configServer);
        assert.eq(shardIdentityDoc.shardName, res.shardName);
        assert.eq(shardIdentityDoc.clusterId, res.clusterId);

        //
        // Test normal startup
        //

        var newMongodOptions = Object.extend(mongodConn.savedOptions, {restart: true});

        MongoRunner.stopMongod(mongodConn.port);
        mongodConn = MongoRunner.runMongod(newMongodOptions);
        waitForMaster(mongodConn);

        res = mongodConn.getDB('admin').runCommand({shardingState: 1});

        assert(res.enabled);
        assert.eq(shardIdentityDoc.configsvrConnectionString, res.configServer);
        assert.eq(shardIdentityDoc.shardName, res.shardName);
        assert.eq(shardIdentityDoc.clusterId, res.clusterId);

        //
        // Test shardIdentity doc without configsvrConnectionString, resulting into parse error
        //

        // Note: modification of the shardIdentity is allowed only when not running with --shardsvr
        MongoRunner.stopMongod(mongodConn.port);
        delete newMongodOptions.shardsvr;
        mongodConn = MongoRunner.runMongod(newMongodOptions);
        waitForMaster(mongodConn);

        assert.writeOK(mongodConn.getDB('admin').system.version.update(
            {_id: 'shardIdentity'},
            {_id: 'shardIdentity', shardName: 'x', clusterId: ObjectId()}));

        MongoRunner.stopMongod(mongodConn.port);

        newMongodOptions.shardsvr = '';
        assert.throws(function() {
            mongodConn = MongoRunner.runMongod(newMongodOptions);
            waitForMaster(mongodConn);
        });

        //
        // Test that it is possible to fix the invalid shardIdentity doc by not passing --shardsvr
        //

        try {
            // The server was terminated not by calling stopMongod earlier, this will cleanup
            // the process from registry in shell_utils_launcher.
            MongoRunner.stopMongod(newMongodOptions.port);
        } catch (ex) {
            if (!(ex instanceof (MongoRunner.StopError))) {
                throw ex;
            }
        }

        mongodConn = restartAndFixShardIdentityDoc(newMongodOptions);
        res = mongodConn.getDB('admin').runCommand({shardingState: 1});
        assert(res.enabled);
    };

    var st = new ShardingTest({shards: 1});

    var mongod = MongoRunner.runMongod({shardsvr: ''});

    runTest(mongod, st.configRS.getURL());

    MongoRunner.stopMongod(mongod.port);

    var replTest = new ReplSetTest({nodes: 1});
    replTest.startSet({shardsvr: ''});
    replTest.initiate();

    runTest(replTest.getPrimary(), st.configRS.getURL());

    replTest.stopSet();

    st.stop();

})();