]> git.decadent.org.uk Git - dak.git/blob - dak/admin.py
Remove SuiteArchitecture from admin.py.
[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
29 ################################################################################
30
31 dispatch = {}
32 dryrun = False
33
34 ################################################################################
35 def warn(msg):
36     print >> sys.stderr, msg
37
38 def die(msg, exit_code=1):
39     print >> sys.stderr, msg
40     sys.exit(exit_code)
41
42 def die_arglen(args, args_needed, msg):
43     if len(args) < args_needed:
44         die(msg)
45
46 def usage(exit_code=0):
47     """Perform administrative work on the dak database."""
48
49     print """Usage: dak admin COMMAND
50 Perform administrative work on the dak database.
51
52   -h, --help          show this help and exit.
53   -n, --dry-run       don't do anything, just show what would have been done
54                       (only applies to add or rm operations).
55
56   Commands can use a long or abbreviated form:
57
58   config / c:
59      c db                   show db config
60      c db-shell             show db config in a usable form for psql
61
62   architecture / a:
63      a list                 show a list of architectures
64      a rm ARCH              remove an architecture (will only work if
65                             no longer linked to any suites)
66      a add ARCH DESCRIPTION [SUITELIST]
67                             add architecture ARCH with DESCRIPTION.
68                             If SUITELIST is given, add to each of the
69                             suites at the same time
70
71   suite / s:
72      s list                 show a list of suites
73      s show SUITE           show config details for a suite
74      s add SUITE VERSION [ label=LABEL ] [ description=DESCRIPTION ]
75                          [ origin=ORIGIN ] [ codename=CODENAME ]
76                             add suite SUITE, version VERSION. label,
77                             description, origin and codename are optional.
78
79   suite-architecture / s-a:
80      s-a list-suite ARCH    show the suites an ARCH is in
81      s-a list-arch SUITE    show the architectures in a SUITE
82      s-a add SUITE ARCH     add ARCH to suite
83      s-a rm SUITE ARCH      remove ARCH from suite (will only work if
84                             no packages remain for the arch in the suite)
85 """
86     sys.exit(exit_code)
87
88 ################################################################################
89
90 def __architecture_list(d, args):
91     q = d.session().query(Architecture).order_by('arch_string')
92     for j in q.all():
93         # HACK: We should get rid of source from the arch table
94         if j.arch_string == 'source': continue
95         print j.arch_string
96     sys.exit(0)
97
98 def __architecture_add(d, args):
99     die_arglen(args, 4, "E: adding an architecture requires a name and a description")
100     print "Adding architecture %s" % args[2]
101     suites = [str(x) for x in args[4:]]
102     print "Adding to suites %s" % ", ".join(suites)
103     if not dryrun:
104         try:
105             s = d.session()
106             a = Architecture()
107             a.arch_string = str(args[2]).lower()
108             a.description = str(args[3])
109             s.add(a)
110             for sn in suites:
111                 su = get_suite(sn, s)
112                 if su is not None:
113                     a.suites.append(su)
114                 else:
115                     warn("W: Cannot find suite %s" % su)
116             s.commit()
117         except IntegrityError, e:
118             die("E: Integrity error adding architecture %s (it probably already exists)" % args[2])
119         except SQLAlchemyError, e:
120             die("E: Error adding architecture %s (%s)" % (args[2], e))
121     print "Architecture %s added" % (args[2])
122
123 def __architecture_rm(d, args):
124     die_arglen(args, 3, "E: removing an architecture requires at least a name")
125     print "Removing architecture %s" % args[2]
126     if not dryrun:
127         try:
128             s = d.session()
129             a = get_architecture(args[2].lower(), s)
130             if a is None:
131                 die("E: Cannot find architecture %s" % args[2])
132             s.delete(a)
133             s.commit()
134         except IntegrityError, e:
135             die("E: Integrity error removing architecture %s (suite-arch entries probably still exist)" % args[2])
136         except SQLAlchemyError, e:
137             die("E: Error removing architecture %s (%s)" % (args[2], e))
138     print "Architecture %s removed" % args[2]
139
140 def architecture(command):
141     args = [str(x) for x in command]
142     Cnf = utils.get_conf()
143     d = DBConn()
144
145     die_arglen(args, 2, "E: architecture needs at least a command")
146
147     mode = args[1].lower()
148     if mode == 'list':
149         __architecture_list(d, args)
150     elif mode == 'add':
151         __architecture_add(d, args)
152     elif mode == 'rm':
153         __architecture_rm(d, args)
154     else:
155         die("E: architecture command unknown")
156
157 dispatch['architecture'] = architecture
158 dispatch['a'] = architecture
159
160 ################################################################################
161
162 def __suite_list(d, args):
163     s = d.session()
164     for j in s.query(Suite).order_by('suite_name').all():
165         print j.suite_name
166
167 def __suite_show(d, args):
168     if len(args) < 2:
169         die("E: showing an suite entry requires a suite")
170
171     s = d.session()
172     su = get_suite(args[2].lower())
173     if su is None:
174         die("E: can't find suite entry for %s" % (args[2].lower()))
175
176     print su.details()
177
178 def __suite_add(d, args):
179     die_arglen(args, 4, "E: adding a suite requires at least a name and a version")
180     suite_name = args[2].lower()
181     version = args[3]
182     rest = args[3:]
183
184     def get_field(field):
185         for varval in args:
186             if varval.startswith(field + '='):
187                 return varval.split('=')[1]
188         return None
189
190     print "Adding suite %s" % suite_name
191     if not dryrun:
192         try:
193             s = d.session()
194             suite = Suite()
195             suite.suite_name = suite_name
196             suite.version = version
197             suite.label = get_field('label')
198             suite.description = get_field('description')
199             suite.origin = get_field('origin')
200             suite.codename = get_field('codename')
201             s.add(suite)
202             s.commit()
203         except IntegrityError, e:
204             die("E: Integrity error adding suite %s (it probably already exists)" % suite_name)
205         except SQLAlchemyError, e:
206             die("E: Error adding suite %s (%s)" % (suite_name, e))
207     print "Suite %s added" % (suite_name)
208
209 def suite(command):
210     args = [str(x) for x in command]
211     Cnf = utils.get_conf()
212     d = DBConn()
213
214     die_arglen(args, 2, "E: suite needs at least a command")
215
216     mode = args[1].lower()
217
218     if mode == 'list':
219         __suite_list(d, args)
220     elif mode == 'show':
221         __suite_show(d, args)
222     elif mode == 'add':
223         __suite_add(d, args)
224     else:
225         die("E: suite command unknown")
226
227 dispatch['suite'] = suite
228 dispatch['s'] = suite
229
230 ################################################################################
231
232 def __suite_architecture_list(d, args):
233     s = d.session()
234     for j in s.query(Suite).order_by('suite_name').all():
235         print j.suite_name + ' ' + \
236               ','.join([a.architecture.arch_string for a in j.suitearchitectures])
237
238 def __suite_architecture_listarch(d, args):
239     die_arglen(args, 3, "E: suite-architecture list-arch requires a suite")
240     a = get_suite_architectures(args[2].lower())
241     for j in a:
242         # HACK: We should get rid of source from the arch table
243         if j.arch_string != 'source':
244             print j.arch_string
245
246
247 def __suite_architecture_listsuite(d, args):
248     die_arglen(args, 3, "E: suite-architecture list-suite requires an arch")
249     for j in get_architecture_suites(args[2].lower()):
250         print j.suite_name
251
252
253 def __suite_architecture_add(d, args):
254     if len(args) < 3:
255         die("E: adding a suite-architecture entry requires a suite and arch")
256
257     s = d.session()
258
259     suite = get_suite(args[2].lower(), s)
260     if suite is None: die("E: Can't find suite %s" % args[2].lower())
261
262     arch = get_architecture(args[3].lower(), s)
263     if arch is None: die("E: Can't find architecture %s" % args[3].lower())
264
265     if not dryrun:
266         try:
267             suite.architectures.append(arch)
268             s.commit()
269         except IntegrityError, e:
270             die("E: Can't add suite-architecture entry (%s, %s) - probably already exists" % (args[2].lower(), args[3].lower()))
271         except SQLAlchemyError, e:
272             die("E: Can't add suite-architecture entry (%s, %s) - %s" % (args[2].lower(), args[3].lower(), e))
273
274     print "Added suite-architecture entry for %s, %s" % (args[2].lower(), args[3].lower())
275
276
277 def __suite_architecture_rm(d, args):
278     if len(args) < 3:
279         die("E: removing an suite-architecture entry requires a suite and arch")
280
281     s = d.session()
282     if not dryrun:
283         try:
284             suite_name = args[2].lower()
285             suite = get_suite(suite_name, s)
286             if suite is None:
287                 die('E: no such suite %s' % suite_name)
288             arch_string = args[3].lower()
289             architecture = get_architecture(arch_string, s)
290             if architecture not in suite.architectures:
291                 die("E: architecture %s not found in suite %s" % (arch_string, suite_name))
292             suite.architectures.remove(architecture)
293             s.commit()
294         except IntegrityError, e:
295             die("E: Can't remove suite-architecture entry (%s, %s) - it's probably referenced" % (args[2].lower(), args[3].lower()))
296         except SQLAlchemyError, e:
297             die("E: Can't remove suite-architecture entry (%s, %s) - %s" % (args[2].lower(), args[3].lower(), e))
298
299     print "Removed suite-architecture entry for %s, %s" % (args[2].lower(), args[3].lower())
300
301
302 def suite_architecture(command):
303     args = [str(x) for x in command]
304     Cnf = utils.get_conf()
305     d = DBConn()
306
307     die_arglen(args, 2, "E: suite-architecture needs at least a command")
308
309     mode = args[1].lower()
310
311     if mode == 'list':
312         __suite_architecture_list(d, args)
313     elif mode == 'list-arch':
314         __suite_architecture_listarch(d, args)
315     elif mode == 'list-suite':
316         __suite_architecture_listsuite(d, args)
317     elif mode == 'add':
318         __suite_architecture_add(d, args)
319     elif mode == 'rm':
320         __suite_architecture_rm(d, args)
321     else:
322         die("E: suite-architecture command unknown")
323
324 dispatch['suite-architecture'] = suite_architecture
325 dispatch['s-a'] = suite_architecture
326
327 ################################################################################
328
329 def show_config(command):
330     args = [str(x) for x in command]
331     cnf = utils.get_conf()
332
333     die_arglen(args, 2, "E: config needs at least a command")
334
335     mode = args[1].lower()
336
337     if mode == 'db':
338         connstr = ""
339         if cnf["DB::Host"]:
340             # TCP/IP
341             connstr = "postgres://%s" % cnf["DB::Host"]
342             if cnf["DB::Port"] and cnf["DB::Port"] != "-1":
343                 connstr += ":%s" % cnf["DB::Port"]
344             connstr += "/%s" % cnf["DB::Name"]
345         else:
346             # Unix Socket
347             connstr = "postgres:///%s" % cnf["DB::Name"]
348             if cnf["DB::Port"] and cnf["DB::Port"] != "-1":
349                 connstr += "?port=%s" % cnf["DB::Port"]
350         print connstr
351     elif mode == 'db-shell':
352         e = ['PGDATABASE']
353         print "PGDATABASE=%s" % cnf["DB::Name"]
354         if cnf["DB::Host"]:
355             print "PGHOST=%s" % cnf["DB::Host"]
356             e.append('PGHOST')
357         if cnf["DB::Port"] and cnf["DB::Port"] != "-1":
358             print "PGPORT=%s" % cnf["DB::Port"]
359             e.append('PGPORT')
360         print "export " + " ".join(e)
361     else:
362         die("E: config command unknown")
363
364 dispatch['config'] = show_config
365 dispatch['c'] = show_config
366
367 ################################################################################
368
369 def main():
370     """Perform administrative work on the dak database"""
371     global dryrun
372     Cnf = utils.get_conf()
373     arguments = [('h', "help", "Admin::Options::Help"),
374                  ('n', "dry-run", "Admin::Options::Dry-Run")]
375     for i in [ "help", "dry-run" ]:
376         if not Cnf.has_key("Admin::Options::%s" % (i)):
377             Cnf["Admin::Options::%s" % (i)] = ""
378
379     arguments = apt_pkg.ParseCommandLine(Cnf, arguments, sys.argv)
380
381     options = Cnf.SubTree("Admin::Options")
382     if options["Help"] or len(arguments) < 1:
383         usage()
384     if options["Dry-Run"]:
385         dryrun = True
386
387     subcommand = str(arguments[0])
388
389     if subcommand in dispatch.keys():
390         dispatch[subcommand](arguments)
391     else:
392         die("E: Unknown command")
393
394 ################################################################################
395
396 if __name__ == '__main__':
397     main()