6
6
import copy
7
7
import gzip
8
8
import json
9
- import logging
10
9
import platform
11
10
import sys
12
11
import time
@@ -276,9 +275,43 @@ def authenticate(self, account, user, password, master_token=None,
276
275
"body['data']: %s" ,
277
276
{k : v for (k , v ) in body [u'data' ].items () if k != u'PASSWORD' })
278
277
279
- ret = self ._post_request (
280
- url , headers , json .dumps (body ),
281
- timeout = self ._connection ._login_timeout )
278
+ try :
279
+ ret = self ._post_request (
280
+ url , headers , json .dumps (body ),
281
+ timeout = self ._connection ._login_timeout )
282
+ except ForbiddenError as err :
283
+ # HTTP 403
284
+ raise err .__class__ (
285
+ msg = (u"Failed to connect to DB. "
286
+ u"Verify the account name is correct: {host}:{port}, "
287
+ u"proxies={proxy_host}:{proxy_port}, "
288
+ u"proxy_user={proxy_user}. {message}" ).format (
289
+ host = self ._host ,
290
+ port = self ._port ,
291
+ proxy_host = self ._proxy_host ,
292
+ proxy_port = self ._proxy_port ,
293
+ proxy_user = self ._proxy_user ,
294
+ message = TO_UNICODE (err )
295
+ ),
296
+ errno = ER_FAILED_TO_CONNECT_TO_DB ,
297
+ sqlstate = SQLSTATE_CONNECTION_WAS_NOT_ESTABLISHED )
298
+ except (ServiceUnavailableError , BadGatewayError ) as err :
299
+ # HTTP 502/504
300
+ raise err .__class__ (
301
+ msg = (u"Failed to connect to DB. "
302
+ u"Service is unavailable: {host}:{port}, "
303
+ u"proxies={proxy_host}:{proxy_port}, "
304
+ u"proxy_user={proxy_user}. {message}" ).format (
305
+ host = self ._host ,
306
+ port = self ._port ,
307
+ proxy_host = self ._proxy_host ,
308
+ proxy_port = self ._proxy_port ,
309
+ proxy_user = self ._proxy_user ,
310
+ message = TO_UNICODE (err )
311
+ ),
312
+ errno = ER_FAILED_TO_CONNECT_TO_DB ,
313
+ sqlstate = SQLSTATE_CONNECTION_WAS_NOT_ESTABLISHED )
314
+
282
315
# this means we are waiting for MFA authentication
283
316
if ret [u'data' ].get (u'nextAction' ) and ret [u'data' ][
284
317
u'nextAction' ] == u'EXT_AUTHN_DUO_ALL' :
@@ -699,8 +732,7 @@ def request_thread(result_queue):
699
732
ProtocolError ,
700
733
OpenSSL .SSL .SysCallError , ValueError ) as err :
701
734
logger .exception ('who is hitting error?' )
702
- if logger .getEffectiveLevel () <= logging .DEBUG :
703
- logger .debug (err )
735
+ logger .debug (err )
704
736
if not isinstance (err , OpenSSL .SSL .SysCallError ) or \
705
737
err .args [0 ] in (
706
738
errno .ECONNRESET ,
@@ -714,12 +746,14 @@ def request_thread(result_queue):
714
746
except ConnectionError as err :
715
747
logger .exception (u'ConnectionError: %s' , err )
716
748
result_queue .put ((OperationalError (
749
+ # no full_url is required in the message
750
+ # as err includes all information
717
751
msg = u'Failed to connect: {0}' .format (err ),
718
752
errno = ER_FAILED_TO_SERVER ,
719
753
sqlstate = SQLSTATE_CONNECTION_WAS_NOT_ESTABLISHED
720
754
), False ))
721
755
except ValueError as err :
722
- logger .exception (u'Return value is not JSON: %s' , err )
756
+ logger .exception (u'Return value is NOT JSON: %s' , err )
723
757
result_queue .put ((InterfaceError (
724
758
msg = u"Failed to decode JSON output" ,
725
759
errno = ER_FAILED_TO_REQUEST ,
@@ -752,10 +786,19 @@ def request_thread(result_queue):
752
786
request_thread_timeout ,
753
787
request_timeout ,
754
788
retry_cnt + 1 )
789
+ start_request_thread = time .time ()
755
790
th .join (timeout = request_thread_timeout )
756
791
logger .debug ('request thread joined' )
792
+ if request_timeout is not None :
793
+ request_timeout -= min (
794
+ int (time .time () - start_request_thread ),
795
+ request_timeout )
796
+ start_get_queue = time .time ()
757
797
return_object , retryable = request_result_queue .get (
758
- timeout = int (request_thread_timeout / 2 ))
798
+ timeout = int (request_thread_timeout / 4 ))
799
+ if request_timeout is not None :
800
+ request_timeout -= min (
801
+ int (time .time () - start_get_queue ), request_timeout )
759
802
logger .debug ('request thread returned object' )
760
803
if retryable :
761
804
raise RequestRetry ()
@@ -797,7 +840,41 @@ def request_thread(result_queue):
797
840
time .sleep (sleeping_time )
798
841
retry_cnt += 1
799
842
800
- if isinstance (return_object , Error ):
843
+ if return_object is None :
844
+ if data :
845
+ try :
846
+ decoded_data = json .loads (data )
847
+ if decoded_data .get (
848
+ 'data' ) and decoded_data ['data' ].get ('PASSWORD' ):
849
+ # masking the password
850
+ decoded_data ['data' ]['PASSWORD' ] = '********'
851
+ data = json .dumps (decoded_data )
852
+ except :
853
+ logger .info ("data is not JSON" )
854
+ logger .error (
855
+ u'Failed to get the response. Hanging? '
856
+ u'method: {method}, url: {url}, headers:{headers}, '
857
+ u'data: {data}, proxies: {proxies}' .format (
858
+ method = method ,
859
+ url = full_url ,
860
+ headers = headers ,
861
+ data = data ,
862
+ proxies = proxies
863
+ )
864
+ )
865
+ Error .errorhandler_wrapper (
866
+ conn , None , OperationalError ,
867
+ {
868
+ u'msg' : u'Failed to get the response. Hanging? '
869
+ u'method: {method}, url: {url}, '
870
+ u'proxies: {proxies}' .format (
871
+ method = method ,
872
+ url = full_url ,
873
+ proxies = proxies
874
+ ),
875
+ u'errno' : ER_FAILED_TO_REQUEST ,
876
+ })
877
+ elif isinstance (return_object , Error ):
801
878
Error .errorhandler_wrapper (conn , None , return_object )
802
879
elif isinstance (return_object , Exception ):
803
880
Error .errorhandler_wrapper (
@@ -844,7 +921,7 @@ def authenticate_by_saml(self, authenticator, account, user, password):
844
921
Error .errorhandler_wrapper (
845
922
self ._connection , None , DatabaseError ,
846
923
{
847
- u'msg' : (u"failed to connect to DB: {host}:{port}, "
924
+ u'msg' : (u"Failed to connect to DB: {host}:{port}, "
848
925
u"proxies={proxy_host}:{proxy_port}, "
849
926
u"proxy_user={proxy_user}, "
850
927
u"{message}" ).format (
0 commit comments