]> scripts.mit.edu Git - wizard.git/blob - wizard/scripts.py
Retry quota parse if volume is busy.
[wizard.git] / wizard / scripts.py
1 import os
2 import shlex
3 import errno
4 import logging
5 import urlparse
6
7 import wizard
8 from wizard import shell, util
9
10 def fill_url(dir, url=None):
11     if url:
12         return url
13
14     # hook hook
15
16     # try the directory
17     homedir, _, web_path = dir.partition("/web_scripts")
18     if web_path:
19         return urlparse.ParseResult(
20                 "http",
21                 util.get_dir_owner(homedir) + ".scripts.mit.edu",
22                 web_path.rstrip('/'),
23                 "", "", "")
24
25     # try the environment
26     host = os.getenv("WIZARD_WEB_HOST")
27     path = os.getenv("WIZARD_WEB_PATH")
28     if host is not None and path is not None:
29         return urlparse.ParseResult(
30                 "http",
31                 host,
32                 path.rstrip('/'),
33                 "", "", "")
34
35     return None
36
37 def get_quota_usage_and_limit(dir=None):
38     """
39     Returns a tuple (quota usage, quota limit).  Works only for scripts
40     servers.  Values are in KiB.  Returns ``(0, None)`` if we couldn't figure it out.
41     """
42     exc = None
43     # sometimes the volume is busy; so we try several times
44     for i in range(0, 3):
45         try:
46             return _get_quota_usage_and_limit(dir)
47         except QuotaParseError as e:
48             exc = e
49     raise exc
50
51 def _get_quota_usage_and_limit(dir=None):
52     # XXX: The correct way is to implement Python modules implementing
53     # bindings for all the appropriate interfaces
54     def parse_last_quote(ret):
55         return ret.rstrip('\'').rpartition('\'')[2]
56     if dir is None:
57         dir = os.getcwd()
58     sh = shell.Shell()
59     try:
60         cell = parse_last_quote(sh.eval("fs", "whichcell", "-path", dir))
61     except shell.CallError:
62         return (0, None)
63     except OSError as e:
64         if e.errno == errno.ENOENT:
65             return (0, None)
66         raise
67     mount = None
68     while dir:
69         try:
70             volume = parse_last_quote(sh.eval("fs", "lsmount", dir))[1:]
71             break
72         except shell.CallError:
73             dir = os.path.dirname(dir)
74         except OSError as e:
75             if e.errno == errno.ENOENT:
76                 return (0, None)
77             raise
78     if not volume: return (0, None)
79     try:
80         result = sh.eval("vos", "examine", "-id", volume, "-cell", cell).splitlines()
81     except OSError:
82         try:
83             result = sh.eval("/usr/sbin/vos", "examine", "-id", volume, "-cell", cell).splitlines()
84         except OSError:
85             return (0, None)
86     except shell.CallError:
87         return (0, None)
88     try:
89         usage = int(result[0].split()[3])
90         limit = int(result[3].split()[1]) # XXX: FRAGILE
91     except ValueError:
92         raise QuotaParseError("vos examine output was:\n\n" + "\n".join(result))
93     return (usage, limit)
94
95 # XXX: Possibly in the wrong module
96 def get_disk_usage(dir=None, excluded_dir=".git"):
97     """
98     Recursively determines the disk usage of a directory, excluding
99     .git directories.  Value is in bytes.
100     """
101     if dir is None: dir = os.getcwd()
102     sum_sizes = 0
103     for root, _, files in os.walk(dir):
104         for name in files:
105             if not os.path.join(root, name).startswith(dir + excluded_dir):
106                 sum_sizes += os.path.getsize(os.path.join(root, name))
107     return sum_sizes
108 class QuotaParseError(wizard.Error):
109     def __init__(self, msg):
110         self.msg = msg
111     def __str__(self):
112         return """
113
114 ERROR: Could not parse quota. %s
115 """ % self.msg