diff options
-rwxr-xr-x | extras/snap_scheduler/snap_scheduler.py | 87 |
1 files changed, 85 insertions, 2 deletions
diff --git a/extras/snap_scheduler/snap_scheduler.py b/extras/snap_scheduler/snap_scheduler.py index 68ac08937cb..e7c1791a15e 100755 --- a/extras/snap_scheduler/snap_scheduler.py +++ b/extras/snap_scheduler/snap_scheduler.py @@ -33,8 +33,10 @@ LOCK_FILE_DIR = SHARED_STORAGE_DIR+"/snaps/lock_files/" LOCK_FILE = LOCK_FILE_DIR+"lock_file" TMP_FILE = SHARED_STORAGE_DIR+"/snaps/tmp_file" GCRON_UPDATE_TASK = "/etc/cron.d/gcron_update_task" +CURRENT_SCHEDULER = SHARED_STORAGE_DIR+"/snaps/current_scheduler" tasks = {} longest_field = 12 +current_scheduler = "" def output(msg): @@ -81,11 +83,28 @@ def scheduler_status(): return success - def enable_scheduler(): ret = scheduler_status() if ret: if not scheduler_enabled: + + # Check if another scheduler is active. + ret = get_current_scheduler() + if ret: + if (current_scheduler != "none"): + print_str = "Failed to enable snapshot scheduling. " \ + "Error: Another scheduler is active." + log.error(print_str) + output(print_str) + ret = False + return ret + else: + print_str = "Failed to get current scheduler info." + log.error(print_str) + output(print_str) + ret = False + return ret + log.info("Enabling snapshot scheduler.") try: if os.path.exists(GCRON_DISABLED): @@ -102,6 +121,7 @@ def enable_scheduler(): ret = False return ret os.symlink(GCRON_ENABLED, GCRON_TASKS) + update_current_scheduler("cli") log.info("Snapshot scheduling is enabled") output("Snapshot scheduling is enabled") except IOError as (errno, strerror): @@ -130,6 +150,20 @@ def disable_scheduler(): if scheduler_enabled: log.info("Disabling snapshot scheduler.") try: + # Check if another scheduler is active. If not, then + # update current scheduler to "none". Else do nothing. + ret = get_current_scheduler() + if ret: + if (current_scheduler == "cli"): + update_current_scheduler("none") + else: + print_str = "Failed to disable snapshot scheduling. " \ + "Error: Failed to get current scheduler info." + log.error(print_str) + output(print_str) + ret = False + return ret + if os.path.exists(GCRON_DISABLED): os.remove(GCRON_DISABLED) if os.path.lexists(GCRON_TASKS): @@ -176,6 +210,7 @@ def load_tasks_from_file(): longest_field = max(longest_field, len(jobname), len(volname), len(schedule)) tasks[jobname] = schedule+":"+volname + f.close() ret = True except IOError as (errno, strerror): log.error("Failed to open %s. Error: %s.", GCRON_ENABLED, strerror) @@ -184,6 +219,20 @@ def load_tasks_from_file(): return ret +def get_current_scheduler(): + global current_scheduler + try: + with open(CURRENT_SCHEDULER, 'r') as f: + current_scheduler = f.readline().rstrip('\n') + f.close() + ret = True + except IOError as (errno, strerror): + log.error("Failed to open %s. Error: %s.", CURRENT_SCHEDULER, strerror) + ret = False + + return ret + + def list_schedules(): log.info("Listing snapshot schedules.") ret = load_tasks_from_file() @@ -230,6 +279,7 @@ def write_tasks_to_file(): f.write("\n") f.flush() os.fsync(f.fileno()) + f.close() except IOError as (errno, strerror): log.error("Failed to open %s. Error: %s.", TMP_FILE, strerror) ret = False @@ -240,6 +290,24 @@ def write_tasks_to_file(): return ret +def update_current_scheduler(data): + ret = False + try: + with open(TMP_FILE, "w", 0644) as f: + f.write("%s" % data) + f.flush() + os.fsync(f.fileno()) + f.close() + except IOError as (errno, strerror): + log.error("Failed to open %s. Error: %s.", TMP_FILE, strerror) + ret = False + return ret + + shutil.move(TMP_FILE, CURRENT_SCHEDULER) + ret = True + + return ret + def add_schedules(jobname, schedule, volname): log.info("Adding snapshot schedules.") @@ -342,6 +410,7 @@ def initialise_scheduler(): f.write("%s\n" % updater) f.flush() os.fsync(f.fileno()) + f.close() except IOError as (errno, strerror): log.error("Failed to open /tmp/crontab. Error: %s.", strerror) ret = False @@ -411,6 +480,13 @@ def perform_operation(args): output("Failed to initialise snapshot scheduling") return ret + # Disable snapshot scheduler + if args.action == "disable_force": + ret = disable_scheduler() + if ret: + subprocess.Popen(["touch", "-h", GCRON_TASKS]) + return ret + # Check if the symlink to GCRON_TASKS is properly set in the shared storage if (not os.path.lexists(GCRON_UPDATE_TASK) or not os.path.lexists(GCRON_CROND_TASK) or @@ -489,7 +565,10 @@ def main(): initLogger() ret = -1 parser = argparse.ArgumentParser() - subparsers = parser.add_subparsers(dest="action") + subparsers = parser.add_subparsers(dest="action", + metavar=('{init, status, enable,' + ' disable, list, add,' + ' delete, edit}')) subparsers.add_parser('init', help="Initialise the node for snapshot scheduling") @@ -500,6 +579,7 @@ def main(): help="Enable snapshot scheduling") subparsers.add_parser("disable", help="Disable snapshot scheduling") + subparsers.add_parser("disable_force") subparsers.add_parser("list", help="List snapshot schedules") parser_add = subparsers.add_parser("add", @@ -549,6 +629,9 @@ def main(): output("Failed to create %s. Error: %s" % (LOCK_FILE_DIR, strerror)) + if not os.path.exists(CURRENT_SCHEDULER): + update_current_scheduler("none") + try: f = os.open(LOCK_FILE, os.O_CREAT | os.O_RDWR | os.O_NONBLOCK, 0644) try: |