"Sync PostgreSQL users with passwd file"),
("init-db",
"Update the database to match the conf file"),
+ ("update-db",
+ "Updates databae schema to latest revision"),
("init-dirs",
"Initial setup of the archive"),
("make-maintainers",
--- /dev/null
+#!/usr/bin/env python
+
+# Debian Archive Kit Database Update Script
+# Copyright (C) 2008 Michael Casadevall <mcasadevall@debian.org>
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+################################################################################
+
+# <tomv_w> really, if we want to screw ourselves, let's find a better way.
+# <Ganneff> rm -rf /srv/ftp.debian.org
+
+################################################################################
+
+import psycopg2
+
+################################################################################
+
+def do_update(self):
+ print "Adding DM fields to database"
+
+ try:
+ c = self.db.cursor()
+ c.execute("ALTER TABLE source ADD COLUMN dm_upload_allowed BOOLEAN DEFAULT 'no' NOT NULL;")
+ c.execute("ALTER TABLE uid ADD COLUMN debian_maintainer BOOLEAN DEFAULT 'false' NOT NULL;")
+
+ print "Migrating DM data to source table. This might take some time ..."
+
+ c.execute("UPDATE source SET dm_upload_allowed = 't' WHERE id = (SELECT source FROM src_uploaders);")
+ c.execute("UPDATE config SET value = '1' WHERE name = 'db_revision'")
+ self.db.commit()
+
+ print "REMINDER: Remember to run the updated byhand-dm crontab to update Debian Maintainer information"
+
+ except psycopg2.ProgrammingError, msg:
+ self.db.rollback()
+ print "FATAL: Unable to apply DM table update 1!"
+ print "Error Message: " + str(msg)
+ print "Database changes have been rolled back."
print """Usage: dak import-keyring [OPTION]... [KEYRING]
-h, --help show this help and exit.
-L, --import-ldap-users generate uid entries for keyring from LDAP
- -U, --generate-users FMT generate uid entries from keyring as FMT"""
+ -U, --generate-users FMT generate uid entries from keyring as FMT
+ -D, --debian-maintainer mark generated uids as debian-maintainers"""
sys.exit(exit_code)
Arguments = [('h',"help","Import-Keyring::Options::Help"),
('L',"import-ldap-users","Import-Keyring::Options::Import-Ldap-Users"),
('U',"generate-users","Import-Keyring::Options::Generate-Users", "HasArg"),
- ]
+ ('D',"debian-maintainer","Import-Keyring::Options::Debian-Maintainer"),
+ ]
for i in [ "help", "report-changes", "generate-users", "import-ldap-users" ]:
if not Cnf.has_key("Import-Keyring::Options::%s" % (i)):
# For the keys in this keyring, add/update any fingerprints that've
# changed.
+ # Determine if we need to set the DM flag
+ is_dm = "no"
+ if Cnf("Import-Keyring::Options::Debian-Maintainer"):
+ is_dm = "yes"
+
for f in fpr:
newuid = fpr[f][0]
newuiduid = db_uid_byid.get(newuid, [None])[0]
if oldfid == -1:
changes.append((newuiduid, "Added key: %s" % (f)))
if newuid:
- projectB.query("INSERT INTO fingerprint (fingerprint, uid, keyring) VALUES ('%s', %d, %d)" % (f, newuid, keyring_id))
+ projectB.query("INSERT INTO fingerprint (fingerprint, uid, keyring, debian_maintainer) VALUES ('%s', %d, %d, %s)" % (f, newuid, keyring_id, is_dm))
else:
- projectB.query("INSERT INTO fingerprint (fingerprint, keyring) VALUES ('%s', %d)" % (f, keyring_id))
+ projectB.query("INSERT INTO fingerprint (fingerprint, keyring) VALUES ('%s', %d, %s)" % (f, keyring_id, is_dm))
else:
if newuid and olduid != newuid:
if olduid != -1:
db_uid_name = {}
ldap_fin_uid_id = {}
q = projectB.query("""
-SELECT f.fingerprint, f.id, u.uid FROM fingerprint f, uid u WHERE f.uid = u.id
+SELECT f.fingerprint, f.id, u.uid, u.debian_maintainer FROM fingerprint f, uid u WHERE f.uid = u.id
UNION SELECT f.fingerprint, f.id, null FROM fingerprint f where f.uid is null""")
for i in q.getresult():
(fingerprint, fingerprint_id, uid) = i
- db_fin_uid[fingerprint] = (uid, fingerprint_id)
+ db_fin_uid[fingerprint] = (uid, fingerprint_id, debian_maintainer)
q = projectB.query("SELECT id, name FROM uid")
for i in q.getresult():
for fingerprint in fingerprints:
ldap_fin_uid_id[fingerprint] = (uid, uid_id)
if db_fin_uid.has_key(fingerprint):
- (existing_uid, fingerprint_id) = db_fin_uid[fingerprint]
+ (existing_uid, fingerprint_id, is_dm) = db_fin_uid[fingerprint]
if not existing_uid:
q = projectB.query("UPDATE fingerprint SET uid = %s WHERE id = %s" % (uid_id, fingerprint_id))
print "Assigning %s to 0x%s." % (uid, fingerprint)
elif existing_uid == uid:
pass
- elif existing_uid[:3] == "dm:":
- q = projectB.query("UPDATE fingerprint SET uid = %s WHERE id = %s" % (uid_id, fingerprint_id))
+ elif is_dm = "t":
+ q = projectB.query("UPDATE fingerprint SET uid = %s AND debian_maintainer = 'f' WHERE id = %s" % (uid_id, fingerprint_id))
print "Promoting DM %s to DD %s with keyid 0x%s." % (existing_uid, uid, fingerprint)
else:
utils.warn("%s has %s in LDAP, but projectB says it should be %s." % (uid, fingerprint, existing_uid))
filename = files[file]["pool name"] + file
dsc_component = files[file]["component"]
dsc_location_id = files[file]["location id"]
+ if dsc.has_key("dm-upload-allowed") and dsc["dm-upload-allowed"] == "yes":
+ dm_upload_allowed = "true"
+ else:
+ dm_upload_allowed = "false"
if not files[file].has_key("files id") or not files[file]["files id"]:
files[file]["files id"] = database.set_files_id (filename, files[file]["size"], files[file]["md5sum"], files[file]["sha1sum"], files[file]["sha256sum"], dsc_location_id)
- projectB.query("INSERT INTO source (source, version, maintainer, changedby, file, install_date, sig_fpr) VALUES ('%s', '%s', %d, %d, %d, '%s', %s)"
- % (package, version, maintainer_id, changedby_id, files[file]["files id"], install_date, fingerprint_id))
+ projectB.query("INSERT INTO source (source, version, maintainer, changedby, file, install_date, sig_fpr, dm_upload_allowed) VALUES ('%s', '%s', %d, %d, %d, '%s', %s, %s)"
+ % (package, version, maintainer_id, changedby_id, files[file]["files id"], install_date, fingerprint_id, dm_upload_allowed))
for suite in changes["distribution"].keys():
suite_id = database.get_suite_id(suite)
projectB.query("INSERT INTO dsc_files (source, file) VALUES (currval('source_id_seq'), %d)" % (files_id))
# Add the src_uploaders to the DB
- if dsc.get("dm-upload-allowed", "no") == "yes":
- uploader_ids = [maintainer_id]
- if dsc.has_key("uploaders"):
- for u in dsc["uploaders"].split(","):
- u = u.replace("'", "\\'")
- u = u.strip()
- uploader_ids.append(
- database.get_or_set_maintainer_id(u))
- added_ids = {}
- for u in uploader_ids:
- if added_ids.has_key(u):
- utils.warn("Already saw uploader %s for source %s" % (u, package))
- continue
- added_ids[u]=1
- projectB.query("INSERT INTO src_uploaders (source, maintainer) VALUES (currval('source_id_seq'), %d)" % (u))
+ uploader_ids = [maintainer_id]
+ if dsc.has_key("uploaders"):
+ for u in dsc["uploaders"].split(","):
+ u = u.replace("'", "\\'")
+ u = u.strip()
+ uploader_ids.append(
+ database.get_or_set_maintainer_id(u))
+ added_ids = {}
+ for u in uploader_ids:
+ if added_ids.has_key(u):
+ utils.warn("Already saw uploader %s for source %s" % (u, package))
+ continue
+ added_ids[u]=1
+ projectB.query("INSERT INTO src_uploaders (source, maintainer) VALUES (currval('source_id_seq'), %d)" % (u))
# Add the .deb files to the DB
################################################################################
def lookup_uid_from_fingerprint(fpr):
- q = Upload.projectB.query("SELECT u.uid, u.name FROM fingerprint f, uid u WHERE f.uid = u.id AND f.fingerprint = '%s'" % (fpr))
+ q = Upload.projectB.query("SELECT u.uid, u.name, u.debian_maintainer FROM fingerprint f, uid u WHERE f.uid = u.id AND f.fingerprint = '%s'" % (fpr))
qs = q.getresult()
if len(qs) == 0:
return (None, None)
def check_signed_by_key():
"""Ensure the .changes is signed by an authorized uploader."""
- (uid, uid_name) = lookup_uid_from_fingerprint(changes["fingerprint"])
+ (uid, uid_name, is_dm) = lookup_uid_from_fingerprint(changes["fingerprint"])
if uid_name == None:
uid_name = ""
may_nmu, may_sponsor = 1, 1
# XXX by default new dds don't have a fingerprint/uid in the db atm,
# and can't get one in there if we don't allow nmu/sponsorship
- elif uid[:3] == "dm:":
- uid_email = uid[3:]
+ elif is_dm is "t":
+ uid_email = uid
may_nmu, may_sponsor = 0, 0
else:
uid_email = "%s@debian.org" % (uid)
if not sponsored and not may_nmu:
source_ids = []
- check_suites = changes["distribution"].keys()
- if "unstable" not in check_suites: check_suites.append("unstable")
- for suite in check_suites:
- suite_id = database.get_suite_id(suite)
- q = Upload.projectB.query("SELECT s.id FROM source s JOIN src_associations sa ON (s.id = sa.source) WHERE s.source = '%s' AND sa.suite = %d" % (changes["source"], suite_id))
- for si in q.getresult():
- if si[0] not in source_ids: source_ids.append(si[0])
-
- is_nmu = 1
- for si in source_ids:
- is_nmu = 1
- q = Upload.projectB.query("SELECT m.name FROM maintainer m WHERE m.id IN (SELECT maintainer FROM src_uploaders WHERE src_uploaders.source = %s)" % (si))
+ q = Upload.projectB.query("SELECT s.id, s.version FROM source s JOIN src_associations sa ON (s.id = sa.source) WHERE s.source = '%s' AND s.dm_upload_allowed = 'yes'" % (changes["source"]))
+
+ highest_sid, highest_version = None, None
+
+ should_reject = True
+ for si in q.getresult():
+ if highest_version == None or apt_pkg.VersionCompare(si[1], highest_version) == 1:
+ highest_sid = si[0]
+ highest_version = si[1]
+
+ if highest_sid == None:
+ reject("Source package %s does not have 'DM-Upload-Allowed: yes' in its most recent version" % changes["source"])
+ else:
+ q = Upload.projectB.query("SELECT m.name FROM maintainer m WHERE m.id IN (SELECT su.maintainer FROM src_uploaders su JOIN source s ON (s.id = su.source) WHERE su.source = %s)" % (highest_sid))
for m in q.getresult():
(rfc822, rfc2047, name, email) = utils.fix_maintainer(m[0])
if email == uid_email or name == uid_name:
- is_nmu=0
+ should_reject=True
break
- if is_nmu:
- reject("%s may not upload/NMU source package %s" % (uid, changes["source"]))
+
+ if should_reject == True:
+ reject("%s is not in Maintainer or Uploaders of source package %s" % (uid, changes["source"]))
for b in changes["binary"].keys():
for suite in changes["distribution"].keys():
--- /dev/null
+#!/usr/bin/env python
+
+# Debian Archive Kit Database Update Script
+# Copyright (C) 2008 Michael Casadevall <mcasadevall@debian.org>
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+################################################################################
+
+# <Ganneff> when do you have it written?
+# <NCommander> Ganneff, after you make my debian account
+# <Ganneff> blackmail wont work
+# <NCommander> damn it
+
+################################################################################
+
+import psycopg2, sys, fcntl, os
+import apt_pkg
+import time
+from daklib import database
+from daklib import utils
+
+################################################################################
+
+Cnf = None
+projectB = None
+required_database_schema = 1
+
+################################################################################
+
+class UpdateDB:
+ def usage (self, exit_code=0):
+ print """Usage: dak update-db
+Updates dak's database schema to the lastest version. You should disable crontabs while this is running
+
+ -h, --help show this help and exit."""
+ sys.exit(exit_code)
+
+
+################################################################################
+
+ def update_db_to_zero(self):
+ # This function will attempt to update a pre-zero database schema to zero
+
+ # First, do the sure thing, and create the configuration table
+ try:
+ print "Creating configuration table ..."
+ c = self.db.cursor()
+ c.execute("""CREATE TABLE config (
+ id SERIAL PRIMARY KEY NOT NULL,
+ name TEXT UNIQUE NOT NULL,
+ value TEXT
+ );""")
+ c.execute("INSERT INTO config VALUES ( nextval('config_id_seq'), 'db_revision', '0')");
+ self.db.commit()
+
+ except psycopg2.ProgrammingError:
+ self.db.rollback()
+ print "Failed to create configuration table."
+ print "Can the projectB user CREATE TABLE?"
+ print ""
+ print "Aborting update."
+ sys.exit(-255)
+
+################################################################################
+
+ def get_db_rev(self):
+ global projectB
+
+ # We keep database revision info the config table
+ # Try and access it
+
+ try:
+ c = self.db.cursor()
+ q = c.execute("SELECT value FROM config WHERE name = 'db_revision';");
+ return c.fetchone()[0]
+
+ except psycopg2.ProgrammingError:
+ # Whoops .. no config table ...
+ self.db.rollback()
+ print "No configuration table found, assuming dak database revision to be pre-zero"
+ return -1
+
+################################################################################
+
+ def update_db(self):
+ # Ok, try and find the configuration table
+ print "Determining dak database revision ..."
+
+ try:
+ self.db = psycopg2.connect("dbname='" + Cnf["DB::Name"] + "' host='" + Cnf["DB::Host"] + "' port='" + str(Cnf["DB::Port"]) + "'")
+
+ except:
+ print "FATAL: Failed connect to database"
+ pass
+
+ database_revision = int(self.get_db_rev())
+
+ if database_revision == -1:
+ print "dak database schema predates update-db."
+ print ""
+ print "This script will attempt to upgrade it to the lastest, but may fail."
+ print "Please make sure you have a database backup handy. If you don't, press Ctrl-C now!"
+ print ""
+ print "Continuing in five seconds ..."
+ time.sleep(5)
+ print ""
+ print "Attempting to upgrade pre-zero database to zero"
+
+ self.update_db_to_zero()
+ database_revision = 0
+
+ print "dak database schema at " + str(database_revision)
+ print "dak version requires schema " + str(required_database_schema)
+
+ if database_revision == required_database_schema:
+ print "no updates required"
+ sys.exit(0)
+
+ for i in range (database_revision, required_database_schema):
+ print "updating databse schema from " + str(database_revision) + " to " + str(i+1)
+ dakdb = __import__("dakdb", globals(), locals(), ['update'+str(i+1)])
+ update_module = getattr(dakdb, "update"+str(i+1))
+ update_module.do_update(self)
+ database_revision =+ 1
+
+################################################################################
+
+ def init (self):
+ global Cnf, projectB
+
+ Cnf = utils.get_conf()
+ arguments = [('h', "help", "Update-DB::Options::Help")]
+ for i in [ "help" ]:
+ if not Cnf.has_key("Update-DB::Options::%s" % (i)):
+ Cnf["Update-DB::Options::%s" % (i)] = ""
+
+ arguments = apt_pkg.ParseCommandLine(Cnf, arguments, sys.argv)
+
+ options = Cnf.SubTree("Update-DB::Options")
+ if options["Help"]:
+ usage()
+ elif arguments:
+ utils.warn("dak update-db takes no arguments.")
+ usage(exit_code=1)
+
+
+ self.update_db()
+
+ try:
+ lock_fd = os.open(Cnf["Dinstall::LockFile"], os.O_RDWR | os.O_CREAT)
+ fcntl.lockf(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
+ except IOError, e:
+ if errno.errorcode[e.errno] == 'EACCES' or errno.errorcode[e.errno] == 'EAGAIN':
+ utils.fubar("Couldn't obtain lock; assuming another 'dak process-unchecked' is already running.")
+
+
+################################################################################
+
+if __name__ == '__main__':
+ app = UpdateDB()
+ app.init()
+
+def main():
+ app = UpdateDB()
+ app.init()
OUT=$(mktemp)
cp "$BYHAND" "$DESTKR"
-dak import-keyring --generate-users "dm:%s" "$DESTKR" >$OUT
+dak import-keyring -D --generate-users "%s" "$DESTKR" >$OUT
if [ -s "$OUT" ]; then
/usr/sbin/sendmail -odq -oi -t <<EOF