+"""
+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):
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:
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)
- usage = int(result[0].split()[3])
- limit = int(result[3].split()[1]) # XXX: FRAGILE
+ 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):
+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):
+ return """
+ERROR: Could not parse quota. %s
+""" % self.msg