Raise error if no members of replica set’s host list are reachable, PYTHON-608.
This commit is contained in:
parent
29ab100814
commit
ac0369dde8
@ -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:
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user