X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=dak%2Fdakdb%2Fupdate83.py;fp=dak%2Fdakdb%2Fupdate83.py;h=f0707d582349b4436c432890b23aba028357659b;hb=707a89a3b86961755a99cb9e1a0a5f23690f9529;hp=0000000000000000000000000000000000000000;hpb=6f5a4716955f6370dc740b62c907d0c0e83735be;p=dak.git diff --git a/dak/dakdb/update83.py b/dak/dakdb/update83.py new file mode 100644 index 00000000..f0707d58 --- /dev/null +++ b/dak/dakdb/update83.py @@ -0,0 +1,219 @@ +#!/usr/bin/env python +# coding=utf8 + +""" +switch to new ACL implementation and add pre-suite NEW + +@contact: Debian FTP Master +@copyright: 2012 Ansgar Burchardt +@license: GNU General Public License version 2 or later +""" + +# 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 + +################################################################################ + +import psycopg2 +from daklib.dak_exceptions import DBUpdateError +from daklib.config import Config + +statements = [ +"""ALTER TABLE suite ADD COLUMN new_queue_id INT REFERENCES policy_queue(id)""", + +"""CREATE TABLE acl ( + id SERIAL PRIMARY KEY NOT NULL, + name TEXT NOT NULL, + is_global BOOLEAN NOT NULL DEFAULT 'f', + + match_fingerprint BOOLEAN NOT NULL DEFAULT 'f', + match_keyring_id INTEGER REFERENCES keyrings(id), + + allow_new BOOLEAN NOT NULL DEFAULT 'f', + allow_source BOOLEAN NOT NULL DEFAULT 'f', + allow_binary BOOLEAN NOT NULL DEFAULT 'f', + allow_binary_all BOOLEAN NOT NULL DEFAULT 'f', + allow_binary_only BOOLEAN NOT NULL DEFAULT 'f', + allow_hijack BOOLEAN NOT NULL DEFAULT 'f', + allow_per_source BOOLEAN NOT NULL DEFAULT 'f', + deny_per_source BOOLEAN NOT NULL DEFAULT 'f' + )""", + +"""CREATE TABLE acl_architecture_map ( + acl_id INTEGER NOT NULL REFERENCES acl(id) ON DELETE CASCADE, + architecture_id INTEGER NOT NULL REFERENCES architecture(id) ON DELETE CASCADE, + PRIMARY KEY (acl_id, architecture_id) + )""", + +"""CREATE TABLE acl_fingerprint_map ( + acl_id INTEGER NOT NULL REFERENCES acl(id) ON DELETE CASCADE, + fingerprint_id INTEGER NOT NULL REFERENCES fingerprint(id) ON DELETE CASCADE, + PRIMARY KEY (acl_id, fingerprint_id) + )""", + +"""CREATE TABLE acl_per_source ( + acl_id INTEGER NOT NULL REFERENCES acl(id) ON DELETE CASCADE, + fingerprint_id INTEGER NOT NULL REFERENCES fingerprint(id) ON DELETE CASCADE, + source TEXT NOT NULL, + reason TEXT, + PRIMARY KEY (acl_id, fingerprint_id, source) + )""", + +"""CREATE TABLE suite_acl_map ( + suite_id INTEGER NOT NULL REFERENCES suite(id) ON DELETE CASCADE, + acl_id INTEGER NOT NULL REFERENCES acl(id), + PRIMARY KEY (suite_id, acl_id) + )""", +] + +################################################################################ + +def get_buildd_acl_id(c, keyring_id): + c.execute(""" + SELECT 'buildd-' || STRING_AGG(a.arch_string, '+' ORDER BY a.arch_string) + FROM keyring_acl_map kam + JOIN architecture a ON kam.architecture_id = a.id + WHERE kam.keyring_id = %(keyring_id)s + """, {'keyring_id': keyring_id}) + acl_name, = c.fetchone() + + c.execute('SELECT id FROM acl WHERE name = %(acl_name)s', {'acl_name': acl_name}) + row = c.fetchone() + if row is not None: + return row[0] + + c.execute(""" + INSERT INTO acl + ( name, allow_new, allow_source, allow_binary, allow_binary_all, allow_binary_only, allow_hijack) + VALUES (%(acl_name)s, 't', 'f', 't', 'f', 't', 't') + RETURNING id""", {'acl_name': acl_name}) + acl_id, = c.fetchone() + + c.execute("""INSERT INTO acl_architecture_map (acl_id, architecture_id) + SELECT %(acl_id)s, architecture_id + FROM keyring_acl_map + WHERE keyring_id = %(keyring_id)s""", + {'acl_id': acl_id, 'keyring_id': keyring_id}) + + return acl_id + +def get_acl_id(c, acl_dd, acl_dm, keyring_id, source_acl_id, binary_acl_id): + c.execute('SELECT access_level FROM source_acl WHERE id = %(source_acl_id)s', {'source_acl_id': source_acl_id}) + row = c.fetchone() + if row is not None: + source_acl = row[0] + else: + source_acl = None + + c.execute('SELECT access_level FROM binary_acl WHERE id = %(binary_acl_id)s', {'binary_acl_id': binary_acl_id}) + row = c.fetchone() + if row is not None: + binary_acl = row[0] + else: + binary_acl = None + + if source_acl == 'full' and binary_acl == 'full': + return acl_dd + elif source_acl == 'dm' and binary_acl == 'full': + return acl_dm + elif source_acl is None and binary_acl == 'map': + return get_buildd_acl_id(c, keyring_id) + + raise Exception('Cannot convert ACL combination automatically: binary_acl={0}, source_acl={1}'.format(binary_acl, source_acl)) + +def do_update(self): + print __doc__ + try: + cnf = Config() + + c = self.db.cursor() + + for stmt in statements: + c.execute(stmt) + + c.execute(""" + INSERT INTO acl + (name, allow_new, allow_source, allow_binary, allow_binary_all, allow_binary_only, allow_hijack) + VALUES ('dd', 't', 't', 't', 't', 't', 't') + RETURNING id""") + acl_dd, = c.fetchone() + + c.execute(""" + INSERT INTO acl + (name, allow_new, allow_source, allow_binary, allow_binary_all, allow_binary_only, allow_per_source, allow_hijack) + VALUES ('dm', 'f', 't', 't', 't', 'f', 't', 'f') + RETURNING id""") + acl_dm, = c.fetchone() + + # convert per-fingerprint ACLs + + c.execute('ALTER TABLE fingerprint ADD COLUMN acl_id INTEGER REFERENCES acl(id)') + c.execute("""SELECT id, keyring, source_acl_id, binary_acl_id + FROM fingerprint + WHERE source_acl_id IS NOT NULL OR binary_acl_id IS NOT NULL""") + for fingerprint_id, keyring_id, source_acl_id, binary_acl_id in c.fetchall(): + acl_id = get_acl_id(c, acl_dd, acl_dm, keyring_id, source_acl_id, binary_acl_id) + c.execute('UPDATE fingerprint SET acl_id = %(acl_id)s WHERE id = %(fingerprint_id)s', + {'acl_id': acl_id, 'fingerprint_id': fingerprint_id}) + c.execute("""ALTER TABLE fingerprint + DROP COLUMN source_acl_id, + DROP COLUMN binary_acl_id, + DROP COLUMN binary_reject""") + + # convert per-keyring ACLs + c.execute('ALTER TABLE keyrings ADD COLUMN acl_id INTEGER REFERENCES acl(id)') + c.execute('SELECT id, default_source_acl_id, default_binary_acl_id FROM keyrings') + for keyring_id, source_acl_id, binary_acl_id in c.fetchall(): + acl_id = get_acl_id(c, acl_dd, acl_dm, keyring_id, source_acl_id, binary_acl_id) + c.execute('UPDATE keyrings SET acl_id = %(acl_id)s WHERE id = %(keyring_id)s', + {'acl_id': acl_id, 'keyring_id': keyring_id}) + c.execute("""ALTER TABLE keyrings + DROP COLUMN default_source_acl_id, + DROP COLUMN default_binary_acl_id, + DROP COLUMN default_binary_reject""") + + c.execute("DROP TABLE keyring_acl_map") + c.execute("DROP TABLE binary_acl_map") + c.execute("DROP TABLE binary_acl") + c.execute("DROP TABLE source_acl") + + # convert upload blocks + c.execute(""" + INSERT INTO acl + ( name, is_global, allow_new, allow_source, allow_binary, allow_binary_all, allow_hijack, allow_binary_only, deny_per_source) + VALUES ('blocks', 't', 't', 't', 't', 't', 't', 't', 't') + RETURNING id""") + acl_block, = c.fetchone() + c.execute("SELECT source, fingerprint_id, reason FROM upload_blocks") + for source, fingerprint_id, reason in c.fetchall(): + if fingerprint_id is None: + raise Exception( + "ERROR: upload blocks based on uid are no longer supported\n" + "=========================================================\n" + "\n" + "dak now only supports upload blocks based on fingerprints. Please remove\n" + "any uid-specific block by running\n" + " DELETE FROM upload_blocks WHERE fingerprint_id IS NULL\n" + "and try again.") + + c.execute('INSERT INTO acl_match_source_map (acl_id, fingerprint_id, source, reason) VALUES (%(acl_id)s, %(fingerprint_id)s, %(source)s, %(reason)s)', + {'acl_id': acl_block, 'fingerprint_id': fingerprint_id, 'source': source, 'reason': reason}) + c.execute("DROP TABLE upload_blocks") + + c.execute("UPDATE config SET value = '83' WHERE name = 'db_revision'") + self.db.commit() + + except psycopg2.ProgrammingError as msg: + self.db.rollback() + raise DBUpdateError('Unable to apply sick update 83, rollback issued. Error message: {0}'.format(msg))