2
2
import threading
3
3
import uuid
4
4
import os
5
+ import time
5
6
6
7
import six
7
8
import pexpect
@@ -39,7 +40,7 @@ def make_dict_key(self, host, port):
39
40
def make_control_master (self , remote_host , remote_port , num_masters = 1 ,
40
41
ssh_username = None , ssh_password = None , private_key = None , pass_phrase = None ,
41
42
jump_host = None , jump_port = None , login_timeout = 60 , reconnect = False ,
42
- with_lock = True , sock_dir = None ):
43
+ with_lock = True , sock_dir = None , connection_lifetime = None ):
43
44
dict_key = self .make_dict_key (remote_host , remote_port )
44
45
if with_lock :
45
46
self .lock .acquire ()
@@ -56,7 +57,8 @@ def make_control_master(self, remote_host, remote_port, num_masters=1,
56
57
'jump_host' : jump_host ,
57
58
'jump_port' : jump_port ,
58
59
'login_timeout' : login_timeout ,
59
- 'sock_dir' : sock_dir
60
+ 'sock_dir' : sock_dir ,
61
+ 'connection_lifetime' : connection_lifetime ,
60
62
}
61
63
else :
62
64
num_masters = self .params [dict_key ]['num_masters' ]
@@ -68,6 +70,7 @@ def make_control_master(self, remote_host, remote_port, num_masters=1,
68
70
jump_port = self .params [dict_key ]['jump_port' ]
69
71
login_timeout = self .params [dict_key ]['login_timeout' ]
70
72
sock_dir = self .params [dict_key ]['sock_dir' ]
73
+ connection_lifetime = self .params [dict_key ]['connection_lifetime' ]
71
74
# make a master
72
75
for i in range (num_masters - len (self .pool [dict_key ])):
73
76
# make a socket file
@@ -94,6 +97,7 @@ def make_control_master(self, remote_host, remote_port, num_masters=1,
94
97
loginString ,
95
98
]
96
99
c = pexpect_spawn (com , echo = False )
100
+ baseLogger .debug ('pexpect_spawn' )
97
101
c .logfile_read = baseLogger .handlers [0 ].stream
98
102
isOK = False
99
103
for iTry in range (3 ):
@@ -132,27 +136,35 @@ def make_control_master(self, remote_host, remote_port, num_masters=1,
132
136
# exec to confirm login
133
137
c .sendline ('echo {0}' .format (loginString ))
134
138
if isOK :
135
- self .pool [dict_key ].append ((sock_file , c ))
139
+ conn_exp_time = (time .time () + connection_lifetime ) if connection_lifetime is not None else None
140
+ self .pool [dict_key ].append ((sock_file , c , conn_exp_time ))
136
141
if with_lock :
137
142
self .lock .release ()
138
143
139
144
# get a connection
140
145
def get_connection (self , remote_host , remote_port , exec_string ):
146
+ baseLogger .debug ('get_connection start' )
141
147
dict_key = self .make_dict_key (remote_host , remote_port )
142
148
self .lock .acquire ()
143
149
active_masters = []
144
150
someClosed = False
145
- for sock_file , child in self .pool [dict_key ]:
146
- if child .isalive ():
147
- active_masters .append ((sock_file , child ))
151
+ for sock_file , child , conn_exp_time in list ( self .pool [dict_key ]) :
152
+ if child .isalive () and time . time () <= conn_exp_time :
153
+ active_masters .append ((sock_file , child , conn_exp_time ))
148
154
else :
149
155
child .close ()
156
+ self .pool [dict_key ].remove ((sock_file , child , conn_exp_time ))
150
157
someClosed = True
158
+ if child .isalive ():
159
+ baseLogger .debug ('a connection process is dead' )
160
+ else :
161
+ baseLogger .debug ('a connection is expired' )
151
162
if someClosed :
152
163
self .make_control_master (remote_host , remote_port , reconnect = True , with_lock = False )
153
164
active_masters = [item for item in self .pool [dict_key ] if os .path .exists (item [0 ])]
165
+ baseLogger .debug ('reconnected; now {0} active connections' .format (len (active_masters )))
154
166
if len (active_masters ) > 0 :
155
- sock_file , child = random .choice (active_masters )
167
+ sock_file , child , conn_exp_time = random .choice (active_masters )
156
168
con = subprocess .Popen (['ssh' , 'dummy' , '-S' , sock_file , exec_string ],
157
169
shell = False ,
158
170
stdin = subprocess .PIPE ,
0 commit comments