5 Multi-archive support; convert policy and build queues to regular suites
7 @contact: Debian FTP Master <ftpmaster@debian.org>
8 @copyright: 2012 Ansgar Burchardt <ansgar@debian.org>
9 @license: GNU General Public License version 2 or later
12 # This program is free software; you can redistribute it and/or modify
13 # it under the terms of the GNU General Public License as published by
14 # the Free Software Foundation; either version 2 of the License, or
15 # (at your option) any later version.
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # GNU General Public License for more details.
22 # You should have received a copy of the GNU General Public License
23 # along with this program; if not, write to the Free Software
24 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 ################################################################################
29 from daklib.dak_exceptions import DBUpdateError
30 from daklib.config import Config
34 ################################################################################
36 def _track_files_per_archive(cnf, c):
37 c.execute("SELECT id FROM archive")
38 (archive_id,) = c.fetchone()
40 if c.fetchone() is not None:
41 raise DBUpdateError("Cannot automatically upgrade from installation with multiple archives.")
43 c.execute("""CREATE TABLE files_archive_map (
44 file_id INT NOT NULL REFERENCES files(id),
45 archive_id INT NOT NULL REFERENCES archive(id),
46 component_id INT NOT NULL REFERENCES component(id),
47 last_used TIMESTAMP DEFAULT NULL,
48 created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
49 PRIMARY KEY (file_id, archive_id, component_id)
52 c.execute("""INSERT INTO files_archive_map (file_id, archive_id, component_id)
53 SELECT f.id, %s, l.component
55 JOIN location l ON f.location = l.id""", (archive_id,))
57 c.execute("""UPDATE files f SET filename = substring(f.filename FROM '/(.*)')
58 FROM location l, component c
59 WHERE f.location = l.id AND l.component = c.id
60 AND f.filename LIKE c.name || '/%'""")
62 # NOTE: The location table would need these changes, but we drop it later
64 #c.execute("""UPDATE location l SET path = path || c.name || '/'
66 # WHERE l.component = c.id
67 # AND l.path NOT LIKE '%/' || c.name || '/'""")
69 c.execute("DROP VIEW IF EXISTS binfiles_suite_component_arch")
70 c.execute("ALTER TABLE files DROP COLUMN location")
71 c.execute("DROP TABLE location")
73 def _convert_policy_queues(cnf, c):
74 base = cnf['Dir::Base']
75 new_path = os.path.join(base, 'new')
76 policy_path = os.path.join(base, 'policy')
78 # Forget changes in (old) policy queues so they can be processed again.
79 c.execute("DROP TABLE IF EXISTS build_queue_policy_files")
80 c.execute("DROP TABLE IF EXISTS build_queue_files")
81 c.execute("DROP TABLE IF EXISTS changes_pending_binaries")
82 c.execute("DROP TABLE IF EXISTS changes_pending_source_files")
83 c.execute("DROP TABLE IF EXISTS changes_pending_source")
84 c.execute("DROP TABLE IF EXISTS changes_pending_files_map")
85 c.execute("DROP TABLE IF EXISTS changes_pending_files")
86 c.execute("DROP TABLE IF EXISTS changes_pool_files")
87 c.execute("DELETE FROM changes WHERE in_queue IS NOT NULL")
89 # newstage and unchecked are no longer queues
91 DELETE FROM policy_queue
92 WHERE queue_name IN ('newstage', 'unchecked')
95 # Create archive for NEW
96 c.execute("INSERT INTO archive (name, description, path, tainted, use_morgue, mode) VALUES ('new', 'new queue', %s, 't', 'f', '0640') RETURNING (id)", (new_path,))
97 (new_archive_id,) = c.fetchone()
99 # Create archive for policy queues
100 c.execute("INSERT INTO archive (name, description, path, use_morgue) VALUES ('policy', 'policy queues', %s, 'f') RETURNING (id)", (policy_path,))
101 (archive_id,) = c.fetchone()
103 # Add suites for policy queues
106 (archive_id, suite_name, origin, label, description, signingkeys)
108 %s, queue_name, origin, label, releasedescription, NULLIF(ARRAY[signingkey], ARRAY[NULL])
110 WHERE queue_name NOT IN ('unchecked')
113 # move NEW to its own archive
114 c.execute("UPDATE suite SET archive_id=%s WHERE suite_name IN ('byhand', 'new')", (new_archive_id,))
116 c.execute("""ALTER TABLE policy_queue
119 DROP COLUMN releasedescription,
120 DROP COLUMN signingkey,
121 DROP COLUMN stay_of_execution,
123 ADD COLUMN suite_id INT REFERENCES suite(id)
126 c.execute("UPDATE policy_queue pq SET suite_id=s.id FROM suite s WHERE s.suite_name = pq.queue_name")
127 c.execute("ALTER TABLE policy_queue ALTER COLUMN suite_id SET NOT NULL")
129 c.execute("""INSERT INTO suite_architectures (suite, architecture)
130 SELECT pq.suite_id, sa.architecture
132 JOIN suite ON pq.id = suite.policy_queue_id
133 JOIN suite_architectures sa ON suite.id = sa.suite
134 WHERE pq.queue_name NOT IN ('byhand', 'new')
135 GROUP BY pq.suite_id, sa.architecture""")
137 # We only add architectures from suite_architectures to only add
138 # arches actually in use. It's not too important to have the
139 # right set of arches for policy queues anyway unless you want
140 # to generate Packages indices.
141 c.execute("""INSERT INTO suite_architectures (suite, architecture)
142 SELECT DISTINCT pq.suite_id, sa.architecture
143 FROM policy_queue pq, suite_architectures sa
144 WHERE pq.queue_name IN ('byhand', 'new')""")
146 c.execute("""CREATE TABLE policy_queue_upload (
147 id SERIAL NOT NULL PRIMARY KEY,
148 policy_queue_id INT NOT NULL REFERENCES policy_queue(id),
149 target_suite_id INT NOT NULL REFERENCES suite(id),
150 changes_id INT NOT NULL REFERENCES changes(id),
151 source_id INT REFERENCES source(id),
152 UNIQUE (policy_queue_id, target_suite_id, changes_id)
155 c.execute("""CREATE TABLE policy_queue_upload_binaries_map (
156 policy_queue_upload_id INT REFERENCES policy_queue_upload(id) ON DELETE CASCADE,
157 binary_id INT REFERENCES binaries(id),
158 PRIMARY KEY (policy_queue_upload_id, binary_id)
162 CREATE TABLE policy_queue_byhand_file (
163 id SERIAL NOT NULL PRIMARY KEY,
164 upload_id INT NOT NULL REFERENCES policy_queue_upload(id),
165 filename TEXT NOT NULL,
166 processed BOOLEAN NOT NULL DEFAULT 'f'
169 c.execute("""ALTER TABLE changes
170 DROP COLUMN in_queue,
171 DROP COLUMN approved_for
174 def _convert_build_queues(cnf, c):
175 base = cnf['Dir::Base']
176 build_queue_path = os.path.join(base, 'build-queues')
178 c.execute("INSERT INTO archive (name, description, path, tainted, use_morgue) VALUES ('build-queues', 'build queues', %s, 't', 'f') RETURNING id", [build_queue_path])
179 archive_id, = c.fetchone()
181 c.execute("ALTER TABLE build_queue ADD COLUMN suite_id INT REFERENCES suite(id)")
185 (archive_id, suite_name, origin, label, description, signingkeys, notautomatic)
187 %s, queue_name, origin, label, releasedescription, NULLIF(ARRAY[signingkey], ARRAY[NULL]), notautomatic
190 c.execute("UPDATE build_queue bq SET suite_id=(SELECT id FROM suite s WHERE s.suite_name = bq.queue_name)")
191 c.execute("ALTER TABLE build_queue ALTER COLUMN suite_id SET NOT NULL")
193 c.execute("""INSERT INTO suite_architectures (suite, architecture)
194 SELECT bq.suite_id, sa.architecture
196 JOIN suite_build_queue_copy sbqc ON bq.id = sbqc.build_queue_id
197 JOIN suite ON sbqc.suite = suite.id
198 JOIN suite_architectures sa ON suite.id = sa.suite
199 GROUP BY bq.suite_id, sa.architecture""")
201 c.execute("""ALTER TABLE build_queue
203 DROP COLUMN copy_files,
206 DROP COLUMN releasedescription,
207 DROP COLUMN signingkey,
208 DROP COLUMN notautomatic""")
214 if 'Dir::Base' not in cnf:
216 MANUAL UPGRADE INSTRUCTIONS
217 ===========================
219 This database update will convert policy and build queues to regular suites.
220 For these archives will be created under Dir::Base:
223 policy queues: <base>/policy
224 build queues: <base>/build-queues
226 Please add Dir::Base to dak.conf and try the update again. Once the database
227 upgrade is finished, you will have to reprocess all uploads currently in
228 policy queues: just move them back to unchecked manually.
230 raise DBUpdateError("Please update dak.conf and try again.")
234 _track_files_per_archive(cnf, c)
235 _convert_policy_queues(cnf, c)
236 _convert_build_queues(cnf, c)
238 c.execute("UPDATE config SET value = '75' WHERE name = 'db_revision'")
241 except psycopg2.ProgrammingError as msg:
243 raise DBUpdateError('Unable to apply sick update 75, rollback issued. Error message : %s' % (str(msg)))