Skip to content
Snippets Groups Projects
Commit c80fd5cb authored by Vladimir Bahyl's avatar Vladimir Bahyl
Browse files

Crated proper directory

parent e85a70c3
Branches
Tags
No related merge requests found
#!/usr/bin/python36
# The CERN Tape Archive (CTA) project
# Copyright (C) 2019 CERN
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Logic:
# * CTA tape pool should have at least X partial tapes available for writing
# * Eligible partial tapes are those that are not DISABLED, not FULL and not
# in a DISABLED logical tape library
# * If the number of eligible partial tapes for a given pool falls below the
# configured limit, the pool needs to be re-supplied with fresh tapes
# * Fresh supply tapes are taken from tape pools defined in the "supply" column
# * Supply tape pools can be separated by a separator (usually comma)
# * There is no distinction between what is a supply pool and what is not, if
# a pool has a value in the "supply" column, tapes are taken from there.
# Because of this, irregularities, cyclical loops and other misconfiguration
# are possible - please be careful
# * This script is intended to run every 15 minutes
#
# Author: Vladimir Bahyl - 7/2019
import sys
import json
import logging
from random import shuffle
from datetime import datetime
from subprocess import STDOUT, check_output
##########
#
# 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
ctaadmin = "/usr/bin/cta-admin"
# Configure logging
logfile = sys.argv[0] + ".log"
logging.basicConfig (
level = logging.INFO, # only messages with log level above this are logged (DEBUG, INFO, WARN, ERROR)
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_eligible_tapes(disabledlibraries, tapepool):
tapes = []
command = [ctaadmin, "--json", "tape", "ls", "--tapepool", tapepool, "--disabled", "false", "--full", "false"]
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:
tapes = [line["vid"] for line in json.loads(output) if not line["logicalLibrary"] in disabledlibraries]
else:
logging.warn("No eligible tapes identified in the tape pool: " + tapepool)
return tapes
##########
#
# MAIN
#
##########
logging.info("Current time: " + format(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
# Extract the list of all tape pools from CTA (in the JSON format)
command = [ctaadmin, "--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)
#logging.debug("List of extracted tape pools from CTA: " + format(tapepools))
# Extract the list of DISABLED tape libraries from CTA (in the JSON format)
command = [ctaadmin, "--json", "logicallibrary", "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:
disabledlibraries = [line["name"] for line in json.loads(output) if line["isDisabled"] ]
else:
logging.info("No DISABLED logical tape libraries detected, considering tapes from all libraries")
if disabledlibraries: logging.warn("List of DISABLED logical tape libraries: " + format(disabledlibraries))
# 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"] + " eligible 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_eligible_tapes(disabledlibraries, tapepool["name"])])
if (currentpartialtapes < int(tapepool["numPartialTapes"])):
logging.info("Tape pool: " + tapepool["name"] + " only has: " + format(currentpartialtapes) + " eligible partial tape(s) available, re-filling")
else:
logging.info("Tape pool: " + tapepool["name"] + " already has: " + format(currentpartialtapes) + " eligible partial tape(s) available, skipping")
continue
# Prepare the eligible supply tapes from a given supply pool(s)
supplytapes = []
for supplypool in tapepool["supply"].split(separator):
supplytapes.extend([tape for tape in extract_eligible_tapes(disabledlibraries, supplypool)])
shuffle(supplytapes) # Randomize it (so that tapes are picked at random from multiple pools)
# Move the required number of supply tapes to the given tape pool (if any eligible tapes were identified)
if len(supplytapes):
logging.info("Identified: " + format(len(supplytapes)) + " supply tapes, moving random " + format(int(tapepool["numPartialTapes"]) - currentpartialtapes) + " to the pool: " + tapepool["name"])
for i in range(int(tapepool["numPartialTapes"]) - currentpartialtapes):
if i < len(supplytapes):
command = [ctaadmin, "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 completely re-fill the tape pool: " + tapepool["name"] + ", run out of supply tapes")
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 eligible partial tapes: " + tapepool["numPartialTapes"] + " or the supply pool: " + tapepool["supply"] + " is not properly configured")
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment