]> scripts.mit.edu Git - wizard.git/blob - wizard/scripts.py
Implement interactive mode without validation.
[wizard.git] / wizard / scripts.py
1 import os
2 import shlex
3 import errno
4 import logging
5
6 import wizard
7 from wizard import shell, util
8
9 def get_sql_credentials(vars=None):
10     """
11     Attempts to determine a user's MySQL credentials.  They are
12     returned as a three-tuple (host, user, password).
13     """
14     sh = shell.Shell()
15     host = os.getenv("WIZARD_MYSQL_HOST")
16     user = os.getenv("WIZARD_MYSQL_USER")
17     password = os.getenv("WIZARD_MYSQL_PASSWORD")
18     if host is not None and user is not None and password is not None:
19         return (host, user, password)
20     # XXX: this is very fragile
21     elif vars and "WIZARD_DBSERVER" in vars and "WIZARD_DBUSER" in vars and "WIZARD_DBPASSWORD" in vars:
22         return (shlex.split(vars[x])[0] for x in ("WIZARD_DBSERVER", "WIZARD_DBUSER", "WIZARD_DBPASSWORD"))
23     try:
24         tuple = sh.eval("/mit/scripts/sql/bin/get-password").split()
25         if len(tuple) == 3:
26             return tuple
27         return None
28     except shell.CallError:
29         return None
30
31 def get_web_host_and_path(dir=None):
32     """
33     Attempts to determine webhost and path for the current directory
34     as it would be accessible from the web.  Works only for scripts
35     servers.  Returns a tuple web_host, web_path, or None if it failed.
36     """
37     # XXX: THIS CODE SUCKS
38     host = os.getenv("WIZARD_WEB_HOST")
39     path = os.getenv("WIZARD_WEB_PATH")
40     if host is not None and path is not None:
41         return (host, path)
42     if not dir:
43         dir = os.getcwd()
44     # XXX: possible security risk?
45     homedir, _, web_path = dir.partition("/web_scripts")
46     if not web_path:
47         return None
48     return (util.get_dir_owner(homedir) + ".scripts.mit.edu", web_path)
49
50 def get_quota_usage_and_limit(dir=None):
51     """
52     Returns a tuple (quota usage, quota limit).  Works only for scripts
53     servers.  Values are in KiB.  Returns ``(0, None)`` if we couldn't figure it out.
54     """
55     # XXX: The correct way is to implement Python modules implementing
56     # bindings for all the appropriate interfaces
57     def parse_last_quote(ret):
58         return ret.rstrip('\'').rpartition('\'')[2]
59     if dir is None:
60         dir = os.getcwd()
61     sh = shell.Shell()
62     try:
63         cell = parse_last_quote(sh.eval("fs", "whichcell", "-path", dir))
64     except shell.CallError:
65         return (0, None)
66     except OSError as e:
67         if e.errno == errno.ENOENT:
68             return (0, None)
69         raise
70     mount = None
71     while dir:
72         try:
73             volume = parse_last_quote(sh.eval("fs", "lsmount", dir))[1:]
74             break
75         except shell.CallError:
76             dir = os.path.dirname(dir)
77         except OSError as e:
78             if e.errno == errno.ENOENT:
79                 return (0, None)
80             raise
81     if not volume: return (0, None)
82     try:
83         result = sh.eval("vos", "examine", "-id", volume, "-cell", cell).splitlines()
84     except shell.CallError:
85         return (0, None)
86     try:
87         usage = int(result[0].split()[3])
88         limit = int(result[3].split()[1]) # XXX: FRAGILE
89     except ValueError:
90         raise QuotaParseError("vos examine output was:\n\n" + "\n".join(result))
91     return (usage, limit)
92
93 # XXX: Possibly in the wrong module
94 def get_disk_usage(dir=None, excluded_dir=".git"):
95     """
96     Recursively determines the disk usage of a directory, excluding
97     .git directories.  Value is in bytes.
98     """
99     if dir is None: dir = os.getcwd()
100     sum_sizes = 0
101     for root, _, files in os.walk(dir):
102         for name in files:
103             if not os.path.join(root, name).startswith(dir + excluded_dir):
104                 sum_sizes += os.path.getsize(os.path.join(root, name))
105     return sum_sizes
106 class QuotaParseError(wizard.Error):
107     def __init__(self, msg):
108         self.msg = msg
109     def __str__(self):
110         return """
111
112 ERROR: Could not parse quota. %s
113 """ % self.msg