Package ganeti :: Package utils :: Module wrapper
[hide private]
[frames] | no frames]

Source Code for Module ganeti.utils.wrapper

  1  # 
  2  # 
  3   
  4  # Copyright (C) 2006, 2007, 2010, 2011, 2012 Google Inc. 
  5  # 
  6  # This program is free software; you can redistribute it and/or modify 
  7  # it under the terms of the GNU General Public License as published by 
  8  # the Free Software Foundation; either version 2 of the License, or 
  9  # (at your option) any later version. 
 10  # 
 11  # This program is distributed in the hope that it will be useful, but 
 12  # WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
 14  # General Public License for more details. 
 15  # 
 16  # You should have received a copy of the GNU General Public License 
 17  # along with this program; if not, write to the Free Software 
 18  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
 19  # 02110-1301, USA. 
 20   
 21  """Utility functions wrapping other functions. 
 22   
 23  """ 
 24   
 25  import sys 
 26  import time 
 27  import socket 
 28  import errno 
 29  import tempfile 
 30  import fcntl 
 31  import os 
 32  import select 
 33  import logging 
 34   
 35   
36 -def TestDelay(duration):
37 """Sleep for a fixed amount of time. 38 39 @type duration: float 40 @param duration: the sleep duration 41 @rtype: boolean 42 @return: False for negative value, True otherwise 43 44 """ 45 if duration < 0: 46 return False, "Invalid sleep duration" 47 time.sleep(duration) 48 return True, None
49 50
51 -def CloseFdNoError(fd, retries=5):
52 """Close a file descriptor ignoring errors. 53 54 @type fd: int 55 @param fd: the file descriptor 56 @type retries: int 57 @param retries: how many retries to make, in case we get any 58 other error than EBADF 59 60 """ 61 try: 62 os.close(fd) 63 except OSError, err: 64 if err.errno != errno.EBADF: 65 if retries > 0: 66 CloseFdNoError(fd, retries - 1)
67 # else either it's closed already or we're out of retries, so we 68 # ignore this and go on 69 70
71 -def SetCloseOnExecFlag(fd, enable):
72 """Sets or unsets the close-on-exec flag on a file descriptor. 73 74 @type fd: int 75 @param fd: File descriptor 76 @type enable: bool 77 @param enable: Whether to set or unset it. 78 79 """ 80 flags = fcntl.fcntl(fd, fcntl.F_GETFD) 81 82 if enable: 83 flags |= fcntl.FD_CLOEXEC 84 else: 85 flags &= ~fcntl.FD_CLOEXEC 86 87 fcntl.fcntl(fd, fcntl.F_SETFD, flags)
88 89
90 -def SetNonblockFlag(fd, enable):
91 """Sets or unsets the O_NONBLOCK flag on on a file descriptor. 92 93 @type fd: int 94 @param fd: File descriptor 95 @type enable: bool 96 @param enable: Whether to set or unset it 97 98 """ 99 flags = fcntl.fcntl(fd, fcntl.F_GETFL) 100 101 if enable: 102 flags |= os.O_NONBLOCK 103 else: 104 flags &= ~os.O_NONBLOCK 105 106 fcntl.fcntl(fd, fcntl.F_SETFL, flags)
107 108
109 -def RetryOnSignal(fn, *args, **kwargs):
110 """Calls a function again if it failed due to EINTR. 111 112 """ 113 while True: 114 try: 115 return fn(*args, **kwargs) 116 except EnvironmentError, err: 117 if err.errno != errno.EINTR: 118 raise 119 except (socket.error, select.error), err: 120 # In python 2.6 and above select.error is an IOError, so it's handled 121 # above, in 2.5 and below it's not, and it's handled here. 122 if not (err.args and err.args[0] == errno.EINTR): 123 raise
124 125
126 -def IgnoreProcessNotFound(fn, *args, **kwargs):
127 """Ignores ESRCH when calling a process-related function. 128 129 ESRCH is raised when a process is not found. 130 131 @rtype: bool 132 @return: Whether process was found 133 134 """ 135 try: 136 fn(*args, **kwargs) 137 except EnvironmentError, err: 138 # Ignore ESRCH 139 if err.errno == errno.ESRCH: 140 return False 141 raise 142 143 return True
144 145
146 -def IgnoreSignals(fn, *args, **kwargs):
147 """Tries to call a function ignoring failures due to EINTR. 148 149 """ 150 try: 151 return fn(*args, **kwargs) 152 except EnvironmentError, err: 153 if err.errno == errno.EINTR: 154 return None 155 else: 156 raise 157 except (select.error, socket.error), err: 158 # In python 2.6 and above select.error is an IOError, so it's handled 159 # above, in 2.5 and below it's not, and it's handled here. 160 if err.args and err.args[0] == errno.EINTR: 161 return None 162 else: 163 raise
164 165
166 -def GetClosedTempfile(*args, **kwargs):
167 """Creates a temporary file and returns its path. 168 169 """ 170 (fd, path) = tempfile.mkstemp(*args, **kwargs) 171 CloseFdNoError(fd) 172 return path
173 174
175 -def IsExecutable(filename):
176 """Checks whether a file exists and is executable. 177 178 @type filename: string 179 @param filename: Filename 180 @rtype: bool 181 182 """ 183 return os.path.isfile(filename) and os.access(filename, os.X_OK)
184 185
186 -def ResetTempfileModule(_time=time.time):
187 """Resets the random name generator of the tempfile module. 188 189 This function should be called after C{os.fork} in the child process to 190 ensure it creates a newly seeded random generator. Otherwise it would 191 generate the same random parts as the parent process. If several processes 192 race for the creation of a temporary file, this could lead to one not getting 193 a temporary name. 194 195 """ 196 # pylint: disable=W0212 197 if ((sys.hexversion >= 0x020703F0 and sys.hexversion < 0x03000000) or 198 sys.hexversion >= 0x030203F0): 199 # Python 2.7 automatically resets the RNG on pid changes (i.e. forking) 200 return 201 202 try: 203 lock = tempfile._once_lock 204 lock.acquire() 205 try: 206 # Re-seed random name generator 207 if tempfile._name_sequence: 208 tempfile._name_sequence.rng.seed(hash(_time()) ^ os.getpid()) 209 finally: 210 lock.release() 211 except AttributeError: 212 logging.critical("The tempfile module misses at least one of the" 213 " '_once_lock' and '_name_sequence' attributes")
214