Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-46089

Test downgrading a replica set with arbiters from 4.4

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 4.4.0-rc0, 4.7.0
    • Affects Version/s: 4.3.3
    • Component/s: Replication
    • None
    • Fully Compatible
    • ALL
    • v4.4
    • Hide
      /**
       * Test the downgrade of a replica set from latest version to last-stable version succeeds and
       * removes the "term" field of config document.
       */
      
      (function() {
      'use strict';
      
      load('jstests/multiVersion/libs/multi_rs.js');
      load('jstests/libs/test_background_ops.js');
      
      let newVersion = "latest";
      let oldVersion = "last-stable";
      
      let nodes = {
          n1: {binVersion: newVersion},
          n2: {binVersion: newVersion},
          n3: {binVersion: newVersion}
      };
      
      let rst = new ReplSetTest({nodes: nodes});
      let nodenames = rst.nodeList();
      rst.startSet();
      // rst.initiate();
      
      rst.initiate({
          "_id": "remove_config_term_on_replset_downgrade",
          "members": [
              {"_id": 0, "host": nodenames[0]},
              {"_id": 1, "host": nodenames[1]},
              {"_id": 2, "host": nodenames[2], arbiterOnly: true}
          ]
      });
      
      let primary = rst.getPrimary();
      
      // The default FCV is latestFCV for non-shard replica sets.
      let primaryAdminDB = rst.getPrimary().getDB("admin");
      checkFCV(primaryAdminDB, latestFCV);
      
      // Reconfig in FCV 4.4.
      let originalConfig = rst.getReplSetConfigFromNode();
      originalConfig.version++;
      reconfig(rst, originalConfig);
      rst.awaitNodesAgreeOnConfigVersion();
      
      // Check that the term field exists in the config document on all nodes.
      rst.nodes.forEach(function(node) {
          jsTestLog("Checking the config term on node " + tojson(node.host) + " before downgrade.");
          let config = node.getDB("local").getCollection("system.replset").findOne();
          assert(config.hasOwnProperty("term"));
      });
      
      // Remember the config from the primary before the downgrade.
      let configInNewVersion = rst.getReplSetConfigFromNode();
      
      jsTest.log("Downgrading FCV to 4.2");
      assert.commandWorked(primary.adminCommand({setFeatureCompatibilityVersion: lastStableFCV}));
      rst.awaitReplication();
      
      jsTest.log("Downgrading replica set..");
      rst.upgradeSet({binVersion: oldVersion});
      jsTest.log("Downgrade complete.");
      
      // Check that the term field doesn't exist in the config document on all nodes.
      rst.nodes.forEach(function(node) {
          reconnect(node);
          jsTestLog("Checking the config term on node " + tojson(node.host) + " after binary downgrade.");
          let config = node.getDB("local").getCollection("system.replset").findOne();
          assert(!config.hasOwnProperty("term"), tojson(config));
          config.term = configInNewVersion.term;
          assert.docEq(configInNewVersion, config);
      });
      rst.stopSet();
      })();
      
      Show
      /** * Test the downgrade of a replica set from latest version to last-stable version succeeds and * removes the "term" field of config document. */ ( function () { 'use strict' ; load( 'jstests/multiVersion/libs/multi_rs.js' ); load( 'jstests/libs/test_background_ops.js' ); let newVersion = "latest" ; let oldVersion = "last-stable" ; let nodes = { n1: {binVersion: newVersion}, n2: {binVersion: newVersion}, n3: {binVersion: newVersion} }; let rst = new ReplSetTest({nodes: nodes}); let nodenames = rst.nodeList(); rst.startSet(); // rst.initiate(); rst.initiate({ "_id" : "remove_config_term_on_replset_downgrade" , "members" : [ { "_id" : 0, "host" : nodenames[0]}, { "_id" : 1, "host" : nodenames[1]}, { "_id" : 2, "host" : nodenames[2], arbiterOnly: true } ] }); let primary = rst.getPrimary(); // The default FCV is latestFCV for non-shard replica sets. let primaryAdminDB = rst.getPrimary().getDB( "admin" ); checkFCV(primaryAdminDB, latestFCV); // Reconfig in FCV 4.4. let originalConfig = rst.getReplSetConfigFromNode(); originalConfig.version++; reconfig(rst, originalConfig); rst.awaitNodesAgreeOnConfigVersion(); // Check that the term field exists in the config document on all nodes. rst.nodes.forEach( function (node) { jsTestLog( "Checking the config term on node " + tojson(node.host) + " before downgrade." ); let config = node.getDB( "local" ).getCollection( "system.replset" ).findOne(); assert(config.hasOwnProperty( "term" )); }); // Remember the config from the primary before the downgrade. let configInNewVersion = rst.getReplSetConfigFromNode(); jsTest.log( "Downgrading FCV to 4.2" ); assert.commandWorked(primary.adminCommand({setFeatureCompatibilityVersion: lastStableFCV})); rst.awaitReplication(); jsTest.log( "Downgrading replica set.." ); rst.upgradeSet({binVersion: oldVersion}); jsTest.log( "Downgrade complete." ); // Check that the term field doesn't exist in the config document on all nodes. rst.nodes.forEach( function (node) { reconnect(node); jsTestLog( "Checking the config term on node " + tojson(node.host) + " after binary downgrade." ); let config = node.getDB( "local" ).getCollection( "system.replset" ).findOne(); assert(!config.hasOwnProperty( "term" ), tojson(config)); config.term = configInNewVersion.term; assert.docEq(configInNewVersion, config); }); rst.stopSet(); })();
    • Repl 2020-03-09, Repl 2020-03-23

      Current plan: on FCV downgrade, the primary executes a reconfig to remove the term field from the on-disk config document. The primary then blocks waiting for all nodes to replicate the new config via heartbeat. Arbiters have no special behavior in this scenario, just ensure we test this scenario in a replica set with one or more arbiters.

      Original title: "Arbiters don't remove configTerm on downgrade"

      Original description: Arbiters don't track FCV so they won't remove the configTerm from their on disk ReplSetConfig object on downgrade. This causes a 4.2 node to fail parsing of the config on restart after binary downgrade.

            Assignee:
            jesse@mongodb.com A. Jesse Jiryu Davis
            Reporter:
            william.schultz@mongodb.com Will Schultz
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: