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