X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/9b97774028b1a6fb9f3d388ec761af5882cfce4f..dd7db36058e0e645c634402fe9c26cee69eef753:/lib/utils.py?ds=inline diff --git a/lib/utils.py b/lib/utils.py index 8bd1000..48388ba 100644 --- a/lib/utils.py +++ b/lib/utils.py @@ -29,7 +29,6 @@ the command line scripts. import sys import os -import sha import time import subprocess import re @@ -47,6 +46,12 @@ import signal from cStringIO import StringIO +try: + from hashlib import sha1 +except ImportError: + import sha + sha1 = sha.new + from ganeti import errors from ganeti import constants @@ -151,11 +156,18 @@ def RunCmd(cmd, env=None, output=None, cwd='/'): if env is not None: cmd_env.update(env) - if output is None: - out, err, status = _RunCmdPipe(cmd, cmd_env, shell, cwd) - else: - status = _RunCmdFile(cmd, cmd_env, shell, output, cwd) - out = err = "" + try: + if output is None: + out, err, status = _RunCmdPipe(cmd, cmd_env, shell, cwd) + else: + status = _RunCmdFile(cmd, cmd_env, shell, output, cwd) + out = err = "" + except OSError, err: + if err.errno == errno.ENOENT: + raise errors.OpExecError("Can't execute '%s': not found (%s)" % + (strcmd, err)) + else: + raise if status >= 0: exitcode = status @@ -330,7 +342,7 @@ def _FingerprintFile(filename): f = open(filename) - fp = sha.sha() + fp = sha1() while True: data = f.read(4096) if not data: @@ -1179,7 +1191,25 @@ def GenerateSecret(): @return: a sha1 hexdigest of a block of 64 random bytes """ - return sha.new(os.urandom(64)).hexdigest() + return sha1(os.urandom(64)).hexdigest() + + +def EnsureDirs(dirs): + """Make required directories, if they don't exist. + + @param dirs: list of tuples (dir_name, dir_mode) + @type dirs: list of (string, integer) + + """ + for dir_name, dir_mode in dirs: + try: + os.mkdir(dir_name, dir_mode) + except EnvironmentError, err: + if err.errno != errno.EEXIST: + raise errors.GenericError("Cannot create needed directory" + " '%s': %s" % (dir_name, err)) + if not os.path.isdir(dir_name): + raise errors.GenericError("%s is not a directory" % dir_name) def ReadFile(file_name, size=None): @@ -1215,7 +1245,7 @@ def WriteFile(file_name, fn=None, data=None, mtime/atime of the file. If the function doesn't raise an exception, it has succeeded and the - target file has the new contents. If the file has raised an + target file has the new contents. If the function has raised an exception, an existing target file should be unmodified and the temporary file should be removed. @@ -1224,7 +1254,7 @@ def WriteFile(file_name, fn=None, data=None, @type fn: callable @param fn: content writing function, called with file descriptor as parameter - @type data: sr + @type data: str @param data: contents of the file @type mode: int @param mode: file mode @@ -1247,7 +1277,7 @@ def WriteFile(file_name, fn=None, data=None, @return: None if the 'close' parameter evaluates to True, otherwise the file descriptor - @raise errors.ProgrammerError: if an of the arguments are not valid + @raise errors.ProgrammerError: if any of the arguments are not valid """ if not os.path.isabs(file_name): @@ -1266,6 +1296,7 @@ def WriteFile(file_name, fn=None, data=None, dir_name, base_name = os.path.split(file_name) fd, new_name = tempfile.mkstemp('.new', base_name, dir_name) + do_remove = True # here we need to make sure we remove the temp file, if any error # leaves it in place try: @@ -1286,13 +1317,15 @@ def WriteFile(file_name, fn=None, data=None, os.utime(new_name, (atime, mtime)) if not dry_run: os.rename(new_name, file_name) + do_remove = False finally: if close: os.close(fd) result = None else: result = fd - RemoveFile(new_name) + if do_remove: + RemoveFile(new_name) return result @@ -1446,7 +1479,7 @@ def Daemonize(logfile): @type logfile: str @param logfile: the logfile to which we should redirect stdout/stderr @rtype: int - @returns: the value zero + @return: the value zero """ UMASK = 077 @@ -1752,6 +1785,13 @@ def SetupLogging(logfile, debug=False, stderr_logging=False, program="", # we need to re-raise the exception raise +def IsNormAbsPath(path): + """Check whether a path is absolute and also normalized + + This avoids things like /dir/../../other/path to be valid. + + """ + return os.path.normpath(path) == path and os.path.isabs(path) def TailFile(fname, lines=20): """Return the last lines from a file. @@ -1800,6 +1840,16 @@ def SafeEncode(text): return text +def CommaJoin(names): + """Nicely join a set of identifiers. + + @param names: set, list or tuple + @return: a string with the formatted results + + """ + return ", ".join(["'%s'" % val for val in names]) + + def LockedMethod(fn): """Synchronized object access decorator.