Raise error if no members of replica set’s host list are reachable, PYTHON-608.

This commit is contained in:
A. Jesse Jiryu Davis 2013-12-11 21:35:59 -05:00
parent 29ab100814
commit ac0369dde8
4 changed files with 52 additions and 11 deletions

View File

@ -1168,6 +1168,15 @@ class MongoReplicaSetClient(common.BaseObject):
if res['ismaster']:
writer = host
if not members:
# In the first loop, we connected to a member in the seed list
# and got a host list, but couldn't reach any members in that
# list.
raise AutoReconnect(
"Couldn't reach any hosts in %s. Replica set is"
" configured with internal hostnames or IPs?"
% list(hosts))
if writer == rs_state.writer:
threadlocal = self.__rs_state.threadlocal
else:

View File

@ -57,7 +57,7 @@ class MockPool(Pool):
class MockClientBase(object):
def __init__(self, standalones, members, mongoses):
def __init__(self, standalones, members, mongoses, config):
"""standalones, etc., are like ['a:1', 'b:2']"""
self.mock_standalones = standalones[:]
self.mock_members = members[:]
@ -67,7 +67,11 @@ class MockClientBase(object):
else:
self.mock_primary = None
self.mock_conf = members[:]
if config is not None:
self.mock_ismaster_hosts = config
else:
self.mock_ismaster_hosts = members[:]
self.mock_mongoses = mongoses[:]
# Hosts that should raise socket errors.
@ -97,7 +101,7 @@ class MockClientBase(object):
'ismaster': ismaster,
'secondary': not ismaster,
'setName': 'rs',
'hosts': self.mock_conf}
'hosts': self.mock_ismaster_hosts}
if self.mock_primary:
response['primary'] = self.mock_primary
@ -107,7 +111,9 @@ class MockClientBase(object):
if host in self.mock_mongoses:
return {'ismaster': True, 'msg': 'isdbgrid'}
raise AssertionError('Unknown host: %s' % host)
# In test_internal_ips(), we try to connect to a host listed
# in ismaster['hosts'] but not publicly accessible.
raise socket.error('Unknown host: %s' % host)
def simple_command(self, sock_info, dbname, spec):
# __simple_command is also used for authentication, but in this
@ -121,8 +127,13 @@ class MockClientBase(object):
class MockClient(MockClientBase, MongoClient):
def __init__(self, standalones, members, mongoses, *args, **kwargs):
MockClientBase.__init__(self, standalones, members, mongoses)
def __init__(
self, standalones, members, mongoses, ismaster_hosts=None,
*args, **kwargs
):
MockClientBase.__init__(
self, standalones, members, mongoses, ismaster_hosts)
kwargs['_pool_class'] = my_partial(MockPool, self)
MongoClient.__init__(self, *args, **kwargs)
@ -131,8 +142,13 @@ class MockClient(MockClientBase, MongoClient):
class MockReplicaSetClient(MockClientBase, MongoReplicaSetClient):
def __init__(self, standalones, members, mongoses, *args, **kwargs):
MockClientBase.__init__(self, standalones, members, mongoses)
def __init__(
self, standalones, members, mongoses, ismaster_hosts=None,
*args, **kwargs
):
MockClientBase.__init__(
self, standalones, members, mongoses, ismaster_hosts)
kwargs['_pool_class'] = my_partial(MockPool, self)
MongoReplicaSetClient.__init__(self, *args, **kwargs)

View File

@ -46,6 +46,7 @@ from pymongo.errors import (AutoReconnect,
InvalidName,
OperationFailure, InvalidOperation)
from test import version, port, pair
from test.pymongo_mocks import MockReplicaSetClient
from test.utils import (
delay, assertReadFrom, assertReadFromAll, read_from_which_host,
remove_all_users, assertRaisesExactly, TestRequestMixin, one,
@ -1166,5 +1167,20 @@ class TestReplicaSetClientLazyConnectBadSeeds(
return MongoReplicaSetClient(seeds, replicaSet=self.name, **kwargs)
class TestReplicaSetClientInternalIPs(unittest.TestCase):
def test_connect_with_internal_ips(self):
# Client is passed an IP it can reach, 'a:1', but the RS config
# only contains unreachable IPs like 'internal-ip'. PYTHON-608.
assertRaisesExactly(
ConnectionFailure,
MockReplicaSetClient,
standalones=[],
members=['a:1'],
mongoses=[],
ismaster_hosts=['internal-ip:27017'],
host='a:1',
replicaSet='rs')
if __name__ == "__main__":
unittest.main()

View File

@ -96,7 +96,7 @@ class TestSecondaryRemoved(unittest.TestCase):
self.assertTrue(('c', 3) in c.secondaries)
# C is removed.
c.mock_conf.remove('c:3')
c.mock_ismaster_hosts.remove('c:3')
c.refresh()
self.assertEqual(('a', 1), c.primary)
@ -139,7 +139,7 @@ class TestSecondaryAdded(unittest.TestCase):
# C is added.
c.mock_members.append('c:3')
c.mock_conf.append('c:3')
c.mock_ismaster_hosts.append('c:3')
c.disconnect()
c.db.collection.find_one()
@ -161,7 +161,7 @@ class TestSecondaryAdded(unittest.TestCase):
# C is added.
c.mock_members.append('c:3')
c.mock_conf.append('c:3')
c.mock_ismaster_hosts.append('c:3')
c.refresh()
self.assertEqual(('a', 1), c.primary)