@ -20,7 +20,7 @@ import os
import re
import re
import socket
import socket
import time
import time
import signal
try :
try :
import paramiko
import paramiko
@ -58,7 +58,7 @@ class ShellError(Exception):
class Shell ( object ) :
class Shell ( object ) :
def __init__ ( self , prompts_re = None , errors_re = None , kickstart = True ):
def __init__ ( self , prompts_re = None , errors_re = None , kickstart = True , timeout = 10 ):
self . ssh = None
self . ssh = None
self . shell = None
self . shell = None
@ -68,7 +68,12 @@ class Shell(object):
self . prompts = prompts_re or list ( )
self . prompts = prompts_re or list ( )
self . errors = errors_re or list ( )
self . errors = errors_re or list ( )
def open ( self , host , port = 22 , username = None , password = None , timeout = 10 ,
self . _timeout = timeout
self . _history = list ( )
signal . signal ( signal . SIGALRM , self . alarm_handler )
def open ( self , host , port = 22 , username = None , password = None ,
key_filename = None , pkey = None , look_for_keys = None ,
key_filename = None , pkey = None , look_for_keys = None ,
allow_agent = False , key_policy = " loose " ) :
allow_agent = False , key_policy = " loose " ) :
@ -90,15 +95,16 @@ class Shell(object):
if not look_for_keys :
if not look_for_keys :
look_for_keys = password is None
look_for_keys = password is None
try :
try :
self . ssh . connect (
self . ssh . connect (
host , port = port , username = username , password = password ,
host , port = port , username = username , password = password ,
timeout = timeout, look_for_keys = look_for_keys , pkey = pkey ,
timeout = self . _ timeout, look_for_keys = look_for_keys , pkey = pkey ,
key_filename = key_filename , allow_agent = allow_agent ,
key_filename = key_filename , allow_agent = allow_agent ,
)
)
self . shell = self . ssh . invoke_shell ( )
self . shell = self . ssh . invoke_shell ( )
self . shell . settimeout ( timeout)
self . shell . settimeout ( self . _ timeout)
except socket . gaierror :
except socket . gaierror :
raise ShellError ( " unable to resolve host name " )
raise ShellError ( " unable to resolve host name " )
except AuthenticationException :
except AuthenticationException :
@ -121,6 +127,10 @@ class Shell(object):
data = regex . sub ( ' ' , data )
data = regex . sub ( ' ' , data )
return data
return data
def alarm_handler ( self , signum , frame ) :
self . shell . close ( )
raise ShellError ( ' timeout trying to send command: %s ' % self . _history [ - 1 ] )
def receive ( self , cmd = None ) :
def receive ( self , cmd = None ) :
recv = StringIO ( )
recv = StringIO ( )
handled = False
handled = False
@ -149,14 +159,21 @@ class Shell(object):
responses = list ( )
responses = list ( )
try :
try :
for command in to_list ( commands ) :
for command in to_list ( commands ) :
signal . alarm ( self . _timeout )
self . _history . append ( str ( command ) )
cmd = ' %s \r ' % str ( command )
cmd = ' %s \r ' % str ( command )
self . shell . sendall ( cmd )
self . shell . sendall ( cmd )
if self . _timeout == 0 :
return
responses . append ( self . receive ( command ) )
responses . append ( self . receive ( command ) )
except socket . timeout :
except socket . timeout :
raise ShellError ( " timeout trying to send command: %s " % cmd )
raise ShellError ( " timeout trying to send command: %s " % cmd )
except socket . error :
except socket . error :
exc = get_exception ( )
exc = get_exception ( )
raise ShellError ( " problem sending command to host: %s " % to_native ( exc ) )
raise ShellError ( " problem sending command to host: %s " % to_native ( exc ) )
return responses
return responses
def close ( self ) :
def close ( self ) :
@ -221,16 +238,16 @@ class CliBase(object):
kickstart = kickstart ,
kickstart = kickstart ,
prompts_re = self . CLI_PROMPTS_RE ,
prompts_re = self . CLI_PROMPTS_RE ,
errors_re = self . CLI_ERRORS_RE ,
errors_re = self . CLI_ERRORS_RE ,
timeout = timeout
)
)
self . shell . open (
host , port = port , username = username , password = password ,
self . shell . open ( host , port = port , username = username ,
key_filename = key_file , timeout = timeout ,
password = password , key_filename = key_file )
)
except ShellError :
except ShellError :
exc = get_exception ( )
exc = get_exception ( )
raise NetworkError (
raise NetworkError ( msg = ' failed to connect to %s : %s ' % ( host , port ) ,
msg = ' failed to connect to %s : %s ' % ( host , port ) , exc = to_native ( exc )
exc = to_native ( exc ) )
)
self . _connected = True
self . _connected = True
@ -241,20 +258,17 @@ class CliBase(object):
def authorize ( self , params , * * kwargs ) :
def authorize ( self , params , * * kwargs ) :
pass
pass
### Command methods ###
def execute ( self , commands ) :
def execute ( self , commands ) :
try :
try :
return self . shell . send ( commands )
return self . shell . send ( commands )
except ShellError :
except ShellError :
exc = get_exception ( )
exc = get_exception ( )
commands = [ str ( c ) for c in commands ]
raise NetworkError ( to_native ( exc ) , commands = commands )
raise NetworkError ( to_native ( exc ) , commands = commands )
def run_commands ( self , commands ) :
def run_commands ( self , commands ) :
return self . execute ( to_list ( commands ) )
return self . execute ( to_list ( commands ) )
### Config methods ###
def configure ( self , commands ) :
def configure ( self , commands ) :
raise NotImplementedError
raise NotImplementedError