]> scripts.mit.edu Git - wizard.git/blobdiff - wizard/scripts.py
Add support for a working dir in wizard.shell
[wizard.git] / wizard / scripts.py
index a81f539ed641a4810a025192217dc6c5146ba72c..9092f268d0be2a96cbe33344fba7c701e8bde536 100644 (file)
@@ -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):