Statistics
| Branch: | Tag: | Revision:

root / lib / utils.py @ 2f8b60b3

History | View | Annotate | Download (20.5 kB)

1 2f31098c Iustin Pop
#
2 a8083063 Iustin Pop
#
3 a8083063 Iustin Pop
4 a8083063 Iustin Pop
# Copyright (C) 2006, 2007 Google Inc.
5 a8083063 Iustin Pop
#
6 a8083063 Iustin Pop
# This program is free software; you can redistribute it and/or modify
7 a8083063 Iustin Pop
# it under the terms of the GNU General Public License as published by
8 a8083063 Iustin Pop
# the Free Software Foundation; either version 2 of the License, or
9 a8083063 Iustin Pop
# (at your option) any later version.
10 a8083063 Iustin Pop
#
11 a8083063 Iustin Pop
# This program is distributed in the hope that it will be useful, but
12 a8083063 Iustin Pop
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 a8083063 Iustin Pop
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 a8083063 Iustin Pop
# General Public License for more details.
15 a8083063 Iustin Pop
#
16 a8083063 Iustin Pop
# You should have received a copy of the GNU General Public License
17 a8083063 Iustin Pop
# along with this program; if not, write to the Free Software
18 a8083063 Iustin Pop
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 a8083063 Iustin Pop
# 02110-1301, USA.
20 a8083063 Iustin Pop
21 a8083063 Iustin Pop
22 a8083063 Iustin Pop
"""Ganeti small utilities
23 a8083063 Iustin Pop
"""
24 a8083063 Iustin Pop
25 a8083063 Iustin Pop
26 a8083063 Iustin Pop
import sys
27 a8083063 Iustin Pop
import os
28 a8083063 Iustin Pop
import sha
29 a8083063 Iustin Pop
import time
30 113b55aa Iustin Pop
import subprocess
31 a8083063 Iustin Pop
import re
32 a8083063 Iustin Pop
import socket
33 a8083063 Iustin Pop
import tempfile
34 a8083063 Iustin Pop
import shutil
35 4ca1b175 Alexander Schreiber
import errno
36 2f8b60b3 Iustin Pop
import pwd
37 a8083063 Iustin Pop
38 a8083063 Iustin Pop
from ganeti import logger
39 a8083063 Iustin Pop
from ganeti import errors
40 a8083063 Iustin Pop
41 16abfbc2 Alexander Schreiber
42 a8083063 Iustin Pop
_locksheld = []
43 a8083063 Iustin Pop
_re_shell_unquoted = re.compile('^[-.,=:/_+@A-Za-z0-9]+$')
44 a8083063 Iustin Pop
45 a8083063 Iustin Pop
class RunResult(object):
46 a8083063 Iustin Pop
  """Simple class for holding the result of running external programs.
47 a8083063 Iustin Pop

48 a8083063 Iustin Pop
  Instance variables:
49 a8083063 Iustin Pop
    exit_code: the exit code of the program, or None (if the program
50 a8083063 Iustin Pop
               didn't exit())
51 a8083063 Iustin Pop
    signal: numeric signal that caused the program to finish, or None
52 a8083063 Iustin Pop
            (if the program wasn't terminated by a signal)
53 a8083063 Iustin Pop
    stdout: the standard output of the program
54 a8083063 Iustin Pop
    stderr: the standard error of the program
55 a8083063 Iustin Pop
    failed: a Boolean value which is True in case the program was
56 a8083063 Iustin Pop
            terminated by a signal or exited with a non-zero exit code
57 a8083063 Iustin Pop
    fail_reason: a string detailing the termination reason
58 a8083063 Iustin Pop

59 a8083063 Iustin Pop
  """
60 a8083063 Iustin Pop
  __slots__ = ["exit_code", "signal", "stdout", "stderr",
61 a8083063 Iustin Pop
               "failed", "fail_reason", "cmd"]
62 a8083063 Iustin Pop
63 a8083063 Iustin Pop
64 a8083063 Iustin Pop
  def __init__(self, exit_code, signal, stdout, stderr, cmd):
65 a8083063 Iustin Pop
    self.cmd = cmd
66 a8083063 Iustin Pop
    self.exit_code = exit_code
67 a8083063 Iustin Pop
    self.signal = signal
68 a8083063 Iustin Pop
    self.stdout = stdout
69 a8083063 Iustin Pop
    self.stderr = stderr
70 a8083063 Iustin Pop
    self.failed = (signal is not None or exit_code != 0)
71 a8083063 Iustin Pop
72 a8083063 Iustin Pop
    if self.signal is not None:
73 a8083063 Iustin Pop
      self.fail_reason = "terminated by signal %s" % self.signal
74 a8083063 Iustin Pop
    elif self.exit_code is not None:
75 a8083063 Iustin Pop
      self.fail_reason = "exited with exit code %s" % self.exit_code
76 a8083063 Iustin Pop
    else:
77 a8083063 Iustin Pop
      self.fail_reason = "unable to determine termination reason"
78 a8083063 Iustin Pop
79 a8083063 Iustin Pop
  def _GetOutput(self):
80 a8083063 Iustin Pop
    """Returns the combined stdout and stderr for easier usage.
81 a8083063 Iustin Pop

82 a8083063 Iustin Pop
    """
83 a8083063 Iustin Pop
    return self.stdout + self.stderr
84 a8083063 Iustin Pop
85 a8083063 Iustin Pop
  output = property(_GetOutput, None, None, "Return full output")
86 a8083063 Iustin Pop
87 a8083063 Iustin Pop
88 a8083063 Iustin Pop
def _GetLockFile(subsystem):
89 a8083063 Iustin Pop
  """Compute the file name for a given lock name."""
90 a8083063 Iustin Pop
  return "/var/lock/ganeti_lock_%s" % subsystem
91 a8083063 Iustin Pop
92 a8083063 Iustin Pop
93 a8083063 Iustin Pop
def Lock(name, max_retries=None, debug=False):
94 a8083063 Iustin Pop
  """Lock a given subsystem.
95 a8083063 Iustin Pop

96 a8083063 Iustin Pop
  In case the lock is already held by an alive process, the function
97 a8083063 Iustin Pop
  will sleep indefintely and poll with a one second interval.
98 a8083063 Iustin Pop

99 a8083063 Iustin Pop
  When the optional integer argument 'max_retries' is passed with a
100 a8083063 Iustin Pop
  non-zero value, the function will sleep only for this number of
101 a8083063 Iustin Pop
  times, and then it will will raise a LockError if the lock can't be
102 a8083063 Iustin Pop
  acquired. Passing in a negative number will cause only one try to
103 a8083063 Iustin Pop
  get the lock. Passing a positive number will make the function retry
104 a8083063 Iustin Pop
  for approximately that number of seconds.
105 a8083063 Iustin Pop

106 a8083063 Iustin Pop
  """
107 a8083063 Iustin Pop
  lockfile = _GetLockFile(name)
108 a8083063 Iustin Pop
109 a8083063 Iustin Pop
  if name in _locksheld:
110 a8083063 Iustin Pop
    raise errors.LockError('Lock "%s" already held!' % (name,))
111 a8083063 Iustin Pop
112 a8083063 Iustin Pop
  errcount = 0
113 a8083063 Iustin Pop
114 a8083063 Iustin Pop
  retries = 0
115 a8083063 Iustin Pop
  while True:
116 a8083063 Iustin Pop
    try:
117 a8083063 Iustin Pop
      fd = os.open(lockfile, os.O_CREAT | os.O_EXCL | os.O_RDWR | os.O_SYNC)
118 a8083063 Iustin Pop
      break
119 a8083063 Iustin Pop
    except OSError, creat_err:
120 4ca1b175 Alexander Schreiber
      if creat_err.errno != errno.EEXIST:
121 3ecf6786 Iustin Pop
        raise errors.LockError("Can't create the lock file. Error '%s'." %
122 3ecf6786 Iustin Pop
                               str(creat_err))
123 a8083063 Iustin Pop
124 a8083063 Iustin Pop
      try:
125 a8083063 Iustin Pop
        pf = open(lockfile, 'r')
126 a8083063 Iustin Pop
      except IOError, open_err:
127 a8083063 Iustin Pop
        errcount += 1
128 a8083063 Iustin Pop
        if errcount >= 5:
129 3ecf6786 Iustin Pop
          raise errors.LockError("Lock file exists but cannot be opened."
130 3ecf6786 Iustin Pop
                                 " Error: '%s'." % str(open_err))
131 a8083063 Iustin Pop
        time.sleep(1)
132 a8083063 Iustin Pop
        continue
133 a8083063 Iustin Pop
134 a8083063 Iustin Pop
      try:
135 a8083063 Iustin Pop
        pid = int(pf.read())
136 a8083063 Iustin Pop
      except ValueError:
137 3ecf6786 Iustin Pop
        raise errors.LockError("Invalid pid string in %s" %
138 a8083063 Iustin Pop
                               (lockfile,))
139 a8083063 Iustin Pop
140 a8083063 Iustin Pop
      if not IsProcessAlive(pid):
141 3ecf6786 Iustin Pop
        raise errors.LockError("Stale lockfile %s for pid %d?" %
142 3ecf6786 Iustin Pop
                               (lockfile, pid))
143 a8083063 Iustin Pop
144 a8083063 Iustin Pop
      if max_retries and max_retries <= retries:
145 3ecf6786 Iustin Pop
        raise errors.LockError("Can't acquire lock during the specified"
146 3ecf6786 Iustin Pop
                               " time, aborting.")
147 a8083063 Iustin Pop
      if retries == 5 and (debug or sys.stdin.isatty()):
148 a8083063 Iustin Pop
        logger.ToStderr("Waiting for '%s' lock from pid %d..." % (name, pid))
149 a8083063 Iustin Pop
150 a8083063 Iustin Pop
      time.sleep(1)
151 a8083063 Iustin Pop
      retries += 1
152 a8083063 Iustin Pop
      continue
153 a8083063 Iustin Pop
154 a8083063 Iustin Pop
  os.write(fd, '%d\n' % (os.getpid(),))
155 a8083063 Iustin Pop
  os.close(fd)
156 a8083063 Iustin Pop
157 a8083063 Iustin Pop
  _locksheld.append(name)
158 a8083063 Iustin Pop
159 a8083063 Iustin Pop
160 a8083063 Iustin Pop
def Unlock(name):
161 098c0958 Michael Hanselmann
  """Unlock a given subsystem.
162 a8083063 Iustin Pop

163 098c0958 Michael Hanselmann
  """
164 a8083063 Iustin Pop
  lockfile = _GetLockFile(name)
165 a8083063 Iustin Pop
166 a8083063 Iustin Pop
  try:
167 a8083063 Iustin Pop
    fd = os.open(lockfile, os.O_RDONLY)
168 a8083063 Iustin Pop
  except OSError:
169 a8083063 Iustin Pop
    raise errors.LockError('Lock "%s" not held.' % (name,))
170 a8083063 Iustin Pop
171 a8083063 Iustin Pop
  f = os.fdopen(fd, 'r')
172 a8083063 Iustin Pop
  pid_str = f.read()
173 a8083063 Iustin Pop
174 a8083063 Iustin Pop
  try:
175 a8083063 Iustin Pop
    pid = int(pid_str)
176 a8083063 Iustin Pop
  except ValueError:
177 a8083063 Iustin Pop
    raise errors.LockError('Unable to determine PID of locking process.')
178 a8083063 Iustin Pop
179 a8083063 Iustin Pop
  if pid != os.getpid():
180 a8083063 Iustin Pop
    raise errors.LockError('Lock not held by me (%d != %d)' %
181 a8083063 Iustin Pop
                           (os.getpid(), pid,))
182 a8083063 Iustin Pop
183 a8083063 Iustin Pop
  os.unlink(lockfile)
184 a8083063 Iustin Pop
  _locksheld.remove(name)
185 a8083063 Iustin Pop
186 a8083063 Iustin Pop
187 a8083063 Iustin Pop
def LockCleanup():
188 098c0958 Michael Hanselmann
  """Remove all locks.
189 a8083063 Iustin Pop

190 098c0958 Michael Hanselmann
  """
191 a8083063 Iustin Pop
  for lock in _locksheld:
192 a8083063 Iustin Pop
    Unlock(lock)
193 a8083063 Iustin Pop
194 a8083063 Iustin Pop
195 a8083063 Iustin Pop
def RunCmd(cmd):
196 a8083063 Iustin Pop
  """Execute a (shell) command.
197 a8083063 Iustin Pop

198 a8083063 Iustin Pop
  The command should not read from its standard input, as it will be
199 a8083063 Iustin Pop
  closed.
200 a8083063 Iustin Pop

201 a8083063 Iustin Pop
  Args:
202 a8083063 Iustin Pop
    cmd: command to run. (str)
203 a8083063 Iustin Pop

204 a8083063 Iustin Pop
  Returns: `RunResult` instance
205 a8083063 Iustin Pop

206 a8083063 Iustin Pop
  """
207 a8083063 Iustin Pop
  if isinstance(cmd, list):
208 a8083063 Iustin Pop
    cmd = [str(val) for val in cmd]
209 113b55aa Iustin Pop
    strcmd = " ".join(cmd)
210 113b55aa Iustin Pop
    shell = False
211 113b55aa Iustin Pop
  else:
212 113b55aa Iustin Pop
    strcmd = cmd
213 113b55aa Iustin Pop
    shell = True
214 23f41a3e Michael Hanselmann
  env = os.environ.copy()
215 23f41a3e Michael Hanselmann
  env["LC_ALL"] = "C"
216 113b55aa Iustin Pop
  child = subprocess.Popen(cmd, shell=shell,
217 113b55aa Iustin Pop
                           stderr=subprocess.PIPE,
218 113b55aa Iustin Pop
                           stdout=subprocess.PIPE,
219 113b55aa Iustin Pop
                           stdin=subprocess.PIPE,
220 23f41a3e Michael Hanselmann
                           close_fds=True, env=env)
221 113b55aa Iustin Pop
222 113b55aa Iustin Pop
  child.stdin.close()
223 113b55aa Iustin Pop
  out = child.stdout.read()
224 113b55aa Iustin Pop
  err = child.stderr.read()
225 a8083063 Iustin Pop
226 a8083063 Iustin Pop
  status = child.wait()
227 113b55aa Iustin Pop
  if status >= 0:
228 113b55aa Iustin Pop
    exitcode = status
229 a8083063 Iustin Pop
    signal = None
230 a8083063 Iustin Pop
  else:
231 a8083063 Iustin Pop
    exitcode = None
232 113b55aa Iustin Pop
    signal = -status
233 a8083063 Iustin Pop
234 a8083063 Iustin Pop
  return RunResult(exitcode, signal, out, err, strcmd)
235 a8083063 Iustin Pop
236 a8083063 Iustin Pop
237 a8083063 Iustin Pop
def RunCmdUnlocked(cmd):
238 a8083063 Iustin Pop
  """Execute a shell command without the 'cmd' lock.
239 a8083063 Iustin Pop

240 a8083063 Iustin Pop
  This variant of `RunCmd()` drops the 'cmd' lock before running the
241 a8083063 Iustin Pop
  command and re-aquires it afterwards, thus it can be used to call
242 a8083063 Iustin Pop
  other ganeti commands.
243 a8083063 Iustin Pop

244 a8083063 Iustin Pop
  The argument and return values are the same as for the `RunCmd()`
245 a8083063 Iustin Pop
  function.
246 a8083063 Iustin Pop

247 a8083063 Iustin Pop
  Args:
248 a8083063 Iustin Pop
    cmd - command to run. (str)
249 a8083063 Iustin Pop

250 a8083063 Iustin Pop
  Returns:
251 a8083063 Iustin Pop
    `RunResult`
252 a8083063 Iustin Pop

253 a8083063 Iustin Pop
  """
254 a8083063 Iustin Pop
  Unlock('cmd')
255 a8083063 Iustin Pop
  ret = RunCmd(cmd)
256 a8083063 Iustin Pop
  Lock('cmd')
257 a8083063 Iustin Pop
258 a8083063 Iustin Pop
  return ret
259 a8083063 Iustin Pop
260 a8083063 Iustin Pop
261 a8083063 Iustin Pop
def RemoveFile(filename):
262 a8083063 Iustin Pop
  """Remove a file ignoring some errors.
263 a8083063 Iustin Pop

264 a8083063 Iustin Pop
  Remove a file, ignoring non-existing ones or directories. Other
265 a8083063 Iustin Pop
  errors are passed.
266 a8083063 Iustin Pop

267 a8083063 Iustin Pop
  """
268 a8083063 Iustin Pop
  try:
269 a8083063 Iustin Pop
    os.unlink(filename)
270 a8083063 Iustin Pop
  except OSError, err:
271 4ca1b175 Alexander Schreiber
    if err.errno not in (errno.ENOENT, errno.EISDIR):
272 a8083063 Iustin Pop
      raise
273 a8083063 Iustin Pop
274 a8083063 Iustin Pop
275 a8083063 Iustin Pop
def _FingerprintFile(filename):
276 a8083063 Iustin Pop
  """Compute the fingerprint of a file.
277 a8083063 Iustin Pop

278 a8083063 Iustin Pop
  If the file does not exist, a None will be returned
279 a8083063 Iustin Pop
  instead.
280 a8083063 Iustin Pop

281 a8083063 Iustin Pop
  Args:
282 a8083063 Iustin Pop
    filename - Filename (str)
283 a8083063 Iustin Pop

284 a8083063 Iustin Pop
  """
285 a8083063 Iustin Pop
  if not (os.path.exists(filename) and os.path.isfile(filename)):
286 a8083063 Iustin Pop
    return None
287 a8083063 Iustin Pop
288 a8083063 Iustin Pop
  f = open(filename)
289 a8083063 Iustin Pop
290 a8083063 Iustin Pop
  fp = sha.sha()
291 a8083063 Iustin Pop
  while True:
292 a8083063 Iustin Pop
    data = f.read(4096)
293 a8083063 Iustin Pop
    if not data:
294 a8083063 Iustin Pop
      break
295 a8083063 Iustin Pop
296 a8083063 Iustin Pop
    fp.update(data)
297 a8083063 Iustin Pop
298 a8083063 Iustin Pop
  return fp.hexdigest()
299 a8083063 Iustin Pop
300 a8083063 Iustin Pop
301 a8083063 Iustin Pop
def FingerprintFiles(files):
302 a8083063 Iustin Pop
  """Compute fingerprints for a list of files.
303 a8083063 Iustin Pop

304 a8083063 Iustin Pop
  Args:
305 a8083063 Iustin Pop
    files - array of filenames.  ( [str, ...] )
306 a8083063 Iustin Pop

307 a8083063 Iustin Pop
  Return value:
308 a8083063 Iustin Pop
    dictionary of filename: fingerprint for the files that exist
309 a8083063 Iustin Pop

310 a8083063 Iustin Pop
  """
311 a8083063 Iustin Pop
  ret = {}
312 a8083063 Iustin Pop
313 a8083063 Iustin Pop
  for filename in files:
314 a8083063 Iustin Pop
    cksum = _FingerprintFile(filename)
315 a8083063 Iustin Pop
    if cksum:
316 a8083063 Iustin Pop
      ret[filename] = cksum
317 a8083063 Iustin Pop
318 a8083063 Iustin Pop
  return ret
319 a8083063 Iustin Pop
320 a8083063 Iustin Pop
321 a8083063 Iustin Pop
def CheckDict(target, template, logname=None):
322 a8083063 Iustin Pop
  """Ensure a dictionary has a required set of keys.
323 a8083063 Iustin Pop

324 a8083063 Iustin Pop
  For the given dictionaries `target` and `template`, ensure target
325 a8083063 Iustin Pop
  has all the keys from template. Missing keys are added with values
326 a8083063 Iustin Pop
  from template.
327 a8083063 Iustin Pop

328 a8083063 Iustin Pop
  Args:
329 a8083063 Iustin Pop
    target   - the dictionary to check
330 a8083063 Iustin Pop
    template - template dictionary
331 a8083063 Iustin Pop
    logname  - a caller-chosen string to identify the debug log
332 a8083063 Iustin Pop
               entry; if None, no logging will be done
333 a8083063 Iustin Pop

334 a8083063 Iustin Pop
  Returns value:
335 a8083063 Iustin Pop
    None
336 a8083063 Iustin Pop

337 a8083063 Iustin Pop
  """
338 a8083063 Iustin Pop
  missing = []
339 a8083063 Iustin Pop
  for k in template:
340 a8083063 Iustin Pop
    if k not in target:
341 a8083063 Iustin Pop
      missing.append(k)
342 a8083063 Iustin Pop
      target[k] = template[k]
343 a8083063 Iustin Pop
344 a8083063 Iustin Pop
  if missing and logname:
345 a8083063 Iustin Pop
    logger.Debug('%s missing keys %s' %
346 a8083063 Iustin Pop
                 (logname, ', '.join(missing)))
347 a8083063 Iustin Pop
348 a8083063 Iustin Pop
349 a8083063 Iustin Pop
def IsProcessAlive(pid):
350 a8083063 Iustin Pop
  """Check if a given pid exists on the system.
351 a8083063 Iustin Pop

352 a8083063 Iustin Pop
  Returns: true or false, depending on if the pid exists or not
353 a8083063 Iustin Pop

354 a8083063 Iustin Pop
  Remarks: zombie processes treated as not alive
355 a8083063 Iustin Pop

356 a8083063 Iustin Pop
  """
357 a8083063 Iustin Pop
  try:
358 a8083063 Iustin Pop
    f = open("/proc/%d/status" % pid)
359 a8083063 Iustin Pop
  except IOError, err:
360 4ca1b175 Alexander Schreiber
    if err.errno in (errno.ENOENT, errno.ENOTDIR):
361 a8083063 Iustin Pop
      return False
362 a8083063 Iustin Pop
363 a8083063 Iustin Pop
  alive = True
364 a8083063 Iustin Pop
  try:
365 a8083063 Iustin Pop
    data = f.readlines()
366 a8083063 Iustin Pop
    if len(data) > 1:
367 a8083063 Iustin Pop
      state = data[1].split()
368 a8083063 Iustin Pop
      if len(state) > 1 and state[1] == "Z":
369 a8083063 Iustin Pop
        alive = False
370 a8083063 Iustin Pop
  finally:
371 a8083063 Iustin Pop
    f.close()
372 a8083063 Iustin Pop
373 a8083063 Iustin Pop
  return alive
374 a8083063 Iustin Pop
375 a8083063 Iustin Pop
376 a8083063 Iustin Pop
def MatchNameComponent(key, name_list):
377 a8083063 Iustin Pop
  """Try to match a name against a list.
378 a8083063 Iustin Pop

379 a8083063 Iustin Pop
  This function will try to match a name like test1 against a list
380 a8083063 Iustin Pop
  like ['test1.example.com', 'test2.example.com', ...]. Against this
381 a8083063 Iustin Pop
  list, 'test1' as well as 'test1.example' will match, but not
382 a8083063 Iustin Pop
  'test1.ex'. A multiple match will be considered as no match at all
383 a8083063 Iustin Pop
  (e.g. 'test1' against ['test1.example.com', 'test1.example.org']).
384 a8083063 Iustin Pop

385 a8083063 Iustin Pop
  Args:
386 a8083063 Iustin Pop
    key: the name to be searched
387 a8083063 Iustin Pop
    name_list: the list of strings against which to search the key
388 a8083063 Iustin Pop

389 a8083063 Iustin Pop
  Returns:
390 a8083063 Iustin Pop
    None if there is no match *or* if there are multiple matches
391 a8083063 Iustin Pop
    otherwise the element from the list which matches
392 a8083063 Iustin Pop

393 a8083063 Iustin Pop
  """
394 a8083063 Iustin Pop
  mo = re.compile("^%s(\..*)?$" % re.escape(key))
395 a8083063 Iustin Pop
  names_filtered = [name for name in name_list if mo.match(name) is not None]
396 a8083063 Iustin Pop
  if len(names_filtered) != 1:
397 a8083063 Iustin Pop
    return None
398 a8083063 Iustin Pop
  return names_filtered[0]
399 a8083063 Iustin Pop
400 a8083063 Iustin Pop
401 bcf043c9 Iustin Pop
class HostInfo:
402 89e1fc26 Iustin Pop
  """Class implementing resolver and hostname functionality
403 bcf043c9 Iustin Pop

404 bcf043c9 Iustin Pop
  """
405 89e1fc26 Iustin Pop
  def __init__(self, name=None):
406 bcf043c9 Iustin Pop
    """Initialize the host name object.
407 bcf043c9 Iustin Pop

408 89e1fc26 Iustin Pop
    If the name argument is not passed, it will use this system's
409 89e1fc26 Iustin Pop
    name.
410 bcf043c9 Iustin Pop

411 bcf043c9 Iustin Pop
    """
412 89e1fc26 Iustin Pop
    if name is None:
413 89e1fc26 Iustin Pop
      name = self.SysName()
414 89e1fc26 Iustin Pop
415 89e1fc26 Iustin Pop
    self.query = name
416 89e1fc26 Iustin Pop
    self.name, self.aliases, self.ipaddrs = self.LookupHostname(name)
417 bcf043c9 Iustin Pop
    self.ip = self.ipaddrs[0]
418 bcf043c9 Iustin Pop
419 89e1fc26 Iustin Pop
  @staticmethod
420 89e1fc26 Iustin Pop
  def SysName():
421 89e1fc26 Iustin Pop
    """Return the current system's name.
422 bcf043c9 Iustin Pop

423 89e1fc26 Iustin Pop
    This is simply a wrapper over socket.gethostname()
424 a8083063 Iustin Pop

425 89e1fc26 Iustin Pop
    """
426 89e1fc26 Iustin Pop
    return socket.gethostname()
427 a8083063 Iustin Pop
428 89e1fc26 Iustin Pop
  @staticmethod
429 89e1fc26 Iustin Pop
  def LookupHostname(hostname):
430 89e1fc26 Iustin Pop
    """Look up hostname
431 a8083063 Iustin Pop

432 89e1fc26 Iustin Pop
    Args:
433 89e1fc26 Iustin Pop
      hostname: hostname to look up
434 89e1fc26 Iustin Pop

435 89e1fc26 Iustin Pop
    Returns:
436 89e1fc26 Iustin Pop
      a tuple (name, aliases, ipaddrs) as returned by socket.gethostbyname_ex
437 89e1fc26 Iustin Pop
      in case of errors in resolving, we raise a ResolverError
438 89e1fc26 Iustin Pop

439 89e1fc26 Iustin Pop
    """
440 89e1fc26 Iustin Pop
    try:
441 89e1fc26 Iustin Pop
      result = socket.gethostbyname_ex(hostname)
442 89e1fc26 Iustin Pop
    except socket.gaierror, err:
443 89e1fc26 Iustin Pop
      # hostname not found in DNS
444 89e1fc26 Iustin Pop
      raise errors.ResolverError(hostname, err.args[0], err.args[1])
445 a8083063 Iustin Pop
446 89e1fc26 Iustin Pop
    return result
447 a8083063 Iustin Pop
448 a8083063 Iustin Pop
449 a8083063 Iustin Pop
def ListVolumeGroups():
450 a8083063 Iustin Pop
  """List volume groups and their size
451 a8083063 Iustin Pop

452 a8083063 Iustin Pop
  Returns:
453 a8083063 Iustin Pop
     Dictionary with keys volume name and values the size of the volume
454 a8083063 Iustin Pop

455 a8083063 Iustin Pop
  """
456 a8083063 Iustin Pop
  command = "vgs --noheadings --units m --nosuffix -o name,size"
457 a8083063 Iustin Pop
  result = RunCmd(command)
458 a8083063 Iustin Pop
  retval = {}
459 a8083063 Iustin Pop
  if result.failed:
460 a8083063 Iustin Pop
    return retval
461 a8083063 Iustin Pop
462 a8083063 Iustin Pop
  for line in result.stdout.splitlines():
463 a8083063 Iustin Pop
    try:
464 a8083063 Iustin Pop
      name, size = line.split()
465 a8083063 Iustin Pop
      size = int(float(size))
466 a8083063 Iustin Pop
    except (IndexError, ValueError), err:
467 a8083063 Iustin Pop
      logger.Error("Invalid output from vgs (%s): %s" % (err, line))
468 a8083063 Iustin Pop
      continue
469 a8083063 Iustin Pop
470 a8083063 Iustin Pop
    retval[name] = size
471 a8083063 Iustin Pop
472 a8083063 Iustin Pop
  return retval
473 a8083063 Iustin Pop
474 a8083063 Iustin Pop
475 a8083063 Iustin Pop
def BridgeExists(bridge):
476 a8083063 Iustin Pop
  """Check whether the given bridge exists in the system
477 a8083063 Iustin Pop

478 a8083063 Iustin Pop
  Returns:
479 a8083063 Iustin Pop
     True if it does, false otherwise.
480 a8083063 Iustin Pop

481 a8083063 Iustin Pop
  """
482 a8083063 Iustin Pop
  return os.path.isdir("/sys/class/net/%s/bridge" % bridge)
483 a8083063 Iustin Pop
484 a8083063 Iustin Pop
485 a8083063 Iustin Pop
def NiceSort(name_list):
486 a8083063 Iustin Pop
  """Sort a list of strings based on digit and non-digit groupings.
487 a8083063 Iustin Pop

488 a8083063 Iustin Pop
  Given a list of names ['a1', 'a10', 'a11', 'a2'] this function will
489 a8083063 Iustin Pop
  sort the list in the logical order ['a1', 'a2', 'a10', 'a11'].
490 a8083063 Iustin Pop

491 a8083063 Iustin Pop
  The sort algorithm breaks each name in groups of either only-digits
492 a8083063 Iustin Pop
  or no-digits. Only the first eight such groups are considered, and
493 a8083063 Iustin Pop
  after that we just use what's left of the string.
494 a8083063 Iustin Pop

495 a8083063 Iustin Pop
  Return value
496 a8083063 Iustin Pop
    - a copy of the list sorted according to our algorithm
497 a8083063 Iustin Pop

498 a8083063 Iustin Pop
  """
499 a8083063 Iustin Pop
  _SORTER_BASE = "(\D+|\d+)"
500 a8083063 Iustin Pop
  _SORTER_FULL = "^%s%s?%s?%s?%s?%s?%s?%s?.*$" % (_SORTER_BASE, _SORTER_BASE,
501 a8083063 Iustin Pop
                                                  _SORTER_BASE, _SORTER_BASE,
502 a8083063 Iustin Pop
                                                  _SORTER_BASE, _SORTER_BASE,
503 a8083063 Iustin Pop
                                                  _SORTER_BASE, _SORTER_BASE)
504 a8083063 Iustin Pop
  _SORTER_RE = re.compile(_SORTER_FULL)
505 a8083063 Iustin Pop
  _SORTER_NODIGIT = re.compile("^\D*$")
506 a8083063 Iustin Pop
  def _TryInt(val):
507 a8083063 Iustin Pop
    """Attempts to convert a variable to integer."""
508 a8083063 Iustin Pop
    if val is None or _SORTER_NODIGIT.match(val):
509 a8083063 Iustin Pop
      return val
510 a8083063 Iustin Pop
    rval = int(val)
511 a8083063 Iustin Pop
    return rval
512 a8083063 Iustin Pop
513 a8083063 Iustin Pop
  to_sort = [([_TryInt(grp) for grp in _SORTER_RE.match(name).groups()], name)
514 a8083063 Iustin Pop
             for name in name_list]
515 a8083063 Iustin Pop
  to_sort.sort()
516 a8083063 Iustin Pop
  return [tup[1] for tup in to_sort]
517 a8083063 Iustin Pop
518 a8083063 Iustin Pop
519 a8083063 Iustin Pop
def CheckDaemonAlive(pid_file, process_string):
520 a8083063 Iustin Pop
  """Check wether the specified daemon is alive.
521 a8083063 Iustin Pop

522 a8083063 Iustin Pop
  Args:
523 a8083063 Iustin Pop
   - pid_file: file to read the daemon pid from, the file is
524 a8083063 Iustin Pop
               expected to contain only a single line containing
525 a8083063 Iustin Pop
               only the PID
526 a8083063 Iustin Pop
   - process_string: a substring that we expect to find in
527 a8083063 Iustin Pop
                     the command line of the daemon process
528 a8083063 Iustin Pop

529 a8083063 Iustin Pop
  Returns:
530 a8083063 Iustin Pop
   - True if the daemon is judged to be alive (that is:
531 a8083063 Iustin Pop
      - the PID file exists, is readable and contains a number
532 a8083063 Iustin Pop
      - a process of the specified PID is running
533 a8083063 Iustin Pop
      - that process contains the specified string in its
534 a8083063 Iustin Pop
        command line
535 a8083063 Iustin Pop
      - the process is not in state Z (zombie))
536 a8083063 Iustin Pop
   - False otherwise
537 a8083063 Iustin Pop

538 a8083063 Iustin Pop
  """
539 a8083063 Iustin Pop
  try:
540 a8083063 Iustin Pop
    pid_file = file(pid_file, 'r')
541 a8083063 Iustin Pop
    try:
542 a8083063 Iustin Pop
      pid = int(pid_file.readline())
543 a8083063 Iustin Pop
    finally:
544 a8083063 Iustin Pop
      pid_file.close()
545 a8083063 Iustin Pop
546 a8083063 Iustin Pop
    cmdline_file_path = "/proc/%s/cmdline" % (pid)
547 a8083063 Iustin Pop
    cmdline_file = open(cmdline_file_path, 'r')
548 a8083063 Iustin Pop
    try:
549 a8083063 Iustin Pop
      cmdline = cmdline_file.readline()
550 a8083063 Iustin Pop
    finally:
551 a8083063 Iustin Pop
      cmdline_file.close()
552 a8083063 Iustin Pop
553 a8083063 Iustin Pop
    if not process_string in cmdline:
554 a8083063 Iustin Pop
      return False
555 a8083063 Iustin Pop
556 a8083063 Iustin Pop
    stat_file_path =  "/proc/%s/stat" % (pid)
557 a8083063 Iustin Pop
    stat_file = open(stat_file_path, 'r')
558 a8083063 Iustin Pop
    try:
559 a8083063 Iustin Pop
      process_state = stat_file.readline().split()[2]
560 a8083063 Iustin Pop
    finally:
561 a8083063 Iustin Pop
      stat_file.close()
562 a8083063 Iustin Pop
563 a8083063 Iustin Pop
    if process_state == 'Z':
564 a8083063 Iustin Pop
      return False
565 a8083063 Iustin Pop
566 a8083063 Iustin Pop
  except (IndexError, IOError, ValueError):
567 a8083063 Iustin Pop
    return False
568 a8083063 Iustin Pop
569 a8083063 Iustin Pop
  return True
570 a8083063 Iustin Pop
571 a8083063 Iustin Pop
572 a8083063 Iustin Pop
def TryConvert(fn, val):
573 a8083063 Iustin Pop
  """Try to convert a value ignoring errors.
574 a8083063 Iustin Pop

575 a8083063 Iustin Pop
  This function tries to apply function `fn` to `val`. If no
576 a8083063 Iustin Pop
  ValueError or TypeError exceptions are raised, it will return the
577 a8083063 Iustin Pop
  result, else it will return the original value. Any other exceptions
578 a8083063 Iustin Pop
  are propagated to the caller.
579 a8083063 Iustin Pop

580 a8083063 Iustin Pop
  """
581 a8083063 Iustin Pop
  try:
582 a8083063 Iustin Pop
    nv = fn(val)
583 a8083063 Iustin Pop
  except (ValueError, TypeError), err:
584 a8083063 Iustin Pop
    nv = val
585 a8083063 Iustin Pop
  return nv
586 a8083063 Iustin Pop
587 a8083063 Iustin Pop
588 a8083063 Iustin Pop
def IsValidIP(ip):
589 a8083063 Iustin Pop
  """Verifies the syntax of an IP address.
590 a8083063 Iustin Pop

591 a8083063 Iustin Pop
  This function checks if the ip address passes is valid or not based
592 a8083063 Iustin Pop
  on syntax (not ip range, class calculations or anything).
593 a8083063 Iustin Pop

594 a8083063 Iustin Pop
  """
595 a8083063 Iustin Pop
  unit = "(0|[1-9]\d{0,2})"
596 a8083063 Iustin Pop
  return re.match("^%s\.%s\.%s\.%s$" % (unit, unit, unit, unit), ip)
597 a8083063 Iustin Pop
598 a8083063 Iustin Pop
599 a8083063 Iustin Pop
def IsValidShellParam(word):
600 a8083063 Iustin Pop
  """Verifies is the given word is safe from the shell's p.o.v.
601 a8083063 Iustin Pop

602 a8083063 Iustin Pop
  This means that we can pass this to a command via the shell and be
603 a8083063 Iustin Pop
  sure that it doesn't alter the command line and is passed as such to
604 a8083063 Iustin Pop
  the actual command.
605 a8083063 Iustin Pop

606 a8083063 Iustin Pop
  Note that we are overly restrictive here, in order to be on the safe
607 a8083063 Iustin Pop
  side.
608 a8083063 Iustin Pop

609 a8083063 Iustin Pop
  """
610 a8083063 Iustin Pop
  return bool(re.match("^[-a-zA-Z0-9._+/:%@]+$", word))
611 a8083063 Iustin Pop
612 a8083063 Iustin Pop
613 a8083063 Iustin Pop
def BuildShellCmd(template, *args):
614 a8083063 Iustin Pop
  """Build a safe shell command line from the given arguments.
615 a8083063 Iustin Pop

616 a8083063 Iustin Pop
  This function will check all arguments in the args list so that they
617 a8083063 Iustin Pop
  are valid shell parameters (i.e. they don't contain shell
618 a8083063 Iustin Pop
  metacharaters). If everything is ok, it will return the result of
619 a8083063 Iustin Pop
  template % args.
620 a8083063 Iustin Pop

621 a8083063 Iustin Pop
  """
622 a8083063 Iustin Pop
  for word in args:
623 a8083063 Iustin Pop
    if not IsValidShellParam(word):
624 3ecf6786 Iustin Pop
      raise errors.ProgrammerError("Shell argument '%s' contains"
625 3ecf6786 Iustin Pop
                                   " invalid characters" % word)
626 a8083063 Iustin Pop
  return template % args
627 a8083063 Iustin Pop
628 a8083063 Iustin Pop
629 a8083063 Iustin Pop
def FormatUnit(value):
630 a8083063 Iustin Pop
  """Formats an incoming number of MiB with the appropriate unit.
631 a8083063 Iustin Pop

632 a8083063 Iustin Pop
  Value needs to be passed as a numeric type. Return value is always a string.
633 a8083063 Iustin Pop

634 a8083063 Iustin Pop
  """
635 a8083063 Iustin Pop
  if value < 1024:
636 a8083063 Iustin Pop
    return "%dM" % round(value, 0)
637 a8083063 Iustin Pop
638 a8083063 Iustin Pop
  elif value < (1024 * 1024):
639 a8083063 Iustin Pop
    return "%0.1fG" % round(float(value) / 1024, 1)
640 a8083063 Iustin Pop
641 a8083063 Iustin Pop
  else:
642 a8083063 Iustin Pop
    return "%0.1fT" % round(float(value) / 1024 / 1024, 1)
643 a8083063 Iustin Pop
644 a8083063 Iustin Pop
645 a8083063 Iustin Pop
def ParseUnit(input_string):
646 a8083063 Iustin Pop
  """Tries to extract number and scale from the given string.
647 a8083063 Iustin Pop

648 a8083063 Iustin Pop
  Input must be in the format NUMBER+ [DOT NUMBER+] SPACE* [UNIT]. If no unit
649 a8083063 Iustin Pop
  is specified, it defaults to MiB. Return value is always an int in MiB.
650 a8083063 Iustin Pop

651 a8083063 Iustin Pop
  """
652 a8083063 Iustin Pop
  m = re.match('^([.\d]+)\s*([a-zA-Z]+)?$', input_string)
653 a8083063 Iustin Pop
  if not m:
654 3ecf6786 Iustin Pop
    raise errors.UnitParseError("Invalid format")
655 a8083063 Iustin Pop
656 a8083063 Iustin Pop
  value = float(m.groups()[0])
657 a8083063 Iustin Pop
658 a8083063 Iustin Pop
  unit = m.groups()[1]
659 a8083063 Iustin Pop
  if unit:
660 a8083063 Iustin Pop
    lcunit = unit.lower()
661 a8083063 Iustin Pop
  else:
662 a8083063 Iustin Pop
    lcunit = 'm'
663 a8083063 Iustin Pop
664 a8083063 Iustin Pop
  if lcunit in ('m', 'mb', 'mib'):
665 a8083063 Iustin Pop
    # Value already in MiB
666 a8083063 Iustin Pop
    pass
667 a8083063 Iustin Pop
668 a8083063 Iustin Pop
  elif lcunit in ('g', 'gb', 'gib'):
669 a8083063 Iustin Pop
    value *= 1024
670 a8083063 Iustin Pop
671 a8083063 Iustin Pop
  elif lcunit in ('t', 'tb', 'tib'):
672 a8083063 Iustin Pop
    value *= 1024 * 1024
673 a8083063 Iustin Pop
674 a8083063 Iustin Pop
  else:
675 3ecf6786 Iustin Pop
    raise errors.UnitParseError("Unknown unit: %s" % unit)
676 a8083063 Iustin Pop
677 a8083063 Iustin Pop
  # Make sure we round up
678 a8083063 Iustin Pop
  if int(value) < value:
679 a8083063 Iustin Pop
    value += 1
680 a8083063 Iustin Pop
681 a8083063 Iustin Pop
  # Round up to the next multiple of 4
682 a8083063 Iustin Pop
  value = int(value)
683 a8083063 Iustin Pop
  if value % 4:
684 a8083063 Iustin Pop
    value += 4 - value % 4
685 a8083063 Iustin Pop
686 a8083063 Iustin Pop
  return value
687 a8083063 Iustin Pop
688 a8083063 Iustin Pop
689 a8083063 Iustin Pop
def AddAuthorizedKey(file_name, key):
690 a8083063 Iustin Pop
  """Adds an SSH public key to an authorized_keys file.
691 a8083063 Iustin Pop

692 a8083063 Iustin Pop
  Args:
693 a8083063 Iustin Pop
    file_name: Path to authorized_keys file
694 a8083063 Iustin Pop
    key: String containing key
695 a8083063 Iustin Pop
  """
696 a8083063 Iustin Pop
  key_fields = key.split()
697 a8083063 Iustin Pop
698 a8083063 Iustin Pop
  f = open(file_name, 'a+')
699 a8083063 Iustin Pop
  try:
700 a8083063 Iustin Pop
    nl = True
701 a8083063 Iustin Pop
    for line in f:
702 a8083063 Iustin Pop
      # Ignore whitespace changes
703 a8083063 Iustin Pop
      if line.split() == key_fields:
704 a8083063 Iustin Pop
        break
705 a8083063 Iustin Pop
      nl = line.endswith('\n')
706 a8083063 Iustin Pop
    else:
707 a8083063 Iustin Pop
      if not nl:
708 a8083063 Iustin Pop
        f.write("\n")
709 a8083063 Iustin Pop
      f.write(key.rstrip('\r\n'))
710 a8083063 Iustin Pop
      f.write("\n")
711 a8083063 Iustin Pop
      f.flush()
712 a8083063 Iustin Pop
  finally:
713 a8083063 Iustin Pop
    f.close()
714 a8083063 Iustin Pop
715 a8083063 Iustin Pop
716 a8083063 Iustin Pop
def RemoveAuthorizedKey(file_name, key):
717 a8083063 Iustin Pop
  """Removes an SSH public key from an authorized_keys file.
718 a8083063 Iustin Pop

719 a8083063 Iustin Pop
  Args:
720 a8083063 Iustin Pop
    file_name: Path to authorized_keys file
721 a8083063 Iustin Pop
    key: String containing key
722 a8083063 Iustin Pop
  """
723 a8083063 Iustin Pop
  key_fields = key.split()
724 a8083063 Iustin Pop
725 a8083063 Iustin Pop
  fd, tmpname = tempfile.mkstemp(dir=os.path.dirname(file_name))
726 a8083063 Iustin Pop
  out = os.fdopen(fd, 'w')
727 a8083063 Iustin Pop
  try:
728 a8083063 Iustin Pop
    f = open(file_name, 'r')
729 a8083063 Iustin Pop
    try:
730 a8083063 Iustin Pop
      for line in f:
731 a8083063 Iustin Pop
        # Ignore whitespace changes while comparing lines
732 a8083063 Iustin Pop
        if line.split() != key_fields:
733 a8083063 Iustin Pop
          out.write(line)
734 a8083063 Iustin Pop
735 a8083063 Iustin Pop
      out.flush()
736 a8083063 Iustin Pop
      os.rename(tmpname, file_name)
737 a8083063 Iustin Pop
    finally:
738 a8083063 Iustin Pop
      f.close()
739 a8083063 Iustin Pop
  finally:
740 a8083063 Iustin Pop
    out.close()
741 a8083063 Iustin Pop
742 a8083063 Iustin Pop
743 a8083063 Iustin Pop
def CreateBackup(file_name):
744 a8083063 Iustin Pop
  """Creates a backup of a file.
745 a8083063 Iustin Pop

746 a8083063 Iustin Pop
  Returns: the path to the newly created backup file.
747 a8083063 Iustin Pop

748 a8083063 Iustin Pop
  """
749 a8083063 Iustin Pop
  if not os.path.isfile(file_name):
750 3ecf6786 Iustin Pop
    raise errors.ProgrammerError("Can't make a backup of a non-file '%s'" %
751 3ecf6786 Iustin Pop
                                file_name)
752 a8083063 Iustin Pop
753 081b1e69 Michael Hanselmann
  prefix = '%s.backup-%d.' % (os.path.basename(file_name), int(time.time()))
754 081b1e69 Michael Hanselmann
  dir = os.path.dirname(file_name)
755 081b1e69 Michael Hanselmann
756 081b1e69 Michael Hanselmann
  fsrc = open(file_name, 'rb')
757 081b1e69 Michael Hanselmann
  try:
758 081b1e69 Michael Hanselmann
    (fd, backup_name) = tempfile.mkstemp(prefix=prefix, dir=dir)
759 081b1e69 Michael Hanselmann
    fdst = os.fdopen(fd, 'wb')
760 081b1e69 Michael Hanselmann
    try:
761 081b1e69 Michael Hanselmann
      shutil.copyfileobj(fsrc, fdst)
762 081b1e69 Michael Hanselmann
    finally:
763 081b1e69 Michael Hanselmann
      fdst.close()
764 081b1e69 Michael Hanselmann
  finally:
765 081b1e69 Michael Hanselmann
    fsrc.close()
766 081b1e69 Michael Hanselmann
767 a8083063 Iustin Pop
  return backup_name
768 a8083063 Iustin Pop
769 a8083063 Iustin Pop
770 a8083063 Iustin Pop
def ShellQuote(value):
771 a8083063 Iustin Pop
  """Quotes shell argument according to POSIX.
772 3ecf6786 Iustin Pop

773 a8083063 Iustin Pop
  """
774 a8083063 Iustin Pop
  if _re_shell_unquoted.match(value):
775 a8083063 Iustin Pop
    return value
776 a8083063 Iustin Pop
  else:
777 a8083063 Iustin Pop
    return "'%s'" % value.replace("'", "'\\''")
778 a8083063 Iustin Pop
779 a8083063 Iustin Pop
780 a8083063 Iustin Pop
def ShellQuoteArgs(args):
781 a8083063 Iustin Pop
  """Quotes all given shell arguments and concatenates using spaces.
782 a8083063 Iustin Pop

783 a8083063 Iustin Pop
  """
784 a8083063 Iustin Pop
  return ' '.join([ShellQuote(i) for i in args])
785 88d14415 Michael Hanselmann
786 88d14415 Michael Hanselmann
787 2c30e9d7 Alexander Schreiber
788 16abfbc2 Alexander Schreiber
def TcpPing(source, target, port, timeout=10, live_port_needed=False):
789 2c30e9d7 Alexander Schreiber
  """Simple ping implementation using TCP connect(2).
790 2c30e9d7 Alexander Schreiber

791 2c30e9d7 Alexander Schreiber
  Try to do a TCP connect(2) from the specified source IP to the specified
792 2c30e9d7 Alexander Schreiber
  target IP and the specified target port. If live_port_needed is set to true,
793 2c30e9d7 Alexander Schreiber
  requires the remote end to accept the connection. The timeout is specified
794 2c30e9d7 Alexander Schreiber
  in seconds and defaults to 10 seconds
795 2c30e9d7 Alexander Schreiber

796 2c30e9d7 Alexander Schreiber
  """
797 2c30e9d7 Alexander Schreiber
  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
798 2c30e9d7 Alexander Schreiber
799 2c30e9d7 Alexander Schreiber
  sucess = False
800 2c30e9d7 Alexander Schreiber
801 2c30e9d7 Alexander Schreiber
  try:
802 2c30e9d7 Alexander Schreiber
    sock.bind((source, 0))
803 2c30e9d7 Alexander Schreiber
  except socket.error, (errcode, errstring):
804 4ca1b175 Alexander Schreiber
    if errcode == errno.EADDRNOTAVAIL:
805 2c30e9d7 Alexander Schreiber
      success = False
806 2c30e9d7 Alexander Schreiber
807 2c30e9d7 Alexander Schreiber
  sock.settimeout(timeout)
808 2c30e9d7 Alexander Schreiber
809 2c30e9d7 Alexander Schreiber
  try:
810 2c30e9d7 Alexander Schreiber
    sock.connect((target, port))
811 2c30e9d7 Alexander Schreiber
    sock.close()
812 2c30e9d7 Alexander Schreiber
    success = True
813 2c30e9d7 Alexander Schreiber
  except socket.timeout:
814 2c30e9d7 Alexander Schreiber
    success = False
815 2c30e9d7 Alexander Schreiber
  except socket.error, (errcode, errstring):
816 4ca1b175 Alexander Schreiber
    success = (not live_port_needed) and (errcode == errno.ECONNREFUSED)
817 2c30e9d7 Alexander Schreiber
818 2c30e9d7 Alexander Schreiber
  return success
819 eedbda4b Michael Hanselmann
820 eedbda4b Michael Hanselmann
821 eedbda4b Michael Hanselmann
def ListVisibleFiles(path):
822 eedbda4b Michael Hanselmann
  """Returns a list of all visible files in a directory.
823 eedbda4b Michael Hanselmann

824 eedbda4b Michael Hanselmann
  """
825 eedbda4b Michael Hanselmann
  return [i for i in os.listdir(path) if not i.startswith(".")]
826 2f8b60b3 Iustin Pop
827 2f8b60b3 Iustin Pop
828 2f8b60b3 Iustin Pop
def GetHomeDir(uid, default=None):
829 2f8b60b3 Iustin Pop
  """Try to get the homedir of the given user id.
830 2f8b60b3 Iustin Pop

831 2f8b60b3 Iustin Pop
  """
832 2f8b60b3 Iustin Pop
  try:
833 2f8b60b3 Iustin Pop
    result = pwd.getpwuid(uid)
834 2f8b60b3 Iustin Pop
  except KeyError:
835 2f8b60b3 Iustin Pop
    return default
836 2f8b60b3 Iustin Pop
  return result.pw_dir