Package dak :: Package dakdb :: Module update83
[hide private]
[frames] | no frames]

Source Code for Module dak.dakdb.update83

  1  """ 
  2  switch to new ACL implementation and add pre-suite NEW 
  3   
  4  @contact: Debian FTP Master <ftpmaster@debian.org> 
  5  @copyright: 2012 Ansgar Burchardt <ansgar@debian.org> 
  6  @license: GNU General Public License version 2 or later 
  7  """ 
  8   
  9  # This program is free software; you can redistribute it and/or modify 
 10  # it under the terms of the GNU General Public License as published by 
 11  # the Free Software Foundation; either version 2 of the License, or 
 12  # (at your option) any later version. 
 13   
 14  # This program is distributed in the hope that it will be useful, 
 15  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 16  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 17  # GNU General Public License for more details. 
 18   
 19  # You should have received a copy of the GNU General Public License 
 20  # along with this program; if not, write to the Free Software 
 21  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 22   
 23  ################################################################################ 
 24   
 25  import psycopg2 
 26   
 27  from daklib.dak_exceptions import DBUpdateError 
 28   
 29  statements = [ 
 30      """ALTER TABLE suite ADD COLUMN new_queue_id INT REFERENCES policy_queue(id)""", 
 31      """CREATE TABLE acl ( 
 32      id SERIAL PRIMARY KEY NOT NULL, 
 33      name TEXT NOT NULL, 
 34      is_global BOOLEAN NOT NULL DEFAULT 'f', 
 35   
 36      match_fingerprint BOOLEAN NOT NULL DEFAULT 'f', 
 37      match_keyring_id INTEGER REFERENCES keyrings(id), 
 38   
 39      allow_new BOOLEAN NOT NULL DEFAULT 'f', 
 40      allow_source BOOLEAN NOT NULL DEFAULT 'f', 
 41      allow_binary BOOLEAN NOT NULL DEFAULT 'f', 
 42      allow_binary_all BOOLEAN NOT NULL DEFAULT 'f', 
 43      allow_binary_only BOOLEAN NOT NULL DEFAULT 'f', 
 44      allow_hijack BOOLEAN NOT NULL DEFAULT 'f', 
 45      allow_per_source BOOLEAN NOT NULL DEFAULT 'f', 
 46      deny_per_source BOOLEAN NOT NULL DEFAULT 'f' 
 47      )""", 
 48      """CREATE TABLE acl_architecture_map ( 
 49      acl_id INTEGER NOT NULL REFERENCES acl(id) ON DELETE CASCADE, 
 50      architecture_id INTEGER NOT NULL REFERENCES architecture(id) ON DELETE CASCADE, 
 51      PRIMARY KEY (acl_id, architecture_id) 
 52      )""", 
 53      """CREATE TABLE acl_fingerprint_map ( 
 54      acl_id INTEGER NOT NULL REFERENCES acl(id) ON DELETE CASCADE, 
 55      fingerprint_id INTEGER NOT NULL REFERENCES fingerprint(id) ON DELETE CASCADE, 
 56      PRIMARY KEY (acl_id, fingerprint_id) 
 57      )""", 
 58      """CREATE TABLE acl_per_source ( 
 59      acl_id INTEGER NOT NULL REFERENCES acl(id) ON DELETE CASCADE, 
 60      fingerprint_id INTEGER NOT NULL REFERENCES fingerprint(id) ON DELETE CASCADE, 
 61      source TEXT NOT NULL, 
 62      reason TEXT, 
 63      PRIMARY KEY (acl_id, fingerprint_id, source) 
 64      )""", 
 65      """CREATE TABLE suite_acl_map ( 
 66      suite_id INTEGER NOT NULL REFERENCES suite(id) ON DELETE CASCADE, 
 67      acl_id INTEGER NOT NULL REFERENCES acl(id), 
 68      PRIMARY KEY (suite_id, acl_id) 
 69      )""", 
 70  ] 
 71   
 72  ################################################################################ 
 73   
 74   
75 -def get_buildd_acl_id(c, keyring_id):
76 c.execute( 77 """ 78 SELECT 'buildd-' || STRING_AGG(a.arch_string, '+' ORDER BY a.arch_string) 79 FROM keyring_acl_map kam 80 JOIN architecture a ON kam.architecture_id = a.id 81 WHERE kam.keyring_id = %(keyring_id)s 82 """, 83 {"keyring_id": keyring_id}, 84 ) 85 (acl_name,) = c.fetchone() 86 87 c.execute("SELECT id FROM acl WHERE name = %(acl_name)s", {"acl_name": acl_name}) 88 row = c.fetchone() 89 if row is not None: 90 return row[0] 91 92 c.execute( 93 """ 94 INSERT INTO acl 95 ( name, allow_new, allow_source, allow_binary, allow_binary_all, allow_binary_only, allow_hijack) 96 VALUES (%(acl_name)s, 't', 'f', 't', 'f', 't', 't') 97 RETURNING id""", 98 {"acl_name": acl_name}, 99 ) 100 (acl_id,) = c.fetchone() 101 102 c.execute( 103 """INSERT INTO acl_architecture_map (acl_id, architecture_id) 104 SELECT %(acl_id)s, architecture_id 105 FROM keyring_acl_map 106 WHERE keyring_id = %(keyring_id)s""", 107 {"acl_id": acl_id, "keyring_id": keyring_id}, 108 ) 109 110 return acl_id
111 112
113 -def get_acl_id(c, acl_dd, acl_dm, keyring_id, source_acl_id, binary_acl_id):
114 c.execute( 115 "SELECT access_level FROM source_acl WHERE id = %(source_acl_id)s", 116 {"source_acl_id": source_acl_id}, 117 ) 118 row = c.fetchone() 119 if row is not None: 120 source_acl = row[0] 121 else: 122 source_acl = None 123 124 c.execute( 125 "SELECT access_level FROM binary_acl WHERE id = %(binary_acl_id)s", 126 {"binary_acl_id": binary_acl_id}, 127 ) 128 row = c.fetchone() 129 if row is not None: 130 binary_acl = row[0] 131 else: 132 binary_acl = None 133 134 if source_acl == "full" and binary_acl == "full": 135 return acl_dd 136 elif source_acl == "dm" and binary_acl == "full": 137 return acl_dm 138 elif source_acl is None and binary_acl == "map": 139 return get_buildd_acl_id(c, keyring_id) 140 141 raise Exception( 142 "Cannot convert ACL combination automatically: binary_acl={0}, source_acl={1}".format( 143 binary_acl, source_acl 144 ) 145 )
146 147
148 -def do_update(self):
149 print(__doc__) 150 try: 151 c = self.db.cursor() 152 153 for stmt in statements: 154 c.execute(stmt) 155 156 c.execute( 157 """ 158 INSERT INTO acl 159 (name, allow_new, allow_source, allow_binary, allow_binary_all, allow_binary_only, allow_hijack) 160 VALUES ('dd', 't', 't', 't', 't', 't', 't') 161 RETURNING id""" 162 ) 163 (acl_dd,) = c.fetchone() 164 165 c.execute( 166 """ 167 INSERT INTO acl 168 (name, allow_new, allow_source, allow_binary, allow_binary_all, allow_binary_only, allow_per_source, allow_hijack) 169 VALUES ('dm', 'f', 't', 't', 't', 'f', 't', 'f') 170 RETURNING id""" 171 ) 172 (acl_dm,) = c.fetchone() 173 174 # convert per-fingerprint ACLs 175 176 c.execute( 177 "ALTER TABLE fingerprint ADD COLUMN acl_id INTEGER REFERENCES acl(id)" 178 ) 179 c.execute( 180 """SELECT id, keyring, source_acl_id, binary_acl_id 181 FROM fingerprint 182 WHERE source_acl_id IS NOT NULL OR binary_acl_id IS NOT NULL""" 183 ) 184 for fingerprint_id, keyring_id, source_acl_id, binary_acl_id in c.fetchall(): 185 acl_id = get_acl_id( 186 c, acl_dd, acl_dm, keyring_id, source_acl_id, binary_acl_id 187 ) 188 c.execute( 189 "UPDATE fingerprint SET acl_id = %(acl_id)s WHERE id = %(fingerprint_id)s", 190 {"acl_id": acl_id, "fingerprint_id": fingerprint_id}, 191 ) 192 c.execute( 193 """ALTER TABLE fingerprint 194 DROP COLUMN source_acl_id, 195 DROP COLUMN binary_acl_id, 196 DROP COLUMN binary_reject""" 197 ) 198 199 # convert per-keyring ACLs 200 c.execute("ALTER TABLE keyrings ADD COLUMN acl_id INTEGER REFERENCES acl(id)") 201 c.execute( 202 "SELECT id, default_source_acl_id, default_binary_acl_id FROM keyrings" 203 ) 204 for keyring_id, source_acl_id, binary_acl_id in c.fetchall(): 205 acl_id = get_acl_id( 206 c, acl_dd, acl_dm, keyring_id, source_acl_id, binary_acl_id 207 ) 208 c.execute( 209 "UPDATE keyrings SET acl_id = %(acl_id)s WHERE id = %(keyring_id)s", 210 {"acl_id": acl_id, "keyring_id": keyring_id}, 211 ) 212 c.execute( 213 """ALTER TABLE keyrings 214 DROP COLUMN default_source_acl_id, 215 DROP COLUMN default_binary_acl_id, 216 DROP COLUMN default_binary_reject""" 217 ) 218 219 c.execute("DROP TABLE keyring_acl_map") 220 c.execute("DROP TABLE binary_acl_map") 221 c.execute("DROP TABLE binary_acl") 222 c.execute("DROP TABLE source_acl") 223 224 # convert upload blocks 225 c.execute( 226 """ 227 INSERT INTO acl 228 ( name, is_global, allow_new, allow_source, allow_binary, allow_binary_all, allow_hijack, allow_binary_only, deny_per_source) 229 VALUES ('blocks', 't', 't', 't', 't', 't', 't', 't', 't') 230 RETURNING id""" 231 ) 232 (acl_block,) = c.fetchone() 233 c.execute("SELECT source, fingerprint_id, reason FROM upload_blocks") 234 for source, fingerprint_id, reason in c.fetchall(): 235 if fingerprint_id is None: 236 raise Exception( 237 "ERROR: upload blocks based on uid are no longer supported\n" 238 "=========================================================\n" 239 "\n" 240 "dak now only supports upload blocks based on fingerprints. Please remove\n" 241 "any uid-specific block by running\n" 242 " DELETE FROM upload_blocks WHERE fingerprint_id IS NULL\n" 243 "and try again." 244 ) 245 246 c.execute( 247 "INSERT INTO acl_match_source_map (acl_id, fingerprint_id, source, reason) VALUES (%(acl_id)s, %(fingerprint_id)s, %(source)s, %(reason)s)", 248 { 249 "acl_id": acl_block, 250 "fingerprint_id": fingerprint_id, 251 "source": source, 252 "reason": reason, 253 }, 254 ) 255 c.execute("DROP TABLE upload_blocks") 256 257 c.execute("UPDATE config SET value = '83' WHERE name = 'db_revision'") 258 self.db.commit() 259 260 except psycopg2.ProgrammingError as msg: 261 self.db.rollback() 262 raise DBUpdateError( 263 "Unable to apply sick update 83, rollback issued. Error message: {0}".format( 264 msg 265 ) 266 )
267