X-Git-Url: https://scripts.mit.edu/gitweb/wizard.git/blobdiff_plain/8939cb421d77e7469160f38381cf2106974e5ba8..db709749a3e3b1cba85a6869c87af925ae33d441:/wizard/scripts.py diff --git a/wizard/scripts.py b/wizard/scripts.py index a81f539..9092f26 100644 --- a/wizard/scripts.py +++ b/wizard/scripts.py @@ -1,54 +1,73 @@ +""" +This is ostensibly the place where Scripts specific code should live. +""" + import os import shlex +import errno +import logging +import urlparse +import time +import errno import wizard from wizard import shell, util -def get_sql_credentials(vars=None): +def fill_url(dir, url=None, old_style=False): """ - Attempts to determine a user's MySQL credentials. They are - returned as a three-tuple (host, user, password). + Attempts to determine the URL a directory would be web-accessible at. + If ``url`` is specified, automatically use it. """ - sh = shell.Shell() - host = os.getenv("WIZARD_MYSQL_HOST") - user = os.getenv("WIZARD_MYSQL_USER") - password = os.getenv("WIZARD_MYSQL_PASSWORD") - if host is not None and user is not None and password is not None: - return (host, user, password) - # XXX: this is very fragile - elif vars and "WIZARD_DBSERVER" in vars and "WIZARD_DBUSER" in vars and "WIZARD_DBPASSWORD" in vars: - return (shlex.split(vars[x])[0] for x in ("WIZARD_DBSERVER", "WIZARD_DBUSER", "WIZARD_DBPASSWORD")) - try: - tuple = sh.eval("/mit/scripts/sql/bin/get-password").split() - if len(tuple) == 3: - return tuple - return None - except CallError: - return None + if url: + return url -def get_web_host_and_path(dir=None): - """ - Attempts to determine webhost and path for the current directory - as it would be accessible from the web. Works only for scripts - servers. Returns a tuple web_host, web_path, or None if it failed. - """ - # XXX: THIS CODE SUCKS + # hook hook + + # try the directory + homedir, _, web_path = dir.partition("/web_scripts") + if web_path: + if old_style: + return urlparse.ParseResult( + "http", + "scripts.mit.edu", + "/~" + util.get_dir_owner(homedir) + web_path.rstrip('/'), + "", "", "") + else: + return urlparse.ParseResult( + "http", + util.get_dir_owner(homedir) + ".scripts.mit.edu", + web_path.rstrip('/'), + "", "", "") + + # try the environment host = os.getenv("WIZARD_WEB_HOST") path = os.getenv("WIZARD_WEB_PATH") if host is not None and path is not None: - return (host, path) - if not dir: - dir = os.getcwd() - _, _, web_path = dir.partition("/web_scripts") - if not web_path: - return None - return (util.get_dir_owner(dir) + ".scripts.mit.edu", web_path) + return urlparse.ParseResult( + "http", + host, + path.rstrip('/'), + "", "", "") + + return None def get_quota_usage_and_limit(dir=None): """ Returns a tuple (quota usage, quota limit). Works only for scripts servers. Values are in KiB. Returns ``(0, None)`` if we couldn't figure it out. """ + end = 2 + # sometimes the volume is busy; so we try several times + for i in range(0, end + 1): + try: + return _get_quota_usage_and_limit(dir) + except QuotaParseError as e: + if i == end: + raise e + time.sleep(3) # give it a chance to unbusy + assert False # should not get here + +def _get_quota_usage_and_limit(dir=None): # XXX: The correct way is to implement Python modules implementing # bindings for all the appropriate interfaces def parse_last_quote(ret): @@ -60,6 +79,10 @@ def get_quota_usage_and_limit(dir=None): cell = parse_last_quote(sh.eval("fs", "whichcell", "-path", dir)) except shell.CallError: return (0, None) + except OSError as e: + if e.errno == errno.ENOENT: + return (0, None) + raise mount = None while dir: try: @@ -67,9 +90,18 @@ def get_quota_usage_and_limit(dir=None): break except shell.CallError: dir = os.path.dirname(dir) + except OSError as e: + if e.errno == errno.ENOENT: + return (0, None) + raise if not volume: return (0, None) try: result = sh.eval("vos", "examine", "-id", volume, "-cell", cell).splitlines() + except OSError: + try: + result = sh.eval("/usr/sbin/vos", "examine", "-id", volume, "-cell", cell).splitlines() + except OSError: + return (0, None) except shell.CallError: return (0, None) try: @@ -80,15 +112,29 @@ def get_quota_usage_and_limit(dir=None): return (usage, limit) # XXX: Possibly in the wrong module -def get_disk_usage(dir=None): +def get_disk_usage(dir=None, excluded_dir=".git"): """ Recursively determines the disk usage of a directory, excluding .git directories. Value is in bytes. """ if dir is None: dir = os.getcwd() - return int(shell.Shell().eval("du", "--exclude=.git", "-s", dir).split()[0]) + sum_sizes = 0 + for root, _, files in os.walk(dir): + for name in files: + if not os.path.join(root, name).startswith(dir + excluded_dir): + file = os.path.join(root, name) + try: + if os.path.islink(file): continue + sum_sizes += os.path.getsize(file) + except OSError as e: + if e.errno == errno.ENOENT: + logging.warning("%s disappeared before we could stat", file) + else: + raise + return sum_sizes class QuotaParseError(wizard.Error): + """Could not parse quota information.""" def __init__(self, msg): self.msg = msg def __str__(self):