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, in seconds 41 @rtype: (boolean, str) 42 @return: False for negative value, and an accompanying error message; 43 True otherwise (and msg is None) 44 45 """ 46 if duration < 0: 47 return False, "Invalid sleep duration" 48 time.sleep(duration) 49 return True, None
50 51
52 -def CloseFdNoError(fd, retries=5):
53 """Close a file descriptor ignoring errors. 54 55 @type fd: int 56 @param fd: the file descriptor 57 @type retries: int 58 @param retries: how many retries to make, in case we get any 59 other error than EBADF 60 61 """ 62 try: 63 os.close(fd) 64 except OSError, err: 65 if err.errno != errno.EBADF: 66 if retries > 0: 67 CloseFdNoError(fd, retries - 1)
68 # else either it's closed already or we're out of retries, so we 69 # ignore this and go on 70 71
72 -def SetCloseOnExecFlag(fd, enable):
73 """Sets or unsets the close-on-exec flag on a file descriptor. 74 75 @type fd: int 76 @param fd: File descriptor 77 @type enable: bool 78 @param enable: Whether to set or unset it. 79 80 """ 81 flags = fcntl.fcntl(fd, fcntl.F_GETFD) 82 83 if enable: 84 flags |= fcntl.FD_CLOEXEC 85 else: 86 flags &= ~fcntl.FD_CLOEXEC 87 88 fcntl.fcntl(fd, fcntl.F_SETFD, flags)
89 90
91 -def SetNonblockFlag(fd, enable):
92 """Sets or unsets the O_NONBLOCK flag on on a file descriptor. 93 94 @type fd: int 95 @param fd: File descriptor 96 @type enable: bool 97 @param enable: Whether to set or unset it 98 99 """ 100 flags = fcntl.fcntl(fd, fcntl.F_GETFL) 101 102 if enable: 103 flags |= os.O_NONBLOCK 104 else: 105 flags &= ~os.O_NONBLOCK 106 107 fcntl.fcntl(fd, fcntl.F_SETFL, flags)
108 109
110 -def RetryOnSignal(fn, *args, **kwargs):
111 """Calls a function again if it failed due to EINTR. 112 113 """ 114 while True: 115 try: 116 return fn(*args, **kwargs) 117 except EnvironmentError, err: 118 if err.errno != errno.EINTR: 119 raise 120 except (socket.error, select.error), err: 121 # In python 2.6 and above select.error is an IOError, so it's handled 122 # above, in 2.5 and below it's not, and it's handled here. 123 if not (err.args and err.args[0] == errno.EINTR): 124 raise
125 126
127 -def IgnoreProcessNotFound(fn, *args, **kwargs):
128 """Ignores ESRCH when calling a process-related function. 129 130 ESRCH is raised when a process is not found. 131 132 @rtype: bool 133 @return: Whether process was found 134 135 """ 136 try: 137 fn(*args, **kwargs) 138 except EnvironmentError, err: 139 # Ignore ESRCH 140 if err.errno == errno.ESRCH: 141 return False 142 raise 143 144 return True
145 146
147 -def IgnoreSignals(fn, *args, **kwargs):
148 """Tries to call a function ignoring failures due to EINTR. 149 150 """ 151 try: 152 return fn(*args, **kwargs) 153 except EnvironmentError, err: 154 if err.errno == errno.EINTR: 155 return None 156 else: 157 raise 158 except (select.error, socket.error), err: 159 # In python 2.6 and above select.error is an IOError, so it's handled 160 # above, in 2.5 and below it's not, and it's handled here. 161 if err.args and err.args[0] == errno.EINTR: 162 return None 163 else: 164 raise
165 166
167 -def GetClosedTempfile(*args, **kwargs):
168 """Creates a temporary file and returns its path. 169 170 """ 171 (fd, path) = tempfile.mkstemp(*args, **kwargs) 172 CloseFdNoError(fd) 173 return path
174 175
176 -def IsExecutable(filename):
177 """Checks whether a file exists and is executable. 178 179 @type filename: string 180 @param filename: Filename 181 @rtype: bool 182 183 """ 184 return os.path.isfile(filename) and os.access(filename, os.X_OK)
185 186
187 -def ResetTempfileModule(_time=time.time):
188 """Resets the random name generator of the tempfile module. 189 190 This function should be called after C{os.fork} in the child process to 191 ensure it creates a newly seeded random generator. Otherwise it would 192 generate the same random parts as the parent process. If several processes 193 race for the creation of a temporary file, this could lead to one not getting 194 a temporary name. 195 196 """ 197 # pylint: disable=W0212 198 if ((sys.hexversion >= 0x020703F0 and sys.hexversion < 0x03000000) or 199 sys.hexversion >= 0x030203F0): 200 # Python 2.7 automatically resets the RNG on pid changes (i.e. forking) 201 return 202 203 try: 204 lock = tempfile._once_lock 205 lock.acquire() 206 try: 207 # Re-seed random name generator 208 if tempfile._name_sequence: 209 tempfile._name_sequence.rng.seed(hash(_time()) ^ os.getpid()) 210 finally: 211 lock.release() 212 except AttributeError: 213 logging.critical("The tempfile module misses at least one of the" 214 " '_once_lock' and '_name_sequence' attributes")
215