@ -33,6 +33,149 @@ import shlex
from ansible . module_utils . basic import BOOLEANS_TRUE , BOOLEANS_FALSE
def to_list ( val ) :
if isinstance ( val , ( list , tuple ) ) :
return list ( val )
elif val is not None :
return [ val ]
else :
return list ( )
class FailedConditionsError ( Exception ) :
def __init__ ( self , msg , failed_conditions ) :
super ( FailedConditionsError , self ) . __init__ ( msg )
self . failed_conditions = failed_conditions
class AddCommandError ( Exception ) :
def __init__ ( self , msg , command ) :
super ( AddCommandError , self ) . __init__ ( msg )
self . command = command
class Cli ( object ) :
def __init__ ( self , connection ) :
self . connection = connection
self . default_output = connection . default_output or ' text '
self . _commands = list ( )
@property
def commands ( self ) :
return [ str ( c ) for c in self . _commands ]
def __call__ ( self , commands , output = None ) :
objects = list ( )
for cmd in commands :
objects . append ( self . to_command ( cmd , output ) )
return self . connection . run_commands ( objects )
def to_command ( self , command , output = None , prompt = None , response = None ) :
output = output or self . default_output
if isinstance ( command , Command ) :
return command
elif isinstance ( command , dict ) :
output = cmd . get ( ' output ' ) or output
cmd = cmd [ ' command ' ]
if isinstance ( prompt , basestring ) :
prompt = re . compile ( re . escape ( prompt ) )
return Command ( command , output , prompt = prompt , response = response )
def add_commands ( self , commands , output = None , * * kwargs ) :
for cmd in commands :
self . _commands . append ( self . to_command ( cmd , output , * * kwargs ) )
def run_commands ( self ) :
responses = self . connection . run_commands ( self . _commands )
for resp , cmd in itertools . izip ( responses , self . _commands ) :
cmd . response = resp
# wipe out the commands list to avoid issues if additional
# commands are executed later
self . _commands = list ( )
return responses
class Command ( object ) :
def __init__ ( self , command , output = None , prompt = None , is_reboot = False ,
response = None , delay = 0 ) :
self . command = command
self . output = output
self . prompt = prompt
self . response = response
self . is_reboot = is_reboot
self . delay = delay
def __str__ ( self ) :
return self . command
class CommandRunner ( object ) :
def __init__ ( self , module ) :
self . module = module
self . items = list ( )
self . conditionals = set ( )
self . commands = list ( )
self . retries = 10
self . interval = 1
self . match = ' all '
self . _cache = dict ( )
self . _default_output = module . connection . default_output
def add_command ( self , command , output = None , prompt = None , response = None ) :
if command in [ str ( c ) for c in self . commands ] :
raise AddCommandError ( ' duplicated command detected ' , command = command )
cmd = self . module . cli . to_command ( command , output = output , prompt = prompt ,
response = response )
self . commands . append ( cmd )
def get_command ( self , command , output = None ) :
output = output or self . _default_output
try :
cmdobj = self . _cache [ ( command , output ) ]
return cmdobj . response
except KeyError :
for cmd in self . commands :
if str ( cmd ) == command and cmd . output == output :
self . _cache [ ( command , output ) ] = cmd
return cmd . response
raise ValueError ( " command ' %s ' not found " % command )
def get_responses ( self ) :
return [ cmd . response for cmd in self . commands ]
def add_conditional ( self , condition ) :
self . conditionals . add ( Conditional ( condition ) )
def run ( self ) :
while self . retries > 0 :
self . module . cli . add_commands ( self . commands )
responses = self . module . cli . run_commands ( )
for item in list ( self . conditionals ) :
if item ( responses ) :
if self . match == ' any ' :
return item
self . conditionals . remove ( item )
if not self . conditionals :
break
time . sleep ( self . interval )
self . retries - = 1
else :
failed_conditions = [ item . raw for item in self . conditionals ]
errmsg = ' One or more conditional statements have not be satisfied '
raise FailedConditionsError ( errmsg , failed_conditions )
class Conditional ( object ) :
""" Used in command modules to evaluate waitfor conditions
"""
@ -154,62 +297,3 @@ class Conditional(object):
match = re . search ( value , self . value , re . M )
return match is not None
class FailedConditionsError ( Exception ) :
def __init__ ( self , msg , failed_conditions ) :
super ( FailedConditionsError , self ) . __init__ ( msg )
self . failed_conditions = failed_conditions
class CommandRunner ( object ) :
def __init__ ( self , module ) :
self . module = module
self . items = list ( )
self . conditionals = set ( )
self . retries = 10
self . interval = 1
self . _cache = dict ( )
def add_command ( self , command , output = None ) :
self . module . cli . add_commands ( command , output = output )
def get_command ( self , command ) :
try :
cmdobj = self . _cache [ command ]
return cmdobj . response
except KeyError :
for cmd in self . module . cli . commands :
if str ( cmd ) == command :
self . _cache [ command ] = cmd
return cmd . response
raise ValueError ( " command ' %s ' not found " % command )
def add_conditional ( self , condition ) :
self . conditionals . add ( Conditional ( condition ) )
def run_commands ( self ) :
responses = self . module . cli . run_commands ( )
self . items = responses
def run ( self ) :
while self . retries > 0 :
self . run_commands ( )
for item in list ( self . conditionals ) :
if item ( self . items ) :
self . conditionals . remove ( item )
if not self . conditionals :
break
time . sleep ( self . interval )
self . retries - = 1
else :
failed_conditions = [ item . raw for item in self . conditionals ]
raise FailedConditionsError ( ' timeout waiting for value ' , failed_conditions )