"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-8.2/tools/glusterfind/src/utils.py" (16 Sep 2020, 7248 Bytes) of package /linux/misc/glusterfs-8.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "utils.py" see the Fossies "Dox" file reference documentation.

    1 # -*- coding: utf-8 -*-
    2 
    3 # Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com/>
    4 # This file is part of GlusterFS.
    5 #
    6 # This file is licensed to you under your choice of the GNU Lesser
    7 # General Public License, version 3 or any later version (LGPLv3 or
    8 # later), or the GNU General Public License, version 2 (GPLv2), in all
    9 # cases as published by the Free Software Foundation.
   10 
   11 import sys
   12 from subprocess import PIPE, Popen
   13 from errno import EEXIST, ENOENT
   14 import xml.etree.cElementTree as etree
   15 import logging
   16 import os
   17 from datetime import datetime
   18 
   19 ROOT_GFID = "00000000-0000-0000-0000-000000000001"
   20 DEFAULT_CHANGELOG_INTERVAL = 15
   21 SPACE_ESCAPE_CHAR = "%20"
   22 NEWLINE_ESCAPE_CHAR = "%0A"
   23 PERCENTAGE_ESCAPE_CHAR = "%25"
   24 
   25 ParseError = etree.ParseError if hasattr(etree, 'ParseError') else SyntaxError
   26 cache_data = {}
   27 
   28 
   29 class RecordType(object):
   30     NEW = "NEW"
   31     MODIFY = "MODIFY"
   32     RENAME = "RENAME"
   33     DELETE = "DELETE"
   34 
   35 
   36 def cache_output(func):
   37     def wrapper(*args, **kwargs):
   38         global cache_data
   39         if cache_data.get(func.__name__, None) is None:
   40             cache_data[func.__name__] = func(*args, **kwargs)
   41 
   42         return cache_data[func.__name__]
   43     return wrapper
   44 
   45 
   46 def handle_rm_error(func, path, exc_info):
   47     if exc_info[1].errno == ENOENT:
   48         return
   49 
   50     raise exc_info[1]
   51 
   52 
   53 def find(path, callback_func=lambda x: True, filter_func=lambda x: True,
   54          ignore_dirs=[], subdirs_crawl=True):
   55     if path in ignore_dirs:
   56         return
   57 
   58     # Capture filter_func output and pass it to callback function
   59     filter_result = filter_func(path)
   60     if filter_result is not None:
   61         callback_func(path, filter_result, os.path.isdir(path))
   62 
   63     for p in os.listdir(path):
   64         full_path = os.path.join(path, p)
   65 
   66         is_dir = os.path.isdir(full_path)
   67         if is_dir:
   68             if subdirs_crawl:
   69                 find(full_path, callback_func, filter_func, ignore_dirs)
   70             else:
   71                 filter_result = filter_func(full_path)
   72                 if filter_result is not None:
   73                     callback_func(full_path, filter_result)
   74         else:
   75             filter_result = filter_func(full_path)
   76             if filter_result is not None:
   77                 callback_func(full_path, filter_result, is_dir)
   78 
   79 
   80 def output_write(f, path, prefix=".", encode=False, tag="",
   81                  field_separator=" "):
   82     if path == "":
   83         return
   84 
   85     if prefix != ".":
   86         path = os.path.join(prefix, path)
   87 
   88     if encode:
   89         path = quote_plus_space_newline(path)
   90 
   91     # set the field separator
   92     FS = "" if tag == "" else field_separator
   93 
   94     f.write("%s%s%s\n" % (tag.strip(), FS, path))
   95 
   96 
   97 def human_time(ts):
   98     return datetime.fromtimestamp(float(ts)).strftime("%Y-%m-%d %H:%M:%S")
   99 
  100 
  101 def setup_logger(logger, path, debug=False):
  102     if debug:
  103         logger.setLevel(logging.DEBUG)
  104     else:
  105         logger.setLevel(logging.INFO)
  106 
  107     # create the logging file handler
  108     fh = logging.FileHandler(path)
  109 
  110     formatter = logging.Formatter("[%(asctime)s] %(levelname)s "
  111                                   "[%(module)s - %(lineno)s:%(funcName)s] "
  112                                   "- %(message)s")
  113 
  114     fh.setFormatter(formatter)
  115 
  116     # add handler to logger object
  117     logger.addHandler(fh)
  118 
  119 
  120 def create_file(path, exit_on_err=False, logger=None):
  121     """
  122     If file exists overwrite. Print error to stderr and exit
  123     if exit_on_err is set, else raise the exception. Consumer
  124     should handle the exception.
  125     """
  126     try:
  127         open(path, 'w').close()
  128     except (OSError, IOError) as e:
  129         if exit_on_err:
  130             fail("Failed to create file %s: %s" % (path, e), logger=logger)
  131         else:
  132             raise
  133 
  134 
  135 def mkdirp(path, exit_on_err=False, logger=None):
  136     """
  137     Try creating required directory structure
  138     ignore EEXIST and raise exception for rest of the errors.
  139     Print error in stderr and exit if exit_on_err is set, else
  140     raise exception.
  141     """
  142     try:
  143         os.makedirs(path)
  144     except (OSError, IOError) as e:
  145         if e.errno == EEXIST and os.path.isdir(path):
  146             pass
  147         else:
  148             if exit_on_err:
  149                 fail("Fail to create dir %s: %s" % (path, e), logger=logger)
  150             else:
  151                 raise
  152 
  153 
  154 def fail(msg, code=1, logger=None):
  155     """
  156     Write error to stderr and exit
  157     """
  158     if logger:
  159         logger.error(msg)
  160     sys.stderr.write("%s\n" % msg)
  161     sys.exit(code)
  162 
  163 
  164 def execute(cmd, exit_msg=None, logger=None):
  165     """
  166     If failure_msg is not None then return returncode, out and error.
  167     If failure msg is set, write to stderr and exit.
  168     """
  169     p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
  170 
  171     (out, err) = p.communicate()
  172     if p.returncode != 0 and exit_msg is not None:
  173         fail("%s: %s" % (exit_msg, err), p.returncode, logger=logger)
  174 
  175     return (p.returncode, out, err)
  176 
  177 
  178 def symlink_gfid_to_path(brick, gfid):
  179     """
  180     Each directories are symlinked to file named GFID
  181     in .glusterfs directory of brick backend. Using readlink
  182     we get PARGFID/basename of dir. readlink recursively till
  183     we get PARGFID as ROOT_GFID.
  184     """
  185     if gfid == ROOT_GFID:
  186         return ""
  187 
  188     out_path = ""
  189     while True:
  190         path = os.path.join(brick, ".glusterfs", gfid[0:2], gfid[2:4], gfid)
  191         path_readlink = os.readlink(path)
  192         pgfid = os.path.dirname(path_readlink)
  193         out_path = os.path.join(os.path.basename(path_readlink), out_path)
  194         if pgfid == "../../00/00/%s" % ROOT_GFID:
  195             break
  196         gfid = os.path.basename(pgfid)
  197     return out_path
  198 
  199 
  200 @cache_output
  201 def get_my_uuid():
  202     cmd = ["gluster", "system::", "uuid", "get", "--xml"]
  203     rc, out, err = execute(cmd)
  204 
  205     if rc != 0:
  206         return None
  207 
  208     tree = etree.fromstring(out)
  209     uuid_el = tree.find("uuidGenerate/uuid")
  210     return uuid_el.text
  211 
  212 
  213 def is_host_local(host_uuid):
  214     # Get UUID only if it is not done previously
  215     # else Cache the UUID value
  216     my_uuid = get_my_uuid()
  217     if my_uuid == host_uuid:
  218         return True
  219 
  220     return False
  221 
  222 
  223 def get_changelog_rollover_time(volumename):
  224     cmd = ["gluster", "volume", "get", volumename,
  225            "changelog.rollover-time", "--xml"]
  226     rc, out, err = execute(cmd)
  227 
  228     if rc != 0:
  229         return DEFAULT_CHANGELOG_INTERVAL
  230 
  231     try:
  232         tree = etree.fromstring(out)
  233         return int(tree.find('volGetopts/Opt/Value').text)
  234     except ParseError:
  235         return DEFAULT_CHANGELOG_INTERVAL
  236 
  237 
  238 def output_path_prepare(path, args):
  239     """
  240     If Prefix is set, joins to Path, removes ending slash
  241     and encodes it.
  242     """
  243     if args.output_prefix != ".":
  244         path = os.path.join(args.output_prefix, path)
  245         if path.endswith("/"):
  246             path = path[0:len(path)-1]
  247 
  248     if args.no_encode:
  249         return path
  250     else:
  251         return quote_plus_space_newline(path)
  252 
  253 
  254 def unquote_plus_space_newline(s):
  255     return s.replace(SPACE_ESCAPE_CHAR, " ")\
  256             .replace(NEWLINE_ESCAPE_CHAR, "\n")\
  257             .replace(PERCENTAGE_ESCAPE_CHAR, "%")
  258 
  259 
  260 def quote_plus_space_newline(s):
  261     return s.replace("%", PERCENTAGE_ESCAPE_CHAR)\
  262             .replace(" ", SPACE_ESCAPE_CHAR)\
  263             .replace("\n", NEWLINE_ESCAPE_CHAR)