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  # All rights reserved. 
  6  # 
  7  # Redistribution and use in source and binary forms, with or without 
  8  # modification, are permitted provided that the following conditions are 
  9  # met: 
 10  # 
 11  # 1. Redistributions of source code must retain the above copyright notice, 
 12  # this list of conditions and the following disclaimer. 
 13  # 
 14  # 2. Redistributions in binary form must reproduce the above copyright 
 15  # notice, this list of conditions and the following disclaimer in the 
 16  # documentation and/or other materials provided with the distribution. 
 17  # 
 18  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
 19  # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
 20  # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 21  # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
 22  # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 23  # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 24  # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
 25  # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 26  # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
 27  # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 28  # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 29   
 30  """Utility functions wrapping other functions. 
 31   
 32  """ 
 33   
 34  import sys 
 35  import time 
 36  import socket 
 37  import errno 
 38  import tempfile 
 39  import fcntl 
 40  import os 
 41  import select 
 42  import logging 
 43   
 44   
45 -def TestDelay(duration):
46 """Sleep for a fixed amount of time. 47 48 @type duration: float 49 @param duration: the sleep duration, in seconds 50 @rtype: (boolean, str) 51 @return: False for negative value, and an accompanying error message; 52 True otherwise (and msg is None) 53 54 """ 55 if duration < 0: 56 return False, "Invalid sleep duration" 57 time.sleep(duration) 58 return True, None
59 60
61 -def CloseFdNoError(fd, retries=5):
62 """Close a file descriptor ignoring errors. 63 64 @type fd: int 65 @param fd: the file descriptor 66 @type retries: int 67 @param retries: how many retries to make, in case we get any 68 other error than EBADF 69 70 """ 71 try: 72 os.close(fd) 73 except OSError, err: 74 if err.errno != errno.EBADF: 75 if retries > 0: 76 CloseFdNoError(fd, retries - 1)
77 # else either it's closed already or we're out of retries, so we 78 # ignore this and go on 79 80
81 -def SetCloseOnExecFlag(fd, enable):
82 """Sets or unsets the close-on-exec flag on a file descriptor. 83 84 @type fd: int 85 @param fd: File descriptor 86 @type enable: bool 87 @param enable: Whether to set or unset it. 88 89 """ 90 flags = fcntl.fcntl(fd, fcntl.F_GETFD) 91 92 if enable: 93 flags |= fcntl.FD_CLOEXEC 94 else: 95 flags &= ~fcntl.FD_CLOEXEC 96 97 fcntl.fcntl(fd, fcntl.F_SETFD, flags)
98 99
100 -def SetNonblockFlag(fd, enable):
101 """Sets or unsets the O_NONBLOCK flag on on a file descriptor. 102 103 @type fd: int 104 @param fd: File descriptor 105 @type enable: bool 106 @param enable: Whether to set or unset it 107 108 """ 109 flags = fcntl.fcntl(fd, fcntl.F_GETFL) 110 111 if enable: 112 flags |= os.O_NONBLOCK 113 else: 114 flags &= ~os.O_NONBLOCK 115 116 fcntl.fcntl(fd, fcntl.F_SETFL, flags)
117 118
119 -def RetryOnSignal(fn, *args, **kwargs):
120 """Calls a function again if it failed due to EINTR. 121 122 """ 123 while True: 124 try: 125 return fn(*args, **kwargs) 126 except EnvironmentError, err: 127 if err.errno != errno.EINTR: 128 raise 129 except (socket.error, select.error), err: 130 # In python 2.6 and above select.error is an IOError, so it's handled 131 # above, in 2.5 and below it's not, and it's handled here. 132 if not (err.args and err.args[0] == errno.EINTR): 133 raise
134 135
136 -def IgnoreProcessNotFound(fn, *args, **kwargs):
137 """Ignores ESRCH when calling a process-related function. 138 139 ESRCH is raised when a process is not found. 140 141 @rtype: bool 142 @return: Whether process was found 143 144 """ 145 try: 146 fn(*args, **kwargs) 147 except EnvironmentError, err: 148 # Ignore ESRCH 149 if err.errno == errno.ESRCH: 150 return False 151 raise 152 153 return True
154 155
156 -def IgnoreSignals(fn, *args, **kwargs):
157 """Tries to call a function ignoring failures due to EINTR. 158 159 """ 160 try: 161 return fn(*args, **kwargs) 162 except EnvironmentError, err: 163 if err.errno == errno.EINTR: 164 return None 165 else: 166 raise 167 except (select.error, socket.error), err: 168 # In python 2.6 and above select.error is an IOError, so it's handled 169 # above, in 2.5 and below it's not, and it's handled here. 170 if err.args and err.args[0] == errno.EINTR: 171 return None 172 else: 173 raise
174 175
176 -def GetClosedTempfile(*args, **kwargs):
177 """Creates a temporary file and returns its path. 178 179 """ 180 (fd, path) = tempfile.mkstemp(*args, **kwargs) 181 CloseFdNoError(fd) 182 return path
183 184
185 -def IsExecutable(filename):
186 """Checks whether a file exists and is executable. 187 188 @type filename: string 189 @param filename: Filename 190 @rtype: bool 191 192 """ 193 return os.path.isfile(filename) and os.access(filename, os.X_OK)
194 195
196 -def ResetTempfileModule(_time=time.time):
197 """Resets the random name generator of the tempfile module. 198 199 This function should be called after C{os.fork} in the child process to 200 ensure it creates a newly seeded random generator. Otherwise it would 201 generate the same random parts as the parent process. If several processes 202 race for the creation of a temporary file, this could lead to one not getting 203 a temporary name. 204 205 """ 206 # pylint: disable=W0212 207 if ((sys.hexversion >= 0x020703F0 and sys.hexversion < 0x03000000) or 208 sys.hexversion >= 0x030203F0): 209 # Python 2.7 automatically resets the RNG on pid changes (i.e. forking) 210 return 211 212 try: 213 lock = tempfile._once_lock 214 lock.acquire() 215 try: 216 # Re-seed random name generator 217 if tempfile._name_sequence: 218 tempfile._name_sequence.rng.seed(hash(_time()) ^ os.getpid()) 219 finally: 220 lock.release() 221 except AttributeError: 222 logging.critical("The tempfile module misses at least one of the" 223 " '_once_lock' and '_name_sequence' attributes")
224