@@ -1220,30 +1220,7 @@ def __init__(self,
1220
1220
self .endpoint_factory = endpoint_factory or DefaultEndPointFactory (port = self .port )
1221
1221
self .endpoint_factory .configure (self )
1222
1222
1223
- raw_contact_points = []
1224
- for cp in [cp for cp in self .contact_points if not isinstance (cp , EndPoint )]:
1225
- raw_contact_points .append (cp if isinstance (cp , tuple ) else (cp , port ))
1226
-
1227
- self .endpoints_resolved = [cp for cp in self .contact_points if isinstance (cp , EndPoint )]
1228
- self ._endpoint_map_for_insights = {repr (ep ): '{ip}:{port}' .format (ip = ep .address , port = ep .port )
1229
- for ep in self .endpoints_resolved }
1230
-
1231
- strs_resolved_map = _resolve_contact_points_to_string_map (raw_contact_points )
1232
- self .endpoints_resolved .extend (list (chain (
1233
- * [
1234
- [DefaultEndPoint (ip , port ) for ip , port in xs if ip is not None ]
1235
- for xs in strs_resolved_map .values () if xs is not None
1236
- ]
1237
- )))
1238
-
1239
- self ._endpoint_map_for_insights .update (
1240
- {key : ['{ip}:{port}' .format (ip = ip , port = port ) for ip , port in value ]
1241
- for key , value in strs_resolved_map .items () if value is not None }
1242
- )
1243
-
1244
- if contact_points and (not self .endpoints_resolved ):
1245
- # only want to raise here if the user specified CPs but resolution failed
1246
- raise UnresolvableContactPoints (self ._endpoint_map_for_insights )
1223
+ self ._resolve_hostnames ()
1247
1224
1248
1225
self .compression = compression
1249
1226
@@ -1427,6 +1404,31 @@ def __init__(self,
1427
1404
if application_version is not None :
1428
1405
self .application_version = application_version
1429
1406
1407
+ def _resolve_hostnames (self ):
1408
+ raw_contact_points = []
1409
+ for cp in [cp for cp in self .contact_points if not isinstance (cp , EndPoint )]:
1410
+ raw_contact_points .append (cp if isinstance (cp , tuple ) else (cp , self .port ))
1411
+
1412
+ self .endpoints_resolved = [cp for cp in self .contact_points if isinstance (cp , EndPoint )]
1413
+ self ._endpoint_map_for_insights = {repr (ep ): '{ip}:{port}' .format (ip = ep .address , port = ep .port )
1414
+ for ep in self .endpoints_resolved }
1415
+ strs_resolved_map = _resolve_contact_points_to_string_map (raw_contact_points )
1416
+ self .endpoints_resolved .extend (list (chain (
1417
+ * [
1418
+ [DefaultEndPoint (ip , port ) for ip , port in xs if ip is not None ]
1419
+ for xs in strs_resolved_map .values () if xs is not None
1420
+ ]
1421
+ )))
1422
+
1423
+ self ._endpoint_map_for_insights .update (
1424
+ {key : ['{ip}:{port}' .format (ip = ip , port = port ) for ip , port in value ]
1425
+ for key , value in strs_resolved_map .items () if value is not None }
1426
+ )
1427
+
1428
+ if self .contact_points and (not self .endpoints_resolved ):
1429
+ # only want to raise here if the user specified CPs but resolution failed
1430
+ raise UnresolvableContactPoints (self ._endpoint_map_for_insights )
1431
+
1430
1432
def _create_thread_pool_executor (self , ** kwargs ):
1431
1433
"""
1432
1434
Create a ThreadPoolExecutor for the cluster. In most cases, the built-in
@@ -1720,6 +1722,20 @@ def protocol_downgrade(self, host_endpoint, previous_version):
1720
1722
"http://datastax.github.io/python-driver/api/cassandra/cluster.html#cassandra.cluster.Cluster.protocol_version" , self .protocol_version , new_version , host_endpoint )
1721
1723
self .protocol_version = new_version
1722
1724
1725
+ def _add_resolved_hosts (self ):
1726
+ for endpoint in self .endpoints_resolved :
1727
+ host , new = self .add_host (endpoint , signal = False )
1728
+ if new :
1729
+ host .set_up ()
1730
+ for listener in self .listeners :
1731
+ listener .on_add (host )
1732
+
1733
+ self .profile_manager .populate (
1734
+ weakref .proxy (self ), self .metadata .all_hosts ())
1735
+ self .load_balancing_policy .populate (
1736
+ weakref .proxy (self ), self .metadata .all_hosts ()
1737
+ )
1738
+
1723
1739
def connect (self , keyspace = None , wait_for_all_pools = False ):
1724
1740
"""
1725
1741
Creates and returns a new :class:`~.Session` object.
@@ -1740,18 +1756,8 @@ def connect(self, keyspace=None, wait_for_all_pools=False):
1740
1756
self .contact_points , self .protocol_version )
1741
1757
self .connection_class .initialize_reactor ()
1742
1758
_register_cluster_shutdown (self )
1743
- for endpoint in self .endpoints_resolved :
1744
- host , new = self .add_host (endpoint , signal = False )
1745
- if new :
1746
- host .set_up ()
1747
- for listener in self .listeners :
1748
- listener .on_add (host )
1749
-
1750
- self .profile_manager .populate (
1751
- weakref .proxy (self ), self .metadata .all_hosts ())
1752
- self .load_balancing_policy .populate (
1753
- weakref .proxy (self ), self .metadata .all_hosts ()
1754
- )
1759
+
1760
+ self ._add_resolved_hosts ()
1755
1761
1756
1762
try :
1757
1763
self .control_connection .connect ()
@@ -3585,16 +3591,8 @@ def _set_new_connection(self, conn):
3585
3591
if old :
3586
3592
log .debug ("[control connection] Closing old connection %r, replacing with %r" , old , conn )
3587
3593
old .close ()
3588
-
3589
- def _reconnect_internal (self ):
3590
- """
3591
- Tries to connect to each host in the query plan until one succeeds
3592
- or every attempt fails. If successful, a new Connection will be
3593
- returned. Otherwise, :exc:`NoHostAvailable` will be raised
3594
- with an "errors" arg that is a dict mapping host addresses
3595
- to the exception that was raised when an attempt was made to open
3596
- a connection to that host.
3597
- """
3594
+
3595
+ def _connect_host_in_lbp (self ):
3598
3596
errors = {}
3599
3597
lbp = (
3600
3598
self ._cluster .load_balancing_policy
@@ -3604,7 +3602,7 @@ def _reconnect_internal(self):
3604
3602
3605
3603
for host in lbp .make_query_plan ():
3606
3604
try :
3607
- return self ._try_connect (host )
3605
+ return ( self ._try_connect (host ), None )
3608
3606
except ConnectionException as exc :
3609
3607
errors [str (host .endpoint )] = exc
3610
3608
log .warning ("[control connection] Error connecting to %s:" , host , exc_info = True )
@@ -3614,7 +3612,31 @@ def _reconnect_internal(self):
3614
3612
log .warning ("[control connection] Error connecting to %s:" , host , exc_info = True )
3615
3613
if self ._is_shutdown :
3616
3614
raise DriverException ("[control connection] Reconnection in progress during shutdown" )
3615
+
3616
+ return (None , errors )
3617
3617
3618
+ def _reconnect_internal (self ):
3619
+ """
3620
+ Tries to connect to each host in the query plan until one succeeds
3621
+ or every attempt fails. If successful, a new Connection will be
3622
+ returned. Otherwise, :exc:`NoHostAvailable` will be raised
3623
+ with an "errors" arg that is a dict mapping host addresses
3624
+ to the exception that was raised when an attempt was made to open
3625
+ a connection to that host.
3626
+ """
3627
+ (conn , _ ) = self ._connect_host_in_lbp ()
3628
+ if conn is not None :
3629
+ return conn
3630
+
3631
+ # Try to re-resolve hostnames as a fallback when all hosts are unreachable
3632
+ self ._cluster ._resolve_hostnames ()
3633
+
3634
+ self ._cluster ._add_resolved_hosts ()
3635
+
3636
+ (conn , errors ) = self ._connect_host_in_lbp ()
3637
+ if conn is not None :
3638
+ return conn
3639
+
3618
3640
raise NoHostAvailable ("Unable to connect to any servers" , errors )
3619
3641
3620
3642
def _try_connect (self , host ):
0 commit comments