]> git.decadent.org.uk Git - dak.git/blob - dak/admin.py
add basic dak admin command to test out sqla work
[dak.git] / dak / admin.py
1 #!/usr/bin/env python
2
3 """Configure dak parameters in the database"""
4 # Copyright (C) 2009  Mark Hymers <mhy@debian.org>
5
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20 ################################################################################
21
22 import sys
23
24 import apt_pkg
25
26 from daklib import utils
27 from daklib.dbconn import *
28 from daklib.config import Config
29
30 ################################################################################
31
32 dispatch = {}
33 dryrun = False
34
35 ################################################################################
36 def warn(msg):
37     print >> sys.stderr, msg
38
39 def die(msg, exit_code=1):
40     print >> sys.stderr, msg
41     sys.exit(exit_code)
42
43 def die_arglen(args, args_needed, msg):
44     if len(args) < args_needed:
45         die(msg)
46
47 def usage(exit_code=0):
48     """Perform administrative work on the dak database."""
49
50     print """Usage: dak admin COMMAND
51 Perform administrative work on the dak database.
52
53   -h, --help          show this help and exit.
54   -n, --dry-run       don't do anything, just show what would have been done
55                       (only applies to add or rm operations).
56
57   Commands can use a long or abbreviated form:
58
59   architecture / a:
60      a list                 show a list of architectures
61      a rm ARCH              remove an architecture (will only work if
62                             no longer linked to any suites)
63      a add ARCH DESCRIPTION [SUITELIST]
64                             add architecture ARCH with DESCRIPTION.
65                             If SUITELIST is given, add to each of the
66                             suites at the same time
67
68   suite-architecture / s-a:
69      s-a list-suite ARCH    show the suites an ARCH is in
70      s-a list-arch SUITE    show the architectures in a SUITE
71      s-a add SUITE ARCH     add ARCH to suite
72      s-a rm SUITE ARCH      remove ARCH from suite (will only work if
73                             no packages remain for the arch in the suite)
74 """
75     sys.exit(exit_code)
76
77 ################################################################################
78
79 def __architecture_list(d, args):
80     q = d.session().query(Architecture).order_by('arch_string')
81     for j in q.all():
82         # HACK: We should get rid of source from the arch table
83         if j.arch_string == 'source': continue
84         print j.arch_string
85     sys.exit(0)
86
87 def __architecture_add(d, args):
88     die_arglen(args, 3, "E: adding an architecture requires a name and a description")
89     print "Adding architecture %s" % args[2]
90     suites = [str(x) for x in args[4:]]
91     print suites
92     if not dryrun:
93         try:
94             s = d.session()
95             s.begin()
96             a = Architecture()
97             a.arch_string = str(args[2]).lower()
98             a.description = str(args[3])
99             s.add(a)
100             for sn in suites:
101                 su = get_suite(sn ,s)
102                 if su is not None:
103                     archsu = SuiteArchitecture()
104                     archsu.arch_id = a.arch_id
105                     archsu.suite_id = su.suite_id
106                     s.add(archsu)
107                 else:
108                     warn("W: Cannot find suite %s" % su)
109             s.commit()
110         except IntegrityError, e:
111             die("E: Integrity error adding architecture %s (it probably already exists)" % args[2])
112         except SQLAlchemyError, e:
113             die("E: Error adding architecture %s (%s)" % (args[2], e))
114     print "Architecture %s added" % (args[2])
115
116 def __architecture_rm(d, args):
117     die_arglen(args, 3, "E: removing an architecture requires at least a name")
118     print "Removing architecture %s" % args[2]
119     if not dryrun:
120         try:
121             s = d.session()
122             s.begin()
123             a = get_architecture(args[2].lower(), s)
124             if a is None:
125                 die("E: Cannot find architecture %s" % args[2])
126             s.delete(a)
127             s.commit()
128         except IntegrityError, e:
129             die("E: Integrity error removing architecture %s (suite-arch entries probably still exist)" % args[2])
130         except SQLAlchemyError, e:
131             die("E: Error removing architecture %s (%s)" % (args[2], e))
132     print "Architecture %s removed" % args[2]
133
134 def architecture(command):
135     args = [str(x) for x in command]
136     Cnf = utils.get_conf()
137     d = DBConn()
138
139     die_arglen(args, 2, "E: architecture needs at least a command")
140
141     mode = args[1].lower()
142     if mode == 'list':
143         __architecture_list(d, args)
144     elif mode == 'add':
145         __architecture_add(d, args)
146     elif mode == 'rm':
147         __architecture_rm(d, args)
148     else:
149         die("E: architecture command unknown")
150
151 dispatch['architecture'] = architecture
152 dispatch['a'] = architecture
153
154 ################################################################################
155
156 def __suite_architecture_listarch(d, args):
157     die_arglen(args, 3, "E: suite-architecture list-arch requires a suite")
158     a = get_suite_architectures(args[2].lower())
159     for j in a:
160         # HACK: We should get rid of source from the arch table
161         if j.arch_string != 'source':
162             print j.arch_string
163
164
165 def __suite_architecture_listsuite(d, args):
166     die_arglen(args, 3, "E: suite-architecture list-suite requires an arch")
167     for j in get_architecture_suites(args[2].lower()):
168         print j.suite_name
169
170
171 def __suite_architecture_add(d, args):
172     if len(args) < 3:
173         die("E: adding a suite-architecture entry requires a suite and arch")
174
175     s = d.session()
176
177     suite = get_suite(args[2].lower(), s)
178     if suite is None: die("E: Can't find suite %s" % args[2].lower())
179
180     arch = get_architecture(args[3].lower(), s)
181     if arch is None: die("E: Can't find architecture %s" % args[3].lower())
182
183     if not dryrun:
184         try:
185             s.begin()
186             sa = SuiteArchitecture()
187             sa.arch_id = arch.arch_id
188             sa.suite_id = suite.suite_id
189             s.add(sa)
190             s.commit()
191         except IntegrityError, e:
192             die("E: Can't add suite-architecture entry (%s, %s) - probably already exists" % (args[2].lower(), args[3].lower()))
193         except SQLAlchemyError, e:
194             die("E: Can't add suite-architecture entry (%s, %s) - %s" % (args[2].lower(), args[3].lower(), e))
195
196     print "Added suite-architecture entry for %s, %s" % (args[2].lower(), args[3].lower())
197
198
199 def __suite_architecture_rm(d, args):
200     if len(args) < 3:
201         die("E: removing an suite-architecture entry requires a suite and arch")
202
203     s = d.session()
204     if not dryrun:
205         try:
206             s.begin()
207             sa = get_suite_architecture(args[2].lower(), args[3].lower(), s)
208             if sa is None:
209                 die("E: can't find suite-architecture entry for %s, %s" % (args[2].lower(), args[3].lower()))
210             s.delete(sa)
211             s.commit()
212         except IntegrityError, e:
213             die("E: Can't remove suite-architecture entry (%s, %s) - it's probably referenced" % (args[2].lower(), args[3].lower()))
214         except SQLAlchemyError, e:
215             die("E: Can't remove suite-architecture entry (%s, %s) - %s" % (args[2].lower(), args[3].lower(), e))
216
217     print "Removed suite-architecture entry for %s, %s" % (args[2].lower(), args[3].lower()) 
218
219
220 def suite_architecture(command):
221     args = [str(x) for x in command]
222     Cnf = utils.get_conf()
223     d = DBConn()
224
225     die_arglen(args, 2, "E: suite-architecture needs at least a command")
226
227     mode = args[1].lower()
228
229     if mode == 'list-arch':
230         __suite_architecture_listarch(d, args)
231     elif mode == 'list-suite':
232         __suite_architecture_listsuite(d, args)
233     elif mode == 'add':
234         __suite_architecture_add(d, args)
235     elif mode == 'rm':
236         __suite_architecture_rm(d, args)
237     else:
238         die("E: suite-architecture command unknown")
239
240 dispatch['suite-architecture'] = suite_architecture
241 dispatch['s-a'] = suite_architecture
242
243 ################################################################################
244
245 def main():
246     """Perform administrative work on the dak database"""
247     global dryrun
248     Cnf = utils.get_conf()
249     arguments = [('h', "help", "Admin::Options::Help"),
250                  ('n', "dry-run", "Admin::Options::Dry-Run")]
251     for i in [ "help", "dry-run" ]:
252         if not Cnf.has_key("Admin::Options::%s" % (i)):
253             Cnf["Admin::Options::%s" % (i)] = ""
254
255     arguments = apt_pkg.ParseCommandLine(Cnf, arguments, sys.argv)
256
257     options = Cnf.SubTree("Admin::Options")
258     if options["Help"] or len(arguments) < 1:
259         usage()
260     if options["Dry-Run"]:
261         dryrun = True
262
263     subcommand = str(arguments[0])
264
265     if subcommand in dispatch.keys():
266         dispatch[subcommand](arguments)
267     else:
268         die("E: Unknown command")
269
270 ################################################################################
271
272 if __name__ == '__main__':
273     main()