diff --git a/operations/tape/supply-pool-refill-mechanism b/operations/tape/supply-pool-refill-mechanism new file mode 100755 index 0000000000000000000000000000000000000000..d5ed692f2052ccd8d3fe0ab500a75b4d4addcea0 --- /dev/null +++ b/operations/tape/supply-pool-refill-mechanism @@ -0,0 +1,114 @@ +#!/usr/bin/python36 + +import sys +import json +import logging +from random import shuffle +from subprocess import STDOUT, check_output, CalledProcessError + +########## +# +# CONFIGURATION +# +########## + +timeout = 10 # how many seconds to wait for the external command to finish +separator = "," # characted which separates multiple tape pools in the CTA "supply" column + +# Configure logging +logfile = sys.argv[0] + ".log" +logging.basicConfig ( + level = logging.DEBUG, # only messages with log level above this are logged + format = "[%(levelname)-5.5s] %(message)s", # format of the logging (can be very complex - see the manual) + handlers = [ + logging.FileHandler(logfile), # log to a logfile + logging.StreamHandler() # log to console STDOUT + ]) + +########## +# +# FUNCTIONS +# +########## + +# Extract eligible (not DISABLED, not FULL and NOT in a DISABLED library) tapes from a given tape pool +def extract_tapes(tapelibrary, tapepool): + tapes = [] + command = ["/usr/bin/cta-admin", "--json", "tape", "ls", "--tapepool", tapepool, "--disabled", "false", "--full", "false"] + if ((tapelibrary) and (tapelibrary != "ALL")): + command.extend(["--logicallibrary", tapelibrary]) + try: + logging.debug("Executing command " + format(command) + " with timeout of " + format(timeout) + " seconds") + output = check_output(command, stderr = STDOUT, timeout = timeout).decode("UTF-8") + except Exception as error: + logging.error(format(error)) + sys.exit(-1) + + if output == "]": output = "" # TEMPORARY UNTIL --json FIXED !!! + if output: + tapes = [line["vid"] for line in json.loads(output)] + else: + logging.warn("No eligible tapes extracted from the tape pool: " + tapepool) + + return tapes + +########## +# +# MAIN +# +########## + +# Extract the list of all tape pools in CTA in JSON format +command = ["/usr/bin/cta-admin", "--json", "tapepool", "ls"] +try: + logging.debug("Executing command " + format(command) + " with timeout of " + format(timeout) + " seconds") + output = check_output(command, stderr = STDOUT, timeout = timeout).decode("UTF-8") +except Exception as error: + logging.error(format(error)) + sys.exit(-1) +if output: + tapepools = json.loads(output) +else: + logging.error("List of CTA tape pools is empty, nothing to do, exiting") + sys.exit(0) + +# Extract the list of DISABLED tape libraries +# LATER as --json not yet implemented + +#logging.debug("List of extracted tape pools from CTA:\n" + format(tapepools)) + +# Iterate over the extracted CTA tape pools and re-fill them with supply tapes as needed +for tapepool in tapepools: + logging.info("Tape pool: " + tapepool["name"] + " which should have at least: " + tapepool["numPartialTapes"] + " partial tape(s) is supplied from: " + tapepool["supply"]) + if (tapepool["numPartialTapes"] and tapepool["supply"]): + # Check if re-filling is actually needed + currentpartialtapes = len([tape for tape in extract_tapes("ALL", tapepool["name"])]) + if (currentpartialtapes < int(tapepool["numPartialTapes"])): + logging.info("Tape pool: " + tapepool["name"] + " only has: " + format(currentpartialtapes) + " partial tape(s) available, re-filling") + else: + logging.info("Tape pool: " + tapepool["name"] + " already has: " + format(currentpartialtapes) + " partial tape(s) available, skipping") + continue + + # Prepare the eligible supply tapes from a given supply pool + supplytapes = [] + for supplypool in tapepool["supply"].split(separator): + supplytapes.extend([tape for tape in extract_tapes("ALL", supplypool)]) + shuffle(supplytapes) # Randomize it (so that tapes are picked at random from multiple pools) + + if len(supplytapes): + # Move the required number of supply tapes to the given tape pool + logging.info("Identified: " + format(len(supplytapes)) + " supply tapes, moving " + format(int(tapepool["numPartialTapes"]) - currentpartialtapes) + " to the pool: " + tapepool["name"]) + for i in range(int(tapepool["numPartialTapes"]) - currentpartialtapes): + command = ["/usr/bin/cta-admin", "tape", "ch", "--vid", supplytapes[i], "--tapepool", tapepool["name"]] + try: + logging.debug("Executing command " + format(command) + " with timeout of " + format(timeout) + " seconds") +# output = check_output(command, stderr = STDOUT, timeout = timeout).decode("UTF-8") + except Exception as error: + logging.error(format(error)) + sys.exit(-1) + logging.info("Tape: " + format(supplytapes[i]) + " moved to the pool: " + tapepool["name"]) + else: + logging.warn("Unable to re-fill the tape pool: " + tapepool["name"] + ", no eligible supply tapes identified") + + else: + logging.warn("Unable to re-fill the tape pool: " + tapepool["name"] + " because either the number of partial tapes: " + tapepool["numPartialTapes"] + " or the supply pool: " + tapepool["supply"] + " is not properly configured")