""" 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 fill_url(dir, url=None, old_style=False): """ Attempts to determine the URL a directory would be web-accessible at. If ``url`` is specified, automatically use it. """ if url: return url # 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 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): return ret.rstrip('\'').rpartition('\'')[2] if dir is None: dir = os.getcwd() sh = shell.Shell() try: 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: volume = parse_last_quote(sh.eval("fs", "lsmount", dir))[1:] 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: usage = int(result[0].split()[3]) limit = int(result[3].split()[1]) # XXX: FRAGILE except ValueError: raise QuotaParseError("vos examine output was:\n\n" + "\n".join(result)) return (usage, limit) # XXX: Possibly in the wrong module 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() 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): return """ ERROR: Could not parse quota. %s """ % self.msg