From c18be39b6c37cad93f1c00507ae76d1fd4d3571a Mon Sep 17 00:00:00 2001 From: Avra Sengupta Date: Fri, 29 May 2015 18:11:01 +0530 Subject: snapshot/scheduler: Return proper error code in case of failure Backport of http://review.gluster.org/#/c/11005/ ENUM RETCODE ERROR ---------------------------------------------------------- INTERNAL_ERROR 2 Internal Error SHARED_STORAGE_DIR_DOESNT_EXIST 3 Shared Storage Dir does not exist SHARED_STORAGE_NOT_MOUNTED 4 Shared storage is not mounted ANOTHER_TRANSACTION_IN_PROGRESS 5 Another transaction is in progress INIT_FAILED 6 Initialisation failed SCHEDULING_ALREADY_DISABLED 7 Scheduler is already disabled SCHEDULING_ALREADY_ENABLED 8 Scheduler is already enabled NODE_NOT_INITIALISED 9 Node not initialised ANOTHER_SCHEDULER_ACTIVE 10 Another scheduler is active JOB_ALREADY_EXISTS 11 Job already exists JOB_NOT_FOUND 12 Job not found INVALID_JOBNAME 13 Jobname is invalid INVALID_VOLNAME 14 Volname is invalid INVALID_SCHEDULE 15 Schedule is invalid INVALID_ARG 16 Argument is invalid Change-Id: Ia1da166659099f4c951fcdb4d755529e41167b80 BUG: 1227615 Signed-off-by: Avra Sengupta (cherry picked from commit 9798a24febba9bbf28e97656b81b8a01a1325f68) Reviewed-on: http://review.gluster.org/11057 Tested-by: Gluster Build System Tested-by: NetBSD Build System Reviewed-by: Rajesh Joseph Reviewed-by: Krishnan Parthasarathi --- extras/snap_scheduler/snap_scheduler.py | 142 ++++++++++++++++++-------------- 1 file changed, 81 insertions(+), 61 deletions(-) (limited to 'extras/snap_scheduler') diff --git a/extras/snap_scheduler/snap_scheduler.py b/extras/snap_scheduler/snap_scheduler.py index e7c1791a15e..1c5f9380dd8 100755 --- a/extras/snap_scheduler/snap_scheduler.py +++ b/extras/snap_scheduler/snap_scheduler.py @@ -38,6 +38,21 @@ tasks = {} longest_field = 12 current_scheduler = "" +INTERNAL_ERROR = 2 +SHARED_STORAGE_DIR_DOESNT_EXIST = 3 +SHARED_STORAGE_NOT_MOUNTED = 4 +ANOTHER_TRANSACTION_IN_PROGRESS = 5 +INIT_FAILED = 6 +SCHEDULING_ALREADY_DISABLED = 7 +SCHEDULING_ALREADY_ENABLED = 8 +NODE_NOT_INITIALISED = 9 +ANOTHER_SCHEDULER_ACTIVE = 10 +JOB_ALREADY_EXISTS = 11 +JOB_NOT_FOUND = 12 +INVALID_JOBNAME = 13 +INVALID_VOLNAME = 14 +INVALID_SCHEDULE = 15 +INVALID_ARG = 16 def output(msg): print("%s: %s" % (SCRIPT_NAME, msg)) @@ -66,7 +81,7 @@ def initLogger(): def scheduler_status(): - success = False + ret = INTERNAL_ERROR global scheduler_enabled try: f = os.path.realpath(GCRON_TASKS) @@ -76,33 +91,32 @@ def scheduler_status(): else: log.info("Snapshot scheduler is currently enabled.") scheduler_enabled = True - success = True + ret = 0 except: log.error("Failed to enable snapshot scheduling. Error: " "Failed to check the status of %s.", GCRON_DISABLED) - return success + return ret def enable_scheduler(): ret = scheduler_status() - if ret: + if ret == 0: if not scheduler_enabled: # Check if another scheduler is active. ret = get_current_scheduler() - if ret: + if ret == 0: 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 + ret = ANOTHER_SCHEDULER_ACTIVE 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.") @@ -118,23 +132,24 @@ def enable_scheduler(): except IOError as (errno, strerror): log.error("Failed to open %s. Error: %s.", GCRON_ENABLED, strerror) - ret = False + ret = INTERNAL_ERROR return ret os.symlink(GCRON_ENABLED, GCRON_TASKS) update_current_scheduler("cli") log.info("Snapshot scheduling is enabled") output("Snapshot scheduling is enabled") + ret = 0 except IOError as (errno, strerror): print_str = "Failed to enable snapshot scheduling. Error: "+strerror log.error(print_str) output(print_str) - ret = False + ret = INTERNAL_ERROR else: print_str = "Failed to enable snapshot scheduling. " \ "Error: Snapshot scheduling is already enabled." log.error(print_str) output(print_str) - ret = False + ret = SCHEDULING_ALREADY_ENABLED else: print_str = "Failed to enable snapshot scheduling. " \ "Error: Failed to check scheduler status." @@ -146,14 +161,14 @@ def enable_scheduler(): def disable_scheduler(): ret = scheduler_status() - if ret: + if ret == 0: 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 ret == 0: if (current_scheduler == "cli"): update_current_scheduler("none") else: @@ -161,7 +176,6 @@ def disable_scheduler(): "Error: Failed to get current scheduler info." log.error(print_str) output(print_str) - ret = False return ret if os.path.exists(GCRON_DISABLED): @@ -173,22 +187,24 @@ def disable_scheduler(): os.symlink(GCRON_DISABLED, GCRON_TASKS) log.info("Snapshot scheduling is disabled") output("Snapshot scheduling is disabled") + ret = 0 except IOError as (errno, strerror): print_str = "Failed to disable snapshot scheduling. Error: "+strerror log.error(print_str) output(print_str) - ret = False + ret = INTERNAL_ERROR else: print_str = "Failed to disable scheduling. " \ "Error: Snapshot scheduling is already disabled." log.error(print_str) output(print_str) - ret = False + ret = SCHEDULING_ALREADY_DISABLED else: print_str = "Failed to disable snapshot scheduling. " \ "Error: Failed to check scheduler status." log.error(print_str) output(print_str) + ret = INTERNAL_ERROR return ret @@ -211,10 +227,10 @@ def load_tasks_from_file(): len(schedule)) tasks[jobname] = schedule+":"+volname f.close() - ret = True + ret = 0 except IOError as (errno, strerror): log.error("Failed to open %s. Error: %s.", GCRON_ENABLED, strerror) - ret = False + ret = INTERNAL_ERROR return ret @@ -225,10 +241,10 @@ def get_current_scheduler(): with open(CURRENT_SCHEDULER, 'r') as f: current_scheduler = f.readline().rstrip('\n') f.close() - ret = True + ret = 0 except IOError as (errno, strerror): log.error("Failed to open %s. Error: %s.", CURRENT_SCHEDULER, strerror) - ret = False + ret = INTERNAL_ERROR return ret @@ -236,7 +252,7 @@ def get_current_scheduler(): def list_schedules(): log.info("Listing snapshot schedules.") ret = load_tasks_from_file() - if ret: + if ret == 0: if len(tasks) == 0: output("No snapshots scheduled") else: @@ -255,6 +271,7 @@ def list_schedules(): longest_field + 5) operation = "Snapshot Create".ljust(longest_field+5) print(jobname+schedule+operation+volname) + ret = 0 else: print_str = "Failed to list snapshot schedules. " \ "Error: Failed to load tasks from "+GCRON_ENABLED @@ -265,7 +282,6 @@ def list_schedules(): def write_tasks_to_file(): - ret = False try: with open(TMP_FILE, "w", 0644) as f: # If tasks is empty, just create an empty tmp file @@ -282,16 +298,15 @@ def write_tasks_to_file(): f.close() except IOError as (errno, strerror): log.error("Failed to open %s. Error: %s.", TMP_FILE, strerror) - ret = False + ret = INTERNAL_ERROR return ret shutil.move(TMP_FILE, GCRON_ENABLED) - ret = True + ret = 0 return ret def update_current_scheduler(data): - ret = False try: with open(TMP_FILE, "w", 0644) as f: f.write("%s" % data) @@ -300,11 +315,11 @@ def update_current_scheduler(data): f.close() except IOError as (errno, strerror): log.error("Failed to open %s. Error: %s.", TMP_FILE, strerror) - ret = False + ret = INTERNAL_ERROR return ret shutil.move(TMP_FILE, CURRENT_SCHEDULER) - ret = True + ret = 0 return ret @@ -312,17 +327,17 @@ def update_current_scheduler(data): def add_schedules(jobname, schedule, volname): log.info("Adding snapshot schedules.") ret = load_tasks_from_file() - if ret: + if ret == 0: if jobname in tasks: print_str = ("%s already exists in schedule. Use " "'edit' to modify %s" % (jobname, jobname)) log.error(print_str) output(print_str) - ret = False + ret = JOB_ALREADY_EXISTS else: tasks[jobname] = schedule + ":" + volname ret = write_tasks_to_file() - if ret: + if ret == 0: # Create a LOCK_FILE for the job job_lockfile = LOCK_FILE_DIR + jobname try: @@ -331,10 +346,11 @@ def add_schedules(jobname, schedule, volname): except IOError as (errno, strerror): log.error("Failed to open %s. Error: %s.", job_lockfile, strerror) - ret = False + ret = INTERNAL_ERROR return ret log.info("Successfully added snapshot schedule %s" % jobname) output("Successfully added snapshot schedule") + ret = 0 else: print_str = "Failed to add snapshot schedule. " \ "Error: Failed to load tasks from "+GCRON_ENABLED @@ -347,11 +363,11 @@ def add_schedules(jobname, schedule, volname): def delete_schedules(jobname): log.info("Delete snapshot schedules.") ret = load_tasks_from_file() - if ret: + if ret == 0: if jobname in tasks: del tasks[jobname] ret = write_tasks_to_file() - if ret: + if ret == 0: # Delete the LOCK_FILE for the job job_lockfile = LOCK_FILE_DIR+jobname try: @@ -359,15 +375,18 @@ def delete_schedules(jobname): except IOError as (errno, strerror): log.error("Failed to open %s. Error: %s.", job_lockfile, strerror) + ret = INTERNAL_ERROR + return ret log.info("Successfully deleted snapshot schedule %s" % jobname) output("Successfully deleted snapshot schedule") + ret = 0 else: print_str = ("Failed to delete %s. Error: No such " "job scheduled" % jobname) log.error(print_str) output(print_str) - ret = False + ret = JOB_NOT_FOUND else: print_str = "Failed to delete snapshot schedule. " \ "Error: Failed to load tasks from "+GCRON_ENABLED @@ -380,11 +399,11 @@ def delete_schedules(jobname): def edit_schedules(jobname, schedule, volname): log.info("Editing snapshot schedules.") ret = load_tasks_from_file() - if ret: + if ret == 0: if jobname in tasks: tasks[jobname] = schedule+":"+volname ret = write_tasks_to_file() - if ret: + if ret == 0: log.info("Successfully edited snapshot schedule %s" % jobname) output("Successfully edited snapshot schedule") else: @@ -392,7 +411,7 @@ def edit_schedules(jobname, schedule, volname): "job scheduled" % jobname) log.error(print_str) output(print_str) - ret = False + ret = JOB_NOT_FOUND else: print_str = "Failed to edit snapshot schedule. " \ "Error: Failed to load tasks from "+GCRON_ENABLED @@ -413,7 +432,7 @@ def initialise_scheduler(): f.close() except IOError as (errno, strerror): log.error("Failed to open /tmp/crontab. Error: %s.", strerror) - ret = False + ret = INIT_FAILED return ret shutil.move("/tmp/crontab", GCRON_UPDATE_TASK) @@ -424,7 +443,7 @@ def initialise_scheduler(): f.close() except IOError as (errno, strerror): log.error("Failed to open %s. Error: %s.", GCRON_TASKS, strerror) - ret = False + ret = INIT_FAILED return ret if os.path.lexists(GCRON_CROND_TASK): @@ -435,22 +454,22 @@ def initialise_scheduler(): log.info("Successfully inited snapshot scheduler for this node") output("Successfully inited snapshot scheduler for this node") - ret = True + ret = 0 return ret def syntax_checker(args): - ret = False - if hasattr(args, 'jobname'): if (len(args.jobname.split()) != 1): output("Invalid Jobname. Jobname should not be empty and should not contain \" \" character.") + ret = INVALID_JOBNAME return ret args.jobname=args.jobname.strip() if hasattr(args, 'volname'): if (len(args.volname.split()) != 1): output("Invalid Volname. Volname should not be empty and should not contain \" \" character.") + ret = INVALID_VOLNAME return ret args.volname=args.volname.strip() @@ -464,26 +483,25 @@ def syntax_checker(args): print ("| | +-------- Day of the Month (range: 1-31)") print ("| +---------- Hour (range: 0-23)") print ("+------------ Minute (range: 0-59)") + ret = INVALID_SCHEDULE return ret - ret = True + ret = 0 return ret def perform_operation(args): - ret = False - # Initialise snapshot scheduler on local node if args.action == "init": ret = initialise_scheduler() - if not ret: + if ret != 0: output("Failed to initialise snapshot scheduling") return ret # Disable snapshot scheduler if args.action == "disable_force": ret = disable_scheduler() - if ret: + if ret == 0: subprocess.Popen(["touch", "-h", GCRON_TASKS]) return ret @@ -495,12 +513,13 @@ def perform_operation(args): "the snap scheduler for the local node.") log.error(print_str) output(print_str) + ret = NODE_NOT_INITIALISED return ret # Check status of snapshot scheduler. if args.action == "status": ret = scheduler_status() - if ret: + if ret == 0: if scheduler_enabled: output("Snapshot scheduling status: Enabled") else: @@ -512,14 +531,14 @@ def perform_operation(args): # Enable snapshot scheduler if args.action == "enable": ret = enable_scheduler() - if ret: + if ret == 0: subprocess.Popen(["touch", "-h", GCRON_TASKS]) return ret # Disable snapshot scheduler if args.action == "disable": ret = disable_scheduler() - if ret: + if ret == 0: subprocess.Popen(["touch", "-h", GCRON_TASKS]) return ret @@ -531,33 +550,34 @@ def perform_operation(args): # Add snapshot schedules if args.action == "add": ret = syntax_checker(args) - if not ret: + if ret != 0: return ret ret = add_schedules(args.jobname, args.schedule, args.volname) - if ret: + if ret == 0: subprocess.Popen(["touch", "-h", GCRON_TASKS]) return ret # Delete snapshot schedules if args.action == "delete": ret = syntax_checker(args) - if not ret: + if ret != 0: return ret ret = delete_schedules(args.jobname) - if ret: + if ret == 0: subprocess.Popen(["touch", "-h", GCRON_TASKS]) return ret # Edit snapshot schedules if args.action == "edit": ret = syntax_checker(args) - if not ret: + if ret != 0: return ret ret = edit_schedules(args.jobname, args.schedule, args.volname) - if ret: + if ret == 0: subprocess.Popen(["touch", "-h", GCRON_TASKS]) return ret + ret = INVALID_ARG return ret @@ -601,11 +621,11 @@ def main(): if not os.path.exists(SHARED_STORAGE_DIR): output("Failed: "+SHARED_STORAGE_DIR+" does not exist.") - return ret + return SHARED_STORAGE_DIR_DOESNT_EXIST if not os.path.ismount(SHARED_STORAGE_DIR): output("Failed: Shared storage is not mounted at "+SHARED_STORAGE_DIR) - return ret + return SHARED_STORAGE_NOT_MOUNTED if not os.path.exists(SHARED_STORAGE_DIR+"/snaps/"): try: @@ -615,6 +635,7 @@ def main(): log.error("Failed to create %s : %s", SHARED_STORAGE_DIR+"/snaps/", strerror) output("Failed to create %s. Error: %s" % (SHARED_STORAGE_DIR+"/snaps/", strerror)) + return INTERNAL_ERROR if not os.path.exists(GCRON_ENABLED): f = os.open(GCRON_ENABLED, os.O_CREAT | os.O_NONBLOCK, 0644) @@ -628,6 +649,7 @@ def main(): log.error("Failed to create %s : %s", LOCK_FILE_DIR, strerror) output("Failed to create %s. Error: %s" % (LOCK_FILE_DIR, strerror)) + return INTERNAL_ERROR if not os.path.exists(CURRENT_SCHEDULER): update_current_scheduler("none") @@ -637,19 +659,17 @@ def main(): try: fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB) ret = perform_operation(args) - if not ret: - ret = 1 - else: - ret = 0 fcntl.flock(f, fcntl.LOCK_UN) except IOError as (errno, strerror): log.info("%s is being processed by another agent.", LOCK_FILE) output("Another snap_scheduler command is running. " "Please try again after some time.") + return ANOTHER_TRANSACTION_IN_PROGRESS os.close(f) except IOError as (errno, strerror): log.error("Failed to open %s : %s", LOCK_FILE, strerror) output("Failed to open %s. Error: %s" % (LOCK_FILE, strerror)) + return INTERNAL_ERROR return ret -- cgit