]> scripts.mit.edu Git - wizard.git/blob - wizard/scripts.py
Rewrite parametrize to use new parametrizeWithVars
[wizard.git] / wizard / scripts.py
1 """
2 This is ostensibly the place where Scripts specific code should live.
3 """
4
5 import os
6 import shlex
7 import errno
8 import logging
9 import urlparse
10 import time
11 import errno
12
13 import wizard
14 from wizard import shell, util
15
16 def fill_url(dir, url=None, old_style=False):
17     """
18     Attempts to determine the URL a directory would be web-accessible at.
19     If ``url`` is specified, automatically use it.
20     """
21     if url:
22         return url
23
24     # hook hook
25
26     # try the directory
27     homedir, _, web_path = dir.partition("/web_scripts")
28     if web_path:
29         if old_style:
30             return urlparse.ParseResult(
31                     "http",
32                     "scripts.mit.edu",
33                     "/~" + util.get_dir_owner(homedir) + web_path.rstrip('/'),
34                     "", "", "")
35         else:
36             return urlparse.ParseResult(
37                     "http",
38                     util.get_dir_owner(homedir) + ".scripts.mit.edu",
39                     web_path.rstrip('/'),
40                     "", "", "")
41
42     # try the environment
43     host = os.getenv("WIZARD_WEB_HOST")
44     path = os.getenv("WIZARD_WEB_PATH")
45     if host is not None and path is not None:
46         return urlparse.ParseResult(
47                 "http",
48                 host,
49                 path.rstrip('/'),
50                 "", "", "")
51
52     return None
53
54 def get_quota_usage_and_limit(dir=None):
55     """
56     Returns a tuple (quota usage, quota limit).  Works only for scripts
57     servers.  Values are in KiB.  Returns ``(0, None)`` if we couldn't figure it out.
58     """
59     end = 2
60     # sometimes the volume is busy; so we try several times
61     for i in range(0, end + 1):
62         try:
63             return _get_quota_usage_and_limit(dir)
64         except QuotaParseError as e:
65             if i == end:
66                 raise e
67             time.sleep(3) # give it a chance to unbusy
68     assert False # should not get here
69
70 def _get_quota_usage_and_limit(dir=None):
71     # XXX: The correct way is to implement Python modules implementing
72     # bindings for all the appropriate interfaces
73     def parse_last_quote(ret):
74         return ret.rstrip('\'').rpartition('\'')[2]
75     if dir is None:
76         dir = os.getcwd()
77     sh = shell.Shell()
78     try:
79         cell = parse_last_quote(sh.eval("fs", "whichcell", "-path", dir))
80     except shell.CallError:
81         return (0, None)
82     except OSError as e:
83         if e.errno == errno.ENOENT:
84             return (0, None)
85         raise
86     mount = None
87     while dir:
88         try:
89             volume = parse_last_quote(sh.eval("fs", "lsmount", dir))[1:]
90             break
91         except shell.CallError:
92             dir = os.path.dirname(dir)
93         except OSError as e:
94             if e.errno == errno.ENOENT:
95                 return (0, None)
96             raise
97     if not volume: return (0, None)
98     try:
99         result = sh.eval("vos", "examine", "-id", volume, "-cell", cell).splitlines()
100     except OSError:
101         try:
102             result = sh.eval("/usr/sbin/vos", "examine", "-id", volume, "-cell", cell).splitlines()
103         except OSError:
104             return (0, None)
105     except shell.CallError:
106         return (0, None)
107     try:
108         usage = int(result[0].split()[3])
109         limit = int(result[3].split()[1]) # XXX: FRAGILE
110     except ValueError:
111         raise QuotaParseError("vos examine output was:\n\n" + "\n".join(result))
112     return (usage, limit)
113
114 # XXX: Possibly in the wrong module
115 def get_disk_usage(dir=None, excluded_dir=".git"):
116     """
117     Recursively determines the disk usage of a directory, excluding
118     .git directories.  Value is in bytes.
119     """
120     if dir is None: dir = os.getcwd()
121     sum_sizes = 0
122     for root, _, files in os.walk(dir):
123         for name in files:
124             if not os.path.join(root, name).startswith(dir + excluded_dir):
125                 file = os.path.join(root, name)
126                 try:
127                     if os.path.islink(file): continue
128                     sum_sizes += os.path.getsize(file)
129                 except OSError as e:
130                     if e.errno == errno.ENOENT:
131                         logging.warning("%s disappeared before we could stat", file)
132                     else:
133                         raise
134     return sum_sizes
135
136 class QuotaParseError(wizard.Error):
137     """Could not parse quota information."""
138     def __init__(self, msg):
139         self.msg = msg
140     def __str__(self):
141         return """
142
143 ERROR: Could not parse quota. %s
144 """ % self.msg