"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-8.2/extras/snap_scheduler/gcron.py" (16 Sep 2020, 6564 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 "gcron.py" see the Fossies "Dox" file reference documentation.

    1 #!/usr/bin/python3
    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 from __future__ import print_function
   12 import subprocess
   13 import os
   14 import os.path
   15 import sys
   16 import time
   17 import logging
   18 import logging.handlers
   19 import fcntl
   20 
   21 
   22 GCRON_TASKS = "/var/run/gluster/shared_storage/snaps/glusterfs_snap_cron_tasks"
   23 GCRON_CROND_TASK = "/etc/cron.d/glusterfs_snap_cron_tasks"
   24 GCRON_RELOAD_FLAG = "/var/run/gluster/crond_task_reload_flag"
   25 LOCK_FILE_DIR = "/var/run/gluster/shared_storage/snaps/lock_files/"
   26 log = logging.getLogger("gcron-logger")
   27 start_time = 0.0
   28 
   29 
   30 def initLogger(script_name):
   31     log.setLevel(logging.DEBUG)
   32     logFormat = "[%(asctime)s %(filename)s:%(lineno)s %(funcName)s] "\
   33         "%(levelname)s %(message)s"
   34     formatter = logging.Formatter(logFormat)
   35 
   36     sh = logging.handlers.SysLogHandler()
   37     sh.setLevel(logging.ERROR)
   38     sh.setFormatter(formatter)
   39 
   40     process = subprocess.Popen(["gluster", "--print-logdir"],
   41                                stdout=subprocess.PIPE)
   42     out, err = process.communicate()
   43     if process.returncode == 0:
   44         logfile = os.path.join(out.strip(), script_name[:-3]+".log")
   45 
   46     fh = logging.FileHandler(logfile)
   47     fh.setLevel(logging.DEBUG)
   48     fh.setFormatter(formatter)
   49 
   50     log.addHandler(sh)
   51     log.addHandler(fh)
   52 
   53 
   54 def takeSnap(volname="", snapname=""):
   55     success = True
   56     if volname == "":
   57         log.debug("No volname given")
   58         return False
   59     if snapname == "":
   60         log.debug("No snapname given")
   61         return False
   62 
   63     cli = ["gluster",
   64            "snapshot",
   65            "create",
   66            snapname,
   67            volname]
   68     log.debug("Running command '%s'", " ".join(cli))
   69 
   70     p = subprocess.Popen(cli, stdout=subprocess.PIPE,
   71                          stderr=subprocess.PIPE)
   72     out, err = p.communicate()
   73     rv = p.returncode
   74 
   75     log.debug("Command '%s' returned '%d'", " ".join(cli), rv)
   76 
   77     if rv:
   78         log.error("Snapshot of %s failed", volname)
   79         log.error("Command output:")
   80         log.error(err)
   81         success = False
   82     else:
   83         log.info("Snapshot of %s successful", volname)
   84 
   85     return success
   86 
   87 
   88 def doJob(name, lockFile, jobFunc, volname):
   89     success = True
   90     try:
   91         f = os.open(lockFile, os.O_CREAT | os.O_RDWR | os.O_NONBLOCK)
   92         try:
   93             fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
   94             mtime = os.path.getmtime(lockFile)
   95             global start_time
   96             log.debug("%s last modified at %s", lockFile, time.ctime(mtime))
   97             if mtime < start_time:
   98                 log.debug("Processing job %s", name)
   99                 if jobFunc(volname, name):
  100                     log.info("Job %s succeeded", name)
  101                 else:
  102                     log.error("Job %s failed", name)
  103                     success = False
  104                 os.utime(lockFile, None)
  105             else:
  106                 log.info("Job %s has been processed already", name)
  107             fcntl.flock(f, fcntl.LOCK_UN)
  108         except (OSError, IOError):
  109             log.info("Job %s is being processed by another agent", name)
  110         os.close(f)
  111     except (OSError, IOError) as e:
  112         log.debug("Failed to open lock file %s : %s", lockFile, e)
  113         log.error("Failed to process job %s", name)
  114         success = False
  115 
  116     return success
  117 
  118 
  119 def main():
  120     script_name = os.path.basename(__file__)
  121     initLogger(script_name)
  122     global start_time
  123     if sys.argv[1] == "--update":
  124         if not os.path.exists(GCRON_TASKS):
  125             # Create a flag in /var/run/gluster which indicates that this
  126             # node doesn't have access to GCRON_TASKS right now, so that
  127             # when the mount is available and GCRON_TASKS is available
  128             # the flag will tell this routine to reload GCRON_CROND_TASK
  129             try:
  130                 f = os.open(GCRON_RELOAD_FLAG,
  131                             os.O_CREAT | os.O_NONBLOCK, 0o644)
  132                 os.close(f)
  133             except OSError as e:
  134                 if errno != EEXIST:
  135                     log.error("Failed to create %s : %s",
  136                               GCRON_RELOAD_FLAG, e)
  137                     output("Failed to create %s. Error: %s"
  138                            % (GCRON_RELOAD_FLAG, e))
  139             return
  140 
  141         if not os.path.exists(GCRON_CROND_TASK):
  142             return
  143 
  144         # As GCRON_TASKS exists now, we should check if GCRON_RELOAD_FLAG
  145         # also exists. If so we should touch GCRON_CROND_TASK and remove
  146         # the GCRON_RELOAD_FLAG
  147         if os.path.exists(GCRON_RELOAD_FLAG):
  148             try:
  149                 os.remove(GCRON_RELOAD_FLAG);
  150                 process = subprocess.Popen(["touch", "-h", GCRON_CROND_TASK],
  151                                            stdout=subprocess.PIPE,
  152                                            stderr=subprocess.PIPE)
  153                 out, err = process.communicate()
  154                 if process.returncode != 0:
  155                     log.error("Failed to touch %s. Error: %s.",
  156                               GCRON_CROND_TASK, err)
  157             except (IOError, OSError) as e:
  158                 log.error("Failed to touch %s. Error: %s.",
  159                           GCRON_CROND_TASK, e)
  160             return
  161         if os.lstat(GCRON_TASKS).st_mtime > \
  162            os.lstat(GCRON_CROND_TASK).st_mtime:
  163             try:
  164                 process = subprocess.Popen(["touch", "-h", GCRON_CROND_TASK],
  165                                            stdout=subprocess.PIPE,
  166                                            stderr=subprocess.PIPE)
  167                 out, err = process.communicate()
  168                 if process.returncode != 0:
  169                     log.error("Failed to touch %s. Error: %s.",
  170                               GCRON_CROND_TASK, err)
  171             except IOError as e:
  172                 log.error("Failed to touch %s. Error: %s.",
  173                           GCRON_CROND_TASK, e)
  174         return
  175 
  176     volname = sys.argv[1]
  177     jobname = sys.argv[2]
  178     locking_file = os.path.join(LOCK_FILE_DIR, jobname)
  179     log.debug("locking_file = %s", locking_file)
  180     log.debug("volname = %s", volname)
  181     log.debug("jobname = %s", jobname)
  182 
  183     start_time = int(time.time())
  184 
  185     doJob("Scheduled-" + jobname + "-" + volname, locking_file, takeSnap, volname)
  186 
  187 
  188 if __name__ == "__main__":
  189     main()