glusterfs

Форк
0
190 строк · 6.5 Кб
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 = "/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 = "/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
                               universal_newlines=True)
43
    out, err = process.communicate()
44
    if process.returncode == 0:
45
        logfile = os.path.join(out.strip(), script_name[:-3]+".log")
46

47
    fh = logging.FileHandler(logfile)
48
    fh.setLevel(logging.DEBUG)
49
    fh.setFormatter(formatter)
50

51
    log.addHandler(sh)
52
    log.addHandler(fh)
53

54

55
def takeSnap(volname="", snapname=""):
56
    success = True
57
    if volname == "":
58
        log.debug("No volname given")
59
        return False
60
    if snapname == "":
61
        log.debug("No snapname given")
62
        return False
63

64
    cli = ["gluster",
65
           "snapshot",
66
           "create",
67
           snapname,
68
           volname]
69
    log.debug("Running command '%s'", " ".join(cli))
70

71
    p = subprocess.Popen(cli, stdout=subprocess.PIPE,
72
                         stderr=subprocess.PIPE)
73
    out, err = p.communicate()
74
    rv = p.returncode
75

76
    log.debug("Command '%s' returned '%d'", " ".join(cli), rv)
77

78
    if rv:
79
        log.error("Snapshot of %s failed", volname)
80
        log.error("Command output:")
81
        log.error(err)
82
        success = False
83
    else:
84
        log.info("Snapshot of %s successful", volname)
85

86
    return success
87

88

89
def doJob(name, lockFile, jobFunc, volname):
90
    success = True
91
    try:
92
        f = os.open(lockFile, os.O_CREAT | os.O_RDWR | os.O_NONBLOCK)
93
        try:
94
            fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
95
            mtime = os.path.getmtime(lockFile)
96
            global start_time
97
            log.debug("%s last modified at %s", lockFile, time.ctime(mtime))
98
            if mtime < start_time:
99
                log.debug("Processing job %s", name)
100
                if jobFunc(volname, name):
101
                    log.info("Job %s succeeded", name)
102
                else:
103
                    log.error("Job %s failed", name)
104
                    success = False
105
                os.utime(lockFile, None)
106
            else:
107
                log.info("Job %s has been processed already", name)
108
            fcntl.flock(f, fcntl.LOCK_UN)
109
        except (OSError, IOError):
110
            log.info("Job %s is being processed by another agent", name)
111
        os.close(f)
112
    except (OSError, IOError) as e:
113
        log.debug("Failed to open lock file %s : %s", lockFile, e)
114
        log.error("Failed to process job %s", name)
115
        success = False
116

117
    return success
118

119

120
def main():
121
    script_name = os.path.basename(__file__)
122
    initLogger(script_name)
123
    global start_time
124
    if sys.argv[1] == "--update":
125
        if not os.path.exists(GCRON_TASKS):
126
            # Create a flag in /var/run/gluster which indicates that this
127
            # node doesn't have access to GCRON_TASKS right now, so that
128
            # when the mount is available and GCRON_TASKS is available
129
            # the flag will tell this routine to reload GCRON_CROND_TASK
130
            try:
131
                f = os.open(GCRON_RELOAD_FLAG,
132
                            os.O_CREAT | os.O_NONBLOCK, 0o644)
133
                os.close(f)
134
            except OSError as e:
135
                if errno != EEXIST:
136
                    log.error("Failed to create %s : %s",
137
                              GCRON_RELOAD_FLAG, e)
138
                    output("Failed to create %s. Error: %s"
139
                           % (GCRON_RELOAD_FLAG, e))
140
            return
141

142
        if not os.path.exists(GCRON_CROND_TASK):
143
            return
144

145
        # As GCRON_TASKS exists now, we should check if GCRON_RELOAD_FLAG
146
        # also exists. If so we should touch GCRON_CROND_TASK and remove
147
        # the GCRON_RELOAD_FLAG
148
        if os.path.exists(GCRON_RELOAD_FLAG):
149
            try:
150
                os.remove(GCRON_RELOAD_FLAG);
151
                process = subprocess.Popen(["touch", "-h", GCRON_CROND_TASK],
152
                                           stdout=subprocess.PIPE,
153
                                           stderr=subprocess.PIPE)
154
                out, err = process.communicate()
155
                if process.returncode != 0:
156
                    log.error("Failed to touch %s. Error: %s.",
157
                              GCRON_CROND_TASK, err)
158
            except (IOError, OSError) as e:
159
                log.error("Failed to touch %s. Error: %s.",
160
                          GCRON_CROND_TASK, e)
161
            return
162
        if os.lstat(GCRON_TASKS).st_mtime > \
163
           os.lstat(GCRON_CROND_TASK).st_mtime:
164
            try:
165
                process = subprocess.Popen(["touch", "-h", GCRON_CROND_TASK],
166
                                           stdout=subprocess.PIPE,
167
                                           stderr=subprocess.PIPE)
168
                out, err = process.communicate()
169
                if process.returncode != 0:
170
                    log.error("Failed to touch %s. Error: %s.",
171
                              GCRON_CROND_TASK, err)
172
            except IOError as e:
173
                log.error("Failed to touch %s. Error: %s.",
174
                          GCRON_CROND_TASK, e)
175
        return
176

177
    volname = sys.argv[1]
178
    jobname = sys.argv[2]
179
    locking_file = os.path.join(LOCK_FILE_DIR, jobname)
180
    log.debug("locking_file = %s", locking_file)
181
    log.debug("volname = %s", volname)
182
    log.debug("jobname = %s", jobname)
183

184
    start_time = int(time.time())
185

186
    doJob("Scheduled-" + jobname + "-" + volname, locking_file, takeSnap, volname)
187

188

189
if __name__ == "__main__":
190
    main()
191

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.