@ -162,6 +162,22 @@ except ImportError:
raise ValueError ( ' malformed string ' )
raise ValueError ( ' malformed string ' )
return _convert ( node_or_string )
return _convert ( node_or_string )
def get_exception ( ) :
""" Get the current exception.
This code needs to work on Python 2.4 through 3. x , so we cannot use
" except Exception, e: " ( SyntaxError on Python 3. x ) nor
" except Exception as e: " ( SyntaxError on Python 2.4 - 2.5 ) .
Instead we must use : :
except Exception :
e = get_exception ( )
"""
return sys . exc_info ( ) [ 1 ]
FILE_COMMON_ARGUMENTS = dict (
FILE_COMMON_ARGUMENTS = dict (
src = dict ( ) ,
src = dict ( ) ,
mode = dict ( ) ,
mode = dict ( ) ,
@ -527,7 +543,8 @@ class AnsibleModule(object):
return context
return context
try :
try :
ret = selinux . lgetfilecon_raw ( self . _to_filesystem_str ( path ) )
ret = selinux . lgetfilecon_raw ( self . _to_filesystem_str ( path ) )
except OSError , e :
except OSError :
e = get_exception ( )
if e . errno == errno . ENOENT :
if e . errno == errno . ENOENT :
self . fail_json ( path = path , msg = ' path %s does not exist ' % path )
self . fail_json ( path = path , msg = ' path %s does not exist ' % path )
else :
else :
@ -607,7 +624,8 @@ class AnsibleModule(object):
return True
return True
rc = selinux . lsetfilecon ( self . _to_filesystem_str ( path ) ,
rc = selinux . lsetfilecon ( self . _to_filesystem_str ( path ) ,
str ( ' : ' . join ( new_context ) ) )
str ( ' : ' . join ( new_context ) ) )
except OSError , e :
except OSError :
e = get_exception ( )
self . fail_json ( path = path , msg = ' invalid selinux context: %s ' % str ( e ) , new_context = new_context , cur_context = cur_context , input_was = context )
self . fail_json ( path = path , msg = ' invalid selinux context: %s ' % str ( e ) , new_context = new_context , cur_context = cur_context , input_was = context )
if rc != 0 :
if rc != 0 :
self . fail_json ( path = path , msg = ' set selinux context failed ' )
self . fail_json ( path = path , msg = ' set selinux context failed ' )
@ -671,7 +689,8 @@ class AnsibleModule(object):
except Exception :
except Exception :
try :
try :
mode = self . _symbolic_mode_to_octal ( path_stat , mode )
mode = self . _symbolic_mode_to_octal ( path_stat , mode )
except Exception , e :
except Exception :
e = get_exception ( )
self . fail_json ( path = path ,
self . fail_json ( path = path ,
msg = " mode must be in octal or symbolic form " ,
msg = " mode must be in octal or symbolic form " ,
details = str ( e ) )
details = str ( e ) )
@ -698,14 +717,16 @@ class AnsibleModule(object):
new_underlying_stat = os . stat ( path )
new_underlying_stat = os . stat ( path )
if underlying_stat . st_mode != new_underlying_stat . st_mode :
if underlying_stat . st_mode != new_underlying_stat . st_mode :
os . chmod ( path , stat . S_IMODE ( underlying_stat . st_mode ) )
os . chmod ( path , stat . S_IMODE ( underlying_stat . st_mode ) )
except OSError , e :
except OSError :
e = get_exception ( )
if os . path . islink ( path ) and e . errno == errno . EPERM : # Can't set mode on symbolic links
if os . path . islink ( path ) and e . errno == errno . EPERM : # Can't set mode on symbolic links
pass
pass
elif e . errno in ( errno . ENOENT , errno . ELOOP ) : # Can't set mode on broken symbolic links
elif e . errno in ( errno . ENOENT , errno . ELOOP ) : # Can't set mode on broken symbolic links
pass
pass
else :
else :
raise e
raise e
except Exception , e :
except Exception :
e = get_exception ( )
self . fail_json ( path = path , msg = ' chmod failed ' , details = str ( e ) )
self . fail_json ( path = path , msg = ' chmod failed ' , details = str ( e ) )
path_stat = os . lstat ( path )
path_stat = os . lstat ( path )
@ -882,7 +903,8 @@ class AnsibleModule(object):
# setting the locale to '' uses the default locale
# setting the locale to '' uses the default locale
# as it would be returned by locale.getdefaultlocale()
# as it would be returned by locale.getdefaultlocale()
locale . setlocale ( locale . LC_ALL , ' ' )
locale . setlocale ( locale . LC_ALL , ' ' )
except locale . Error , e :
except locale . Error :
e = get_exception ( )
# fallback to the 'C' locale, which may cause unicode
# fallback to the 'C' locale, which may cause unicode
# issues but is preferable to simply failing because
# issues but is preferable to simply failing because
# of an unknown locale
# of an unknown locale
@ -890,7 +912,8 @@ class AnsibleModule(object):
os . environ [ ' LANG ' ] = ' C '
os . environ [ ' LANG ' ] = ' C '
os . environ [ ' LC_CTYPE ' ] = ' C '
os . environ [ ' LC_CTYPE ' ] = ' C '
os . environ [ ' LC_MESSAGES ' ] = ' C '
os . environ [ ' LC_MESSAGES ' ] = ' C '
except Exception , e :
except Exception :
e = get_exception ( )
self . fail_json ( msg = " An unknown error was encountered while attempting to validate the locale: %s " % e )
self . fail_json ( msg = " An unknown error was encountered while attempting to validate the locale: %s " % e )
def _handle_aliases ( self ) :
def _handle_aliases ( self ) :
@ -1035,7 +1058,8 @@ class AnsibleModule(object):
return ( result , None )
return ( result , None )
else :
else :
return result
return result
except Exception , e :
except Exception :
e = get_exception ( )
if include_exceptions :
if include_exceptions :
return ( str , e )
return ( str , e )
return str
return str
@ -1403,7 +1427,8 @@ class AnsibleModule(object):
try :
try :
shutil . copy2 ( fn , backupdest )
shutil . copy2 ( fn , backupdest )
except ( shutil . Error , IOError ) , e :
except ( shutil . Error , IOError ) :
e = get_exception ( )
self . fail_json ( msg = ' Could not make backup of %s to %s : %s ' % ( fn , backupdest , e ) )
self . fail_json ( msg = ' Could not make backup of %s to %s : %s ' % ( fn , backupdest , e ) )
return backupdest
return backupdest
@ -1412,7 +1437,8 @@ class AnsibleModule(object):
if os . path . exists ( tmpfile ) :
if os . path . exists ( tmpfile ) :
try :
try :
os . unlink ( tmpfile )
os . unlink ( tmpfile )
except OSError , e :
except OSError :
e = get_exception ( )
sys . stderr . write ( " could not cleanup %s : %s " % ( tmpfile , e ) )
sys . stderr . write ( " could not cleanup %s : %s " % ( tmpfile , e ) )
def atomic_move ( self , src , dest ) :
def atomic_move ( self , src , dest ) :
@ -1426,7 +1452,8 @@ class AnsibleModule(object):
dest_stat = os . stat ( dest )
dest_stat = os . stat ( dest )
os . chmod ( src , dest_stat . st_mode & 07777 )
os . chmod ( src , dest_stat . st_mode & 07777 )
os . chown ( src , dest_stat . st_uid , dest_stat . st_gid )
os . chown ( src , dest_stat . st_uid , dest_stat . st_gid )
except OSError , e :
except OSError :
e = get_exception ( )
if e . errno != errno . EPERM :
if e . errno != errno . EPERM :
raise
raise
if self . selinux_enabled ( ) :
if self . selinux_enabled ( ) :
@ -1452,7 +1479,8 @@ class AnsibleModule(object):
try :
try :
# Optimistically try a rename, solves some corner cases and can avoid useless work, throws exception if not atomic.
# Optimistically try a rename, solves some corner cases and can avoid useless work, throws exception if not atomic.
os . rename ( src , dest )
os . rename ( src , dest )
except ( IOError , OSError ) , e :
except ( IOError , OSError ) :
e = get_exception ( )
# only try workarounds for errno 18 (cross device), 1 (not permitted), 13 (permission denied)
# only try workarounds for errno 18 (cross device), 1 (not permitted), 13 (permission denied)
# and 26 (text file busy) which happens on vagrant synced folders
# and 26 (text file busy) which happens on vagrant synced folders
if e . errno not in [ errno . EPERM , errno . EXDEV , errno . EACCES , errno . ETXTBSY ] :
if e . errno not in [ errno . EPERM , errno . EXDEV , errno . EACCES , errno . ETXTBSY ] :
@ -1463,7 +1491,8 @@ class AnsibleModule(object):
try :
try :
tmp_dest = tempfile . NamedTemporaryFile (
tmp_dest = tempfile . NamedTemporaryFile (
prefix = " .ansible_tmp " , dir = dest_dir , suffix = dest_file )
prefix = " .ansible_tmp " , dir = dest_dir , suffix = dest_file )
except ( OSError , IOError ) , e :
except ( OSError , IOError ) :
e = get_exception ( )
self . fail_json ( msg = ' The destination directory ( %s ) is not writable by the current user. ' % dest_dir )
self . fail_json ( msg = ' The destination directory ( %s ) is not writable by the current user. ' % dest_dir )
try : # leaves tmp file behind when sudo and not root
try : # leaves tmp file behind when sudo and not root
@ -1480,11 +1509,13 @@ class AnsibleModule(object):
tmp_stat = os . stat ( tmp_dest . name )
tmp_stat = os . stat ( tmp_dest . name )
if dest_stat and ( tmp_stat . st_uid != dest_stat . st_uid or tmp_stat . st_gid != dest_stat . st_gid ) :
if dest_stat and ( tmp_stat . st_uid != dest_stat . st_uid or tmp_stat . st_gid != dest_stat . st_gid ) :
os . chown ( tmp_dest . name , dest_stat . st_uid , dest_stat . st_gid )
os . chown ( tmp_dest . name , dest_stat . st_uid , dest_stat . st_gid )
except OSError , e :
except OSError :
e = get_exception ( )
if e . errno != errno . EPERM :
if e . errno != errno . EPERM :
raise
raise
os . rename ( tmp_dest . name , dest )
os . rename ( tmp_dest . name , dest )
except ( shutil . Error , OSError , IOError ) , e :
except ( shutil . Error , OSError , IOError ) :
e = get_exception ( )
self . cleanup ( tmp_dest . name )
self . cleanup ( tmp_dest . name )
self . fail_json ( msg = ' Could not replace file: %s to %s : %s ' % ( src , dest , e ) )
self . fail_json ( msg = ' Could not replace file: %s to %s : %s ' % ( src , dest , e ) )
@ -1609,7 +1640,8 @@ class AnsibleModule(object):
if cwd and os . path . isdir ( cwd ) :
if cwd and os . path . isdir ( cwd ) :
try :
try :
os . chdir ( cwd )
os . chdir ( cwd )
except ( OSError , IOError ) , e :
except ( OSError , IOError ) :
e = get_exception ( )
self . fail_json ( rc = e . errno , msg = " Could not open %s , %s " % ( cwd , str ( e ) ) )
self . fail_json ( rc = e . errno , msg = " Could not open %s , %s " % ( cwd , str ( e ) ) )
try :
try :
@ -1662,7 +1694,8 @@ class AnsibleModule(object):
cmd . stderr . close ( )
cmd . stderr . close ( )
rc = cmd . returncode
rc = cmd . returncode
except ( OSError , IOError ) , e :
except ( OSError , IOError ) :
e = get_exception ( )
self . fail_json ( rc = e . errno , msg = str ( e ) , cmd = clean_args )
self . fail_json ( rc = e . errno , msg = str ( e ) , cmd = clean_args )
except :
except :
self . fail_json ( rc = 257 , msg = traceback . format_exc ( ) , cmd = clean_args )
self . fail_json ( rc = 257 , msg = traceback . format_exc ( ) , cmd = clean_args )