Setup: paramiko 1.15.1
According to the documentation a timeout was created for exec_command since 1.10.0 but for some reason it's not working for me. Do I have an error in my code that I've missed or is it in fact a bug?
I have this code
class CustomSSH(object):
def __init__(self, node):
self.node = node
self.ssh = paramiko.SSHClient()
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
self.privkey = paramiko.RSAKey.from_private_key_file('./secret.key')
except:
self.use_password = True
def connect_ssh(self, timeout=60):
try:
if self.use_password:
self.ssh.connect(self.node,
timeout=60,
username='xxx',
password='xxx',
look_for_keys=False)
else:
"""Using SSH Key"""
self.ssh.connect(self.node,
timeout=60,
username='xxx',
pkey=self.privkey,
look_for_keys=False)
self.using_ssh = True
return True
except paramiko.AuthenticationException, e:
if self.use_password:
raise paramiko.SSHException
print "Private key {}".format(e)
print "Trying using username/password instead"
self.use_password = True
self.connect_ssh()
except paramiko.SSHException, e:
print "some other error ", e
self.close()
raise
except Exception:
print "exception"
raise
def close(self):
print "Closing connection"
try:
self.ssh.close()
except:
print "Error closing connection"
def send_cmd(self, command, regexmatch='', timeout=60):
"""Issue Commands using SSH
returns a Tuple of (True/False, results)"""
try:
stdin, stdout, stderr = self.ssh.exec_command(command, timeout)
xresults = stdout.readlines()
results = ''.join(xresults)
re_status = re.compile(regexmatch, re.IGNORECASE)
if re_status.search(results):
return (True, xresults)
else:
return (False, xresults)
except Exception as e:
raise KeyError, e
That I'm executing as follows:
ssh = CustomSSH(node)
ssh.connect_ssh()
ssh.send_cmd(abort_cmd)
What is wrong here?
It was of course a simple typo.
When calling exec_command I sent the value of timeout instead of timeout=value.
self.ssh.exec_command(command, timeout)
should have been
self.ssh.exec_command(command, timeout=60)
Related
This my code
def timeout(seconds_before_timeout):
def deco(func):
#functools.wraps(func)
def wrapper(*args, **kwargs):
res = [
Exception("function [%s] timeout [%s seconds] exceeded!"
% (func.__name__, seconds_before_timeout))
]
def new_func():
try:
res[0] = func(*args, **kwargs)
except Exception as ex:
res[0] = ex
thread = Thread(target=new_func)
thread.daemon = True
try:
thread.start()
thread.join(seconds_before_timeout)
except Exception as ex:
print("error starting thread")
raise ex
ret = res[0]
if isinstance(ret, BaseException):
raise ret
return ret
return wrapper
return deco
And timeout function i used for:
#timeout(2)
def listen_for_a_new_campaign(self):
"""
Start listening for new campaign in list_campaign queue
"""
while True:
try:
for method_frame, properties, body \
in self.obj_requester_channel.consume(LIST_CAMPAIGN_QUEUE):
body_dict = literal_eval(body.decode("utf-8"))
message_number = body_dict["Msg_Count"]
n_message = min(message_number, BATCH_SIZE)
identify(n_message)
a_request = {
"campaign_request": body_dict,
"campaign_ack" : method_frame.delivery_tag,
"n_message" : n_message
}
identify(a_request)
return a_request
# Acknowledge the message
n_requeued_messages = self.obj_requester_channel.cancel()
print("Requeued %i messages" % n_requeued_messages)
break
except pika.exceptions.ConnectionWrongStateError:
print("Create connection ...")
self.create_connection()
continue
except pika.exceptions.ChannelWrongStateError:
print("Create connection ...")
self.create_connection()
self.obj_requester_channel = self.obj_connection.channel()
self.obj_requester_channel.queue_declare(queue=LIST_CAMPAIGN_QUEUE)
self.obj_campaign_channel = self.obj_connection.channel()
continue
When I run my program, I checked all process by htop and below is result, all thread is alive:
I don't know what's wrong with that.
I run this code on my laptop everything was OK, but when I deploy them to EC2 instance I found that problems.
Help me!!
I'm having trouble with this error:
Exception in thread StompReceiverThread-1 (most likely raised during
interpreter shutdown):
That is no traceback at all.. just that.
Usualy everything works fine but rarely it happens and then the action does not conclude.
Any tips?
My code:
class Listener(stomp.ConnectionListener):
def __init__(self, conn, request):
self.conn = conn
self.request = request
def on_error(self, headers, message):
global WAITING_RESPONSE
print('received an error: ' + message)
WAITING_RESPONSE = False
def on_message(self, headers, message):
global WAITING_RESPONSE
try:
msg = json.loads(message)
if str(msg.get('transaction_id','')) == str(CURRENT_ID):
printDebugLine('Queue response:'+str(message))
manageQueueResponse(message,self.request)
WAITING_RESPONSE = False
self.conn.ack(headers['message-id'], '11')
except stomp.exception.ConnectFailedException:
print('Stomp error on message')
sys.exit(3)
except Exception as e:
print('ERROR: %s' % str(e))
sys.exit(3)
class Queue(object):
def __init__(self):
self.host = xx
self.port = xx
self.login = xx
self.passwd = xx
self.request = {}
self.start()
def start(self):
try:
self.conn = stomp.Connection(host_and_ports=[(self.host, self.port)])
self.conn.start()
self.conn.connect(self.login, self.passwd, wait=True)
self.conn.set_listener('xx', Listener(self.conn, self.request))
self.conn.subscribe(destination='xx', id='xx', ack='xx')
except stomp.exception.ConnectFailedException:
print('ERROR: unable to connect')
sys.exit(3)
except Exception as e:
print('ERROR: %s' % str(e))
sys.exit(3)
def send(self, data):
global CURRENT_ID
while WAITING_RESPONSE:
time.time(0.1)
try:
CURRENT_ID = str(uuid.uuid4())
data.update({'transaction_id': CURRENT_ID})
b = json.dumps(data)
self.request.update(data)
printDebugLine('Queue request:'+str(data))
self.conn.send(body=b, destination='xx')
timeout(data,self.request,29)
except stomp.exception.ConnectFailedException:
print('ERROR: unable to connect')
except Exception as e:
print('ERROR: %s' % str(e))
It looks like your main program is exiting, the interpreter is cleaning up things, but the stomp receiver thread was not shutdown first. The receiver thread goes to do something but basic modules are no longer available, so it gives an exception message, but cannot print a Traceback because that fuctionality is no longer available due to the program exiting.
Look at why the main program would be exiting.
im trying to check multiple imap login informations asynchronously with aioimaplib.
This code works as long as the imap servers are reachable and / or the clients don't time out.
What is the correct way to catch the exceptions?
Example exception:
ERROR:asyncio:Task exception was never retrieved future: <Task finished coro=<BaseEventLoop.create_connection() done, defined at G:\WinPython-3.5.4\python-3.5.4.amd64\lib\asyncio\base_events.py:679> exception=TimeoutError(10060, "Connect call failed ('74.117.114.100', 993)")>
Code:
account_infos = [
# User Password Server
('user1#web.com', 'password1', 'imap.google.com'),
('user2#web.com', 'password2', 'imap.yandex.com'),
('user3#web.com', 'password3', 'imap.server3.com'),
]
class MailLogin:
def __init__(self):
self.loop = asyncio.get_event_loop()
self.queue = asyncio.Queue(loop=self.loop)
self.max_workers = 2
async def produce_work(self):
for i in account_infos:
await self.queue.put(i)
for _ in range(max_workers):
await self.queue.put((None, None, None))
async def worker(self):
while True:
(username, password, server) = await self.queue.get()
if username is None:
break
while True:
try:
s = IMAP4_SSL(server)
await s.wait_hello_from_server()
r = await s.login(username, password)
await s.logout()
if r.result != 'NO':
print('Information works')
except Exception as e:
# DOES NOT CATCH
print(str(e))
else:
break
def start(self):
try:
self.loop.run_until_complete(
asyncio.gather(self.produce_work(), *[self.worker() for _ in range(self.max_workers)],
loop=self.loop, return_exceptions=True)
)
finally:
print('Done')
if __name__ == '__main__':
MailLogin().start()
There are several ways to do this but the TimeoutError is probably caught in your except. You don't see it because str(e) is an empty string.
You can see the stacks enabling debug mode of asyncio.
First, you can catch the exception as you did:
async def fail_fun():
try:
imap_client = aioimaplib.IMAP4_SSL(host='foo', timeout=1)
await imap_client.wait_hello_from_server()
except Exception as e:
print('Exception : ' + str(e))
if __name__ == '__main__':
get_event_loop().run_until_complete(fail_fun())
Second, you can catch the exception at run_until_complete
async def fail_fun():
imap_client = aioimaplib.IMAP4_SSL(host='foo', timeout=1)
await imap_client.wait_hello_from_server()
if __name__ == '__main__':
try:
get_event_loop().run_until_complete(fail_fun())
except Exception as e:
print('Exception : ' + str(e))
The connection is established wrapping the loop.create_connection coroutine with create_task : we wanted to establish the connection in the IMAP4 constructor and __init__ should return None.
So if your host has a wrong value, you could test it before, or wait for the timeout :
socket.gaierror: [Errno -5] No address associated with hostname
if a host is not responding before the timeout, you can raise the timeout. And if the connection is lost during the connection, you can add a connection lost callback in the IMAP4 constructor.
If I run the _create_system_cobbler function by itself in a standalone script, I'm able to capture the error. In this case, I am simulating an error and it's going to tell me that the dns name I'm using already exist. However, if I put it into a function and make the call from my main function, it always return True. I
Error:
Error! <class 'cobbler.cexceptions.CX'>:'dns-name duplicated: inadmin001.domain.local'
_create_system_cobbler function
def _create_system_cobbler():
try:
cobbler_server = xmlrpclib.Server("https://127.0.0.1/cobbler_api")
except socket.error:
print "Can't Connect to Cobbler"
quit()
serverinfo = {
'hostname' : 'inadmin001',
'macaddress': '00:2e:4e:78:ba:86',
'ipaddress': '172.21.10.33',
'dnsname': 'inadmin001.domain.local'
}
try:
token = cobbler_server.login("cobbler","cobbler")
system_id = cobbler_server.new_system(token)
...
<more code>
...
except xmlrpclib.Fault as err:
errormsg = "Error " + str(err.faultString)
return False, errormsg
return True, serverinfo
Main Function
def main(session)
handler, serverinfo = _create_system_cobbler()
if handler:
print "Let's create a VM"
print serverinfo
# Let's continue with the rest of the code
else:
print serverinfo
quit()
Using return codes is not very pythonic, you should write the function assuming everything goes well and except exceptions outside:
def create_system_cobbler():
cobbler_server = xmlrpclib.Server("https://127.0.0.1/cobbler_api")
serverinfo = {
'hostname' : 'inadmin001',
'macaddress': '00:2e:4e:78:ba:86',
'ipaddress': '172.21.10.33',
'dnsname': 'inadmin001.domain.local'
}
token = cobbler_server.login("cobbler","cobbler")
system_id = cobbler_server.new_system(token)
...
<more code>
...
return cobbler_server
def main(session):
try:
handler = create_system_cobbler()
except socket.error:
print("Can't Connect to Cobbler")
except xmlrpclib.Fault as err:
print('Error: ', err)
I created the following class that I want to have a socket member within it and then want to use member functions to connect, close, send, and receive.
class Connection:
Kon = ""
SSLx = ""
def Close(self):
try:
self.Kon.close()
return True
except:
return False
def Send(self,Message):
try:
self.Kon.write(Message)
return True
except Exception,e:
print e
return False
def Recieve(self):
try:
Response = self.Kon.recv(10240)
return Response
except:
return False
#Conenct Function Makes a SSL connection with the node
def Connect(self,Link):
self.SSLx = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Ip = Link[0].replace("'",'')
print Ip
Port = int(Link[1])
try:
self.SSLx.connect((Ip,Port))
return True
except Exception,e:
print "Connection Attempt Failed"
self.Kon = socket.ssl(SSLx)
return False
I ran the .Connect function successfully, but after that when I try the Send function it says 'str' object does not have a write member.
Any ideas on how to get this done?
There seems to have been a small error from a debugging process I did, I had shifted one of the lines that initialized the Kon variable few lines below. The following is the corrected class.
class Connection:
Kon = ""
SSLx = ""
def Close(self):
try:
self.Kon.close()
return True
except:
return False
def Send(self,Message):
try:
self.Kon.write(Message)
return True
except Exception,e:
return False
def Recieve(self):
try:
Response = self.Kon.read(10240)
return Response
except Exception,e:
print e
return False
#Conenct Function Makes a SSL connection with the node
def Connect(self,Link):
self.SSLx = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Ip = Link[0].replace("'",'')
print Ip
Port = int(Link[1])
try:
self.SSLx.connect((Ip,Port))
self.Kon = socket.ssl(self.SSLx)
return True
except Exception,e:
print e
print "Connection Attempt Failed"
return False