X-Git-Url: https://git.decadent.org.uk/gitweb/?p=dak.git;a=blobdiff_plain;f=dak%2Fadmin.py;h=60428cfb2afa0e5a761170ce49beeb98bcefd2ae;hp=8ba79797bdaf6345e6d5b1c3bd0206c8c3313c08;hb=0d69fff35ef45fda573467873ae2f01ca1954650;hpb=1617994b76d0cd90ce89a7e6d9f7bb886439f010 diff --git a/dak/admin.py b/dak/admin.py index 8ba79797..60428cfb 100755 --- a/dak/admin.py +++ b/dak/admin.py @@ -23,6 +23,9 @@ import sys import apt_pkg +import daklib.archive +import daklib.gpg + from daklib import utils from daklib.dbconn import * from sqlalchemy.orm.exc import NoResultFound @@ -65,6 +68,8 @@ Perform administrative work on the dak database. k list-all list all keyrings k list-binary list all keyrings with a NULL source acl k list-source list all keyrings with a non NULL source acl + k add-buildd NAME ARCH... add buildd keyring with upload permission + for the given architectures architecture / a: a list show a list of architectures @@ -75,18 +80,29 @@ Perform administrative work on the dak database. If SUITELIST is given, add to each of the suites at the same time + component: + component list show a list of components + component rm COMPONENT remove a component (will only work if + empty) + component add NAME DESCRIPTION ORDERING + add component NAME with DESCRIPTION. + Ordered at ORDERING. + suite / s: - s list show a list of suites + s list [--print-archive] + show a list of suites s show SUITE show config details for a suite s add SUITE VERSION [ label=LABEL ] [ description=DESCRIPTION ] [ origin=ORIGIN ] [ codename=CODENAME ] - [ signingkey=SIGNINGKEY ] + [ signingkey=SIGNINGKEY ] [ archive=ARCHIVE ] add suite SUITE, version VERSION. label, description, origin, codename and signingkey are optional. s add-all-arches SUITE VERSION... as "s add" but adds suite-architecture relationships for all architectures + s add-build-queue SUITE BUILD-QUEUE BUILD-QUEUE-CODENAME BUILD-QUEUE-ARCHIVE + add a build queue for an existing suite suite-architecture / s-a: s-a list show the architectures for all suites @@ -96,6 +112,17 @@ Perform administrative work on the dak database. s-a rm SUITE ARCH remove ARCH from suite (will only work if no packages remain for the arch in the suite) + suite-component / s-c: + s-c list show the architectures for all suites + s-c list-suite COMPONENT + show the suites a COMPONENT is in + s-c list-component SUITE + show the components in a SUITE + s-c add SUITE COMPONENT + add COMPONENT to suite + s-c rm SUITE COMPONENT remove component from suite (will only work if + no packages remain for the component in the suite) + archive: archive list list all archives archive add NAME ROOT DESCRIPTION [primary-mirror=MIRROR] [tainted=1] @@ -103,6 +130,7 @@ Perform administrative work on the dak database. primary mirror MIRROR. archive rm NAME remove archive NAME (will only work if there are no files and no suites in the archive) + archive rename OLD NEW rename archive OLD to NEW version-check / v-c: v-c list show version checks for all suites @@ -112,6 +140,14 @@ Perform administrative work on the dak database. where CHECK is one of Enhances, MustBeNewerThan, MustBeOlderThan REFERENCE is another suite name + + change-component: + change-component SUITE COMPONENT source SOURCE... + change-component SUITE COMPONENT binary BINARY... + Move source or binary packages to a different component by copying + associated files and changing the overrides. + + forget-signature FILE: forget that we saw FILE """ sys.exit(exit_code) @@ -190,10 +226,84 @@ dispatch['a'] = architecture ################################################################################ +def component_list(): + session = DBConn().session() + for component in session.query(Component).order_by(Component.component_name): + print "{0} ordering={1}".format(component.component_name, component.ordering) + +def component_add(args): + (name, description, ordering) = args[0:3] + + attributes = dict( + component_name=name, + description=description, + ordering=ordering, + ) + + for option in args[3:]: + (key, value) = option.split('=') + attributes[key] = value + + session = DBConn().session() + + component = Component() + for key, value in attributes.iteritems(): + setattr(component, key, value) + + session.add(component) + session.flush() + + if dryrun: + session.rollback() + else: + session.commit() + +def component_rm(name): + session = DBConn().session() + component = get_component(name, session) + session.delete(component) + session.flush() + + if dryrun: + session.rollback() + else: + session.commit() + +def component_rename(oldname, newname): + session = DBConn().session() + component = get_component(oldname, session) + component.component_name = newname + session.flush() + + if dryrun: + session.rollback() + else: + session.commit() + +def component(command): + mode = command[1] + if mode == 'list': + component_list() + elif mode == 'rename': + component_rename(command[2], command[3]) + elif mode == 'add': + component_add(command[2:]) + elif mode == 'rm': + component_rm(command[2]) + else: + die("E: component command unknown") + +dispatch['component'] = component + +################################################################################ + def __suite_list(d, args): s = d.session() - for j in s.query(Suite).order_by(Suite.suite_name).all(): - print j.suite_name + for j in s.query(Suite).join(Suite.archive).order_by(Archive.archive_name, Suite.suite_name).all(): + if len(args) > 2 and args[2] == "--print-archive": + print "{0} {1}".format(j.archive.archive_name, j.suite_name) + else: + print "{0}".format(j.suite_name) def __suite_show(d, args): if len(args) < 2: @@ -212,6 +322,9 @@ def __suite_add(d, args, addallarches=False): version = args[3] rest = args[3:] + if len(version) == 0: + version = None + def get_field(field): for varval in args: if varval.startswith(field + '='): @@ -258,6 +371,73 @@ def __suite_add(d, args, addallarches=False): s.commit() +def __suite_rm(d, args): + die_arglen(args, 3, "E: removing a suite requires at least a name") + name = args[2] + print "Removing suite {0}".format(name) + if not dryrun: + try: + s = d.session() + su = get_suite(name.lower()) + if su is None: + die("E: Cannot find suite {0}".format(name)) + s.delete(su) + s.commit() + except IntegrityError as e: + die("E: Integrity error removing suite {0} (suite-arch entries probably still exist)".format(name)) + except SQLAlchemyError as e: + die("E: Error removing suite {0} ({1})".format(name, e)) + print "Suite {0} removed".format(name) + +def __suite_add_build_queue(d, args): + session = d.session() + + die_arglen(args, 6, "E: Adding a build queue needs four parameters.") + + suite_name = args[2] + build_queue_name = args[3] + build_queue_codename = args[4] + build_queue_archive_name = args[5] + try: + suite = session.query(Suite).filter_by(suite_name=suite_name).one() + except NoResultFound: + die("E: Unknown suite '{0}'".format(suite_name)) + try: + build_queue_archive = session.query(Archive).filter_by(archive_name=build_queue_archive_name).one() + except NoResultFound: + die("E: Unknown archive '{0}'".format(build_queue_archive_name)) + + # Create suite + s = Suite() + s.suite_name = build_queue_name + s.origin = suite.origin + s.label = suite.label + s.description = "buildd {0} incoming".format(suite_name) + s.codename = build_queue_codename + s.notautomatic = suite.notautomatic + s.overridesuite = suite.overridesuite or suite.suite_name + s.butautomaticupgrades = suite.butautomaticupgrades + s.signingkeys = suite.signingkeys + s.include_long_description = False + + s.archive = build_queue_archive + s.architectures.extend(suite.architectures) + s.components.extend(suite.components) + s.srcformats.extend(suite.srcformats) + + session.add(s) + session.flush() + + bq = BuildQueue() + bq.queue_name = build_queue_codename + bq.suite = s + + session.add(bq) + session.flush() + + suite.copy_queues.append(bq) + + session.commit() def suite(command): args = [str(x) for x in command] @@ -272,10 +452,14 @@ def suite(command): __suite_list(d, args) elif mode == 'show': __suite_show(d, args) + elif mode == 'rm': + __suite_rm(d, args) elif mode == 'add': __suite_add(d, args, False) elif mode == 'add-all-arches': __suite_add(d, args, True) + elif mode == 'add-build-queue': + __suite_add_build_queue(d, args) else: die("E: suite command unknown") @@ -319,20 +503,24 @@ def __suite_architecture_add(d, args): suite = get_suite(args[2].lower(), s) if suite is None: die("E: Can't find suite %s" % args[2].lower()) - arch = get_architecture(args[3].lower(), s) - if arch is None: die("E: Can't find architecture %s" % args[3].lower()) + for arch_name in args[3:]: + arch = get_architecture(arch_name.lower(), s) + if arch is None: die("E: Can't find architecture %s" % args[3].lower()) - if not dryrun: try: suite.architectures.append(arch) - s.commit() + s.flush() except IntegrityError as e: - die("E: Can't add suite-architecture entry (%s, %s) - probably already exists" % (args[2].lower(), args[3].lower())) + die("E: Can't add suite-architecture entry (%s, %s) - probably already exists" % (args[2].lower(), arch_name)) except SQLAlchemyError as e: - die("E: Can't add suite-architecture entry (%s, %s) - %s" % (args[2].lower(), args[3].lower(), e)) + die("E: Can't add suite-architecture entry (%s, %s) - %s" % (args[2].lower(), arch_name, e)) + + print "Added suite-architecture entry for %s, %s" % (args[2].lower(), arch_name) - print "Added suite-architecture entry for %s, %s" % (args[2].lower(), args[3].lower()) + if not dryrun: + s.commit() + s.close() def __suite_architecture_rm(d, args): if len(args) < 3: @@ -386,6 +574,111 @@ dispatch['s-a'] = suite_architecture ################################################################################ +def __suite_component_list(d, args): + s = d.session() + for j in s.query(Suite).order_by(Suite.suite_name): + components = j.components + print j.suite_name + ': ' + \ + ', '.join([c.component_name for c in components]) + + +def __suite_component_listcomponent(d, args): + die_arglen(args, 3, "E: suite-component list-component requires a suite") + suite = get_suite(args[2].lower(), d.session()) + if suite is None: + die('E: suite %s is invalid' % args[2].lower()) + for c in suite.components: + print c.component_name + + +def __suite_component_listsuite(d, args): + die_arglen(args, 3, "E: suite-component list-suite requires an component") + component = get_component(args[2].lower(), d.session()) + if component is None: + die("E: component %s is invalid" % args[2].lower()) + for s in component.suites: + print s.suite_name + + +def __suite_component_add(d, args): + if len(args) < 3: + die("E: adding a suite-component entry requires a suite and component") + + s = d.session() + + suite = get_suite(args[2].lower(), s) + if suite is None: die("E: Can't find suite %s" % args[2].lower()) + + for component_name in args[3:]: + component = get_component(component_name.lower(), s) + if component is None: die("E: Can't find component %s" % args[3].lower()) + + try: + suite.components.append(component) + s.flush() + except IntegrityError as e: + die("E: Can't add suite-component entry (%s, %s) - probably already exists" % (args[2].lower(), component_name)) + except SQLAlchemyError as e: + die("E: Can't add suite-component entry (%s, %s) - %s" % (args[2].lower(), component_name, e)) + + print "Added suite-component entry for %s, %s" % (args[2].lower(), component_name) + + if not dryrun: + s.commit() + s.close() + +def __suite_component_rm(d, args): + if len(args) < 3: + die("E: removing an suite-component entry requires a suite and component") + + s = d.session() + if not dryrun: + try: + suite_name = args[2].lower() + suite = get_suite(suite_name, s) + if suite is None: + die('E: no such suite %s' % suite_name) + component_string = args[3].lower() + component = get_component(arch_string, s) + if component not in suite.components: + die("E: component %s not found in suite %s" % (component_string, suite_name)) + suite.components.remove(component) + s.commit() + except IntegrityError as e: + die("E: Can't remove suite-component entry (%s, %s) - it's probably referenced" % (args[2].lower(), args[3].lower())) + except SQLAlchemyError as e: + die("E: Can't remove suite-component entry (%s, %s) - %s" % (args[2].lower(), args[3].lower(), e)) + + print "Removed suite-component entry for %s, %s" % (args[2].lower(), args[3].lower()) + + +def suite_component(command): + args = [str(x) for x in command] + Cnf = utils.get_conf() + d = DBConn() + + die_arglen(args, 2, "E: suite-component needs at least a command") + + mode = args[1].lower() + + if mode == 'list': + __suite_component_list(d, args) + elif mode == 'list-component': + __suite_component_listcomponent(d, args) + elif mode == 'list-suite': + __suite_component_listsuite(d, args) + elif mode == 'add': + __suite_component_add(d, args) + # elif mode == 'rm': + # __suite_architecture_rm(d, args) + else: + die("E: suite-component command unknown") + +dispatch['suite-component'] = suite_component +dispatch['s-c'] = suite_component + +################################################################################ + def archive_list(): session = DBConn().session() for archive in session.query(Archive).order_by(Archive.archive_name): @@ -420,7 +713,7 @@ def archive_add(args): def archive_rm(name): session = DBConn().session() - archive = session.query(Archive).filter_by(archive_name=name).one() + archive = get_archive(name, session) session.delete(archive) session.flush() @@ -429,10 +722,23 @@ def archive_rm(name): else: session.commit() +def archive_rename(oldname, newname): + session = DBConn().session() + archive = get_archive(oldname, session) + archive.archive_name = newname + session.flush() + + if dryrun: + session.rollback() + else: + session.commit() + def archive(command): mode = command[1] if mode == 'list': archive_list() + elif mode == 'rename': + archive_rename(command[2], command[3]) elif mode == 'add': archive_add(command[2:]) elif mode == 'rm': @@ -595,8 +901,109 @@ def show_keyring(command): for k in q.all(): print k.keyring_name -dispatch['keyring'] = show_keyring -dispatch['k'] = show_keyring +def keyring_add_buildd(command): + name = command[2] + arch_names = command[3:] + + session = DBConn().session() + arches = session.query(Architecture).filter(Architecture.arch_string.in_(arch_names)) + + acl = ACL() + acl.name = 'buildd-{0}'.format('+'.join(arch_names)) + acl.architectures.update(arches) + acl.allow_new = True + acl.allow_binary = True + acl.allow_binary_only = True + acl.allow_hijack = True + session.add(acl) + + k = Keyring() + k.keyring_name = name + k.acl = acl + k.priority = 10 + session.add(k) + + session.commit() + +def keyring(command): + if command[1].startswith('list-'): + show_keyring(command) + elif command[1] == 'add-buildd': + keyring_add_buildd(command) + else: + die("E: keyring command unknown") + +dispatch['keyring'] = keyring +dispatch['k'] = keyring + +################################################################################ + +def change_component_source(transaction, suite, component, source_names): + session = transaction.session + + overrides = session.query(Override).filter(Override.package.in_(source_names)).filter_by(suite=suite).join(OverrideType).filter_by(overridetype='dsc') + for override in overrides: + print "Changing override for {0}".format(override.package) + override.component = component + session.flush() + + sources = session.query(DBSource).filter(DBSource.source.in_(source_names)).filter(DBSource.suites.contains(suite)) + for source in sources: + print "Copying {0}={1}".format(source.source, source.version) + transaction.copy_source(source, suite, component) + +def change_component_binary(transaction, suite, component, binary_names): + session = transaction.session + + overrides = session.query(Override).filter(Override.package.in_(binary_names)).filter_by(suite=suite).join(OverrideType).filter(OverrideType.overridetype.in_(['deb', 'udeb'])) + for override in overrides: + print "Changing override for {0}".format(override.package) + override.component = component + session.flush() + + binaries = session.query(DBBinary).filter(DBBinary.package.in_(binary_names)).filter(DBBinary.suites.contains(suite)) + for binary in binaries: + print "Copying {0}={1} [{2}]".format(binary.package, binary.version, binary.architecture.arch_string) + transaction.copy_binary(binary, suite, component) + pass + +def change_component(args): + with daklib.archive.ArchiveTransaction() as transaction: + session = transaction.session + + suite = session.query(Suite).filter_by(suite_name=args[1]).one() + component = session.query(Component).filter_by(component_name=args[2]).one() + + if args[3] == 'source': + change_component_source(transaction, suite, component, args[4:]) + elif args[3] == 'binary': + change_component_binary(transaction, suite, component, args[4:]) + else: + raise Exception("Can only move source or binary, not {0}".format(args[3])) + + transaction.commit() + +dispatch['change-component'] = change_component + +################################################################################ + +def forget_signature(args): + filename = args[1] + with open(filename, 'r') as fh: + data = fh.read() + + session = DBConn().session() + keyrings = [ k.keyring_name for k in session.query(Keyring).filter_by(active=True).order_by(Keyring.priority) ] + signed_file = daklib.gpg.SignedFile(data, keyrings) + history = SignatureHistory.from_signed_file(signed_file).query(session) + if history is not None: + session.delete(history) + session.commit() + else: + print "Signature was not known to dak." + session.rollback() + +dispatch['forget-signature'] = forget_signature ################################################################################