13

I've got a MongoDB instance, set up using a config file and a key file.

I'd like to initiate a replica set using pymongo. When I attempt to initiate the replcia set, by executing a python script against the server which will become the replica set primary, as such:

from pymongo import MongoClient

uri = "mongodb://correctWorkingUsername:password@localhost:27017"
c = MongoClient(uri)

config = {'_id': 'RelicaSetName', 'members': [
{'_id': 0, 'host': 'FirstServer:27017'},
{'_id': 1, 'host': 'SecondServer:27017'},
{'_id': 2, 'host': 'ThirdServer:27017'}]}

c.admin.command("replSetInitiate", config)

I get an error message, the following:

'SecondSErver:27017' has data already, cannot initiate set

However, if I authenticate to the database using

mongo admin -u correctWorkingUsername -p password

I can initiate the replication, and successfully add members:

rs.initiate()
rs.add('SecondServer:27017')

I was unsure if this was related to the keyfile authentication, or the fact that the users were ALREADY created on the other servers by a script. Each server has also been started with a config file, mongod.conf, which contains a replica set name.

Why is this failing? The rs.initiate() and rs.add() work perfectly, but the python script does not work though it can infact connect to the database.

Mr.Budris
  • 552
  • 5
  • 21
  • 1
    Given I can't find a 'solution' to this specific problem, I've decided to use a shell script to execute the mongodb replica initiation directly. Basically I'm using a shell script to follow through the steps on their walk through. https://api.mongodb.com/python/current/examples/high_availability.html – Mr.Budris Dec 22 '16 at 16:32
  • 1
    Are you running this same python script against all of the members of the replica set? If that's the case then that is your problem. – helmy Apr 25 '17 at 23:39
  • @helmy no, I ran the script only against the RS primary. Edited the question for clarity. – Mr.Budris Apr 26 '17 at 14:23
  • How can you have a script create users on the servers already? If you start up a node with replSet option, you cannot write to them as you'll get a not master error. Also you say you try this "against the replica set primary" - but there is no primary until you initialize the replica set successfully. You should be starting up replica nodes with keyfile, initializing replica set and then creating users in the primary which will replicate. – Asya Kamsky Apr 27 '17 at 20:33
  • @AsyaKamsky when I said 'against the primary' I'm just using a convention -- it's not the primary yet, it is the node which will start out as the primary. Edited for clarity. – Mr.Budris Apr 28 '17 at 18:18

1 Answers1

4

When you initialize the full replica set at once, every node should not have data.

When you turn an existing single node into a replica set, its data becomes the replica set data, and then adding additional nodes will replicate data to them wiping out their existing data.

What you should be doing is starting up the nodes, initializing the replica set and then creating users (only on the primary).

the users were ALREADY created on the other servers by a script

This is the issue at the core - the only way this could have been done on an uninitialized member of a replica set is if it was first brought up as non-replica set node, users were added and then it was restarted with the replSet option. That's not the correct sequence to follow. For correct list of steps check the docs.

Asya Kamsky
  • 41,784
  • 5
  • 109
  • 133
  • Interesting, I was getting the same behavior after an untouched installation of mongo 3.4 from the official repo on Amazon Linux. I guess they might add a default user or something. I solved the problem by deleting everything in `/var/lib/mongo/`, but it seemed like that shouldn't be necessary. – Jesse Crossen Apr 27 '17 at 21:18
  • I just tried this with python and it all worked as I would have expected, but I started with clean instance. I'm guessing you're using some installation/deployment scripts that try to be helpful. If you want to still do this with Python you can initiate the first node and then add the other ones through Python commands, same as through mongo shell. – Asya Kamsky Apr 27 '17 at 21:28
  • @AsyaKamsky Any thoughts as to why this order of operations (creating the user on the primary node before initiating the replica set) works for us every time when using the mongo shell, but fails with this script? We experience no issues at all initiating the RS from the shell, only when using the python script. – Mr.Budris Apr 28 '17 at 18:15
  • the operations you are doing in the shell are different than what you are doing in your python script. rs.initiate with all three servers is different sequence than rs.initiate with one followed by rs.add for the other servers. If you compare the same commands in shell and python script they will absolutely give you the same results. – Asya Kamsky May 15 '17 at 15:08